/** * 业务场景: * 微信小程序利用canvas生成海报分享图片 * 唯一一个不同点在于,要根据返回list算canvas的高度(也就是高度是不确定的,图片可以无限长) * */ // 页面结构 <block> <view class="dire-content" wx:if="{{postersShow}}" catchtouchmove="donMove"> <scroll-view scroll-y class="dire-scroll"> <canvas class="inviteCanvas" canvas-id="inviteCanvas" style="width:{{canvasWidth}}rpx;height:{{canvasHeight}}rpx;"> </canvas> <image class="canvasimg" src="{{canvasImg}}" style="width:630rpx;height:{{canvasHeight}}rpx"></image> </scroll-view> </view> <view class="create-poster-wbtn" bindtap="saveInviteCard" wx:if="{{postersShow}}">保存到手机</view> </block> const app = getApp(); var that; var articleApps = require('../../banyan/logics/articleApps'); var promise = require("../../vendor/lib/promise.min.js"); Page({ data: { resultList: [], img: "", showModal: false, // 遮罩层 showWeekly: false, // 分享 postersShow: false, // 生成海报 canWidth: Number, canHeight: Number }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { that = this; let wkid = options.wkid; // let wkid = 8; // let title = "生命周期函数--监听页面加载生命周期函数--监听页面加载" that.setData({ wkid: wkid, title: options.title // title: title }) that.getWeeklyList(wkid); // 扫码场景处理 var scene = options.scene ? decodeURIComponent(options.scene) : false; console.log(options); if (scene) { let param = scene.split(','); let wkidKey = param[0]; // let wkidValue = param[1]; if (param.length > 1 && wkidValue !== null) { that.getWeeklyList(wkidKey); } else { wx.switchTab({ url: '/pages/index/index', }); } } }, /** * 生命周期函数--监听页面显示 */ onShow: function () { that.setData({ resultList: [], img: "", showModal: false, showWeekly: false, postersShow: false, }) if (!app.globalData.userInfo) { app.getCurrentUser(res => { that.getWeeklyList(that.data.wkid) }, 2); } else { that.getWeeklyList(that.data.wkid) } }, // 加载页面数据 getWeeklyList(id) { let reqData = { wkid: id } articleApps.weeklyList({ data: reqData }, that, data => { that.setData({ resultList: data.list, img: data.qrcode }) that.dowloadImgFiles(that.data.img); }); }, // 显示分享弹框 share() { that.setData({ showModal: true, showWeekly: true }) }, // 显示canvas海报 posters() { that.setData({ showModal: true, showWeekly: false, postersShow: true, }) that.getCanvasSize(); that.drawInviteCard(); }, // 关闭分享弹框 unShow() { that.setData({ showModal: false, showWeekly: false, postersShow: false }) }, // 下载图片 downloadImage: function (url) { var ulpromise = new promise(function (resolve, reject) { wx.downloadFile({ url: url, success: function (res) { resolve(res); }, fail: function (e) { reject(e); console.log('download image failed'); } }); }); return ulpromise; }, // 下载图片到缓存 dowloadImgFiles(img) { try { var imgArr = []; that.downloadImage(img).then(function (res) { imgArr.push(res.tempFilePath); that.data.imgArr = imgArr; return that.downloadImage(img); }.bind(this)).then(function (res) { that.getCanvasSize(); that.drawInviteCard(); }); } catch (err) { console.log(err) that.setData({ loaded: true, }); app.ulToast('加载失败', 0); } }, // 获取画布宽高 getCanvasSize() { wx.getSystemInfo({ success(res) { that.setData({ canWidth: res.windowWidth, canHeight: res.windowHeight }) } }); }, // 绘制邀请卡画布 drawInviteCard(callback) { let imgArr = that.data.imgArr; let con = that.data.resultList; // 文本list添加序号 for (let j = 0; j < con.length; j++) { con[j].index = j; } let ctx = wx.createCanvasContext('inviteCanvas'); // 设置单个主体内容高度 let _height = 190; // 绘制白色背景 ctx.setFillStyle('#fff'); ctx.fillRect(0, 0, that.changeRpx(630), (that.changeRpx(_height) * con.length + that.changeRpx(600))); // ctx.clip(); //剪切矩形后 开始画画 ctx.fill(); that.setData({ canvasWidth: that.changeRpx(630) * 2, // canvasHeight: Math.round((that.changeRpx(_height) * con.length + that.changeRpx(680)) * 2) canvasHeight: (95 * con.length + 300) * 2 }) // 文本标题 // let title = "本周报告更新目录"; let title = that.data.title; ctx.beginPath(); ctx.setFillStyle('#000'); ctx.font = "bold 16px Arial"; // ctx.fillText(title, that.changeRpx(60), that.changeRpx(104)); that.drawText(ctx, title, that.changeRpx(60), that.changeRpx(104), that.changeRpx(530), that.changeRpx(32), 1); // 以下为研究中心本期更新内容 let title_two = "以下为研究中心本期更新内容"; ctx.beginPath(); ctx.setFontSize(that.changeRpx(28)); ctx.setFillStyle('#747474'); ctx.font = "nobold 14px Arial"; ctx.fillText(title_two, that.changeRpx(60), that.changeRpx(150)); // canvas主体内容 for (let i = 0; i < con.length; i++) { // 标题 let con_title = con[i].index + 1 + '.' + con[i].Title; ctx.beginPath(); ctx.setFillStyle('#000'); ctx.font = "bold 16px Arial"; that.drawText(ctx, con_title, that.changeRpx(60), that.changeRpx(_height) * i + that.changeRpx(260), that.changeRpx(530), that.changeRpx(40), 2); // 内容 let con_content = con[i].Summary; ctx.beginPath(); ctx.setFillStyle('#747474'); ctx.font = "nobold 14px Arial"; // 判断10的用意是因为第二行是摘要,要缩略与标题保持一致 if (i < 10) { that.drawText(ctx, con_content, that.changeRpx(90), that.changeRpx(_height) * i + that.changeRpx(340), that.changeRpx(470), that.changeRpx(32), 3); } else { that.drawText(ctx, con_content, that.changeRpx(110), that.changeRpx(_height) * i + that.changeRpx(340), that.changeRpx(470), that.changeRpx(32), 3); } // // 设置文本之间距离 // let distance = that.changeRpx(160); // // 线框 // ctx.moveTo(that.changeRpx(40), that.changeRpx(200) + i * distance); // ctx.lineTo(that.changeRpx(600), that.changeRpx(200) + i * distance); // ctx.lineTo(that.changeRpx(600), that.changeRpx(340) + i * distance); // ctx.lineTo(that.changeRpx(40), that.changeRpx(340) + i * distance); // ctx.lineTo(that.changeRpx(40), that.changeRpx(340) + i * distance); // ctx.closePath(); //闭合路径 // ctx.lineWidth = 1; // ctx.strokeStyle = '#F6F6F6'; // ctx.stroke(); } // 小程序二维码 ctx.beginPath(); ctx.drawImage(imgArr[0], that.changeRpx(230), ((that.changeRpx(_height) * con.length) + that.changeRpx(260)), that.changeRpx(172), that.changeRpx(172)); ctx.draw(); setTimeout(() => { that.downloadCanvasImg(0, 0, that.changeRpx(630), (that.changeRpx(_height) * con.length + that.changeRpx(600)), (that.changeRpx(630) * 2), ((that.changeRpx(_height) * con.length + that.changeRpx(630)) * 2)); }, 500); }, /** * * @method downloadCanvasImg 把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径 * @param { Number } x 画布区域的左上角横坐标 * @param { Number } y 画布区域的左上角纵坐标 * @param { Number } width 画布区域的宽度 * @param { Number } height 画布区域的高度 * @param { Number } destWidth 图片的宽度 * @param { Number } destHeight 图片的高度 */ downloadCanvasImg(x, y, width, height, destWidth, destHeight) { wx.canvasToTempFilePath({ x: x, y: y, width: width, height: height, destWidth: destWidth, destHeight: destHeight, canvasId: 'inviteCanvas', fileType: 'jpg', quality: 2, success(res) { console.log(res) let filePath = res.tempFilePath; that.setData({ canvasImg: filePath }) }, fail(err) { console.log(err); } }); }, /** * * @method centerText canvas文本居中 * @param {*} ctx canvas对象 * @param {*} text 文字 * @param {*} fontSzie 字体 * @param {*} color 颜色 * @param {*} height 绘制高度 */ centerText(ctx, text, fontSzie, color, height) { ctx.font = fontSzie; ctx.fillStyle = color; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText(text, ctx.width / 2, height); }, /** * * @method drawText canvas文本超过隐藏 * @param {*} ctx canvas对象 * @param {*} text 文字 * @param {*} x X轴 * @param {*} y Y轴 * @param {*} maxWidth 文本宽度 * @param {*} lineHeight 行高 * @param {*} maxLine 显示行数 */ drawText(ctx, text, x, y, maxWidth, lineHeight, maxLine) { let arrText = text.split(''); let line = ''; let num = 1; for (let n = 0; n < arrText.length; n++) { let testLine = line + arrText[n]; let metrics = ctx.measureText(testLine); let testWidth = metrics.width; if (testWidth > maxWidth && n > 0) { if (maxLine != undefined && num >= maxLine) { ctx.fillText(line.substr(0, line.length - 1) + '...', x, y); return num; } num++; ctx.fillText(line, x, y); line = arrText[n]; y += lineHeight; } else { line = testLine; } } ctx.fillText(line, x, y); return num; }, // canvas圆角 // drawRoundRect() drawRoundRect(ctx, x, y, width, height, radius) { ctx.beginPath(); ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2); ctx.lineTo(width - radius + x, y); ctx.arc(width - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2); ctx.lineTo(width + x, height + y - radius); ctx.arc(width - radius + x, height - radius + y, radius, 0, Math.PI * 1 / 2); ctx.lineTo(radius + x, height + y); ctx.arc(radius + x, height - radius + y, radius, Math.PI * 1 / 2, Math.PI); ctx.closePath(); }, // 转换rpx单位为px changeRpx(rpx) { return rpx * that.data.canWidth / 750; }, // 保存图片 saveInviteCard(e) { app.saveCanvasToAlbum(e, that, res => { app.ulToast('保存成功', 1); that.setData({ showModal: false, showWeekly: false, postersShow: false }); }); }, })//