效果:
完整uniapp代码,兼容app、h5、小程序
<template> <view> <!-- 生成海报的点击事件 --> <view @click="generatePoster">点击分享</view> <!-- 生成海报的canvas --> <view class="my-canvas-box" @touchmove.stop.prevent v-show="show" @click="show = false"> <canvas class="my-canvas" canvas-id="myCanvas" @longpress.stop="saveSharePic"></canvas> <view class="canvas-tip">长按可保存海报</view> </view> </view> </template> <script> export default { data() { return { show: false, } }, methods: { // 生成海报 generatePoster() { // 这里是创建 canvas 绘图上下文 let context = uni.createCanvasContext('myCanvas'); // 这里可以根据自己的需求显示加载动画 uni.showToast({ title: '正在生成海报,请稍后', icon: 'none', duration: 3000 }); // 小程序码图片,下面可以放一个请求,来保存小程序码。然后赋值到qrImg这个变量上面 let qrImg = 'http://repo.bfw.wiki/bfwrepo/image/5f9e27c437f2a.png'; // 给整个canvas填充白色背景(这个如果不加上的话,在APP端生成的海报没有白色背景) context.setFillStyle('#ffffff'); context.fillRect(0, 0, 500, 900); context.draw(); // 绘制用户昵称 context.setFontSize(14); context.setFillStyle('#000000'); // 这里根据自己的项目填写用户昵称的字段 context.fillText('用户的昵称', 100, 48); context.setFontSize(12); context.setFillStyle('#999999'); context.fillText('的分享', 100, 68); // 绘制价格 context.setFontSize(18); context.setFillStyle('red'); context.fillText(`¥199`, 20, 366); // 绘制商品名称,这里是调用一个方法,按字符串长度进行分割换行。【可以做一个优化】 this.drawText("商品名称", 20, 379, context); // 绘制头像 uni.downloadFile({ url: 'http://repo.bfw.wiki/bfwrepo/image/60d41f5173b0d.png?x-oss-process=image/auto-orient,1/resize,m_fill,w_100,h_100,/quality,q_90', success: function(res) { context.save(); // 这个就是绘制圆形头像 context.beginPath(); context.arc(50, 50, 30, 0, 2 * Math.PI) context.clip(); context.drawImage(res.tempFilePath, 20, 20, 60, 60); context.restore(); context.draw(true); } }); // 绘制商品详情 uni.downloadFile({ url: 'http://repo.bfw.wiki/bfwrepo/image/60dd752ac3e0a.png', success: function(res) { context.drawImage(res.tempFilePath, 15, 92, 245, 245); context.draw(true); } }); // 绘制小程序码 uni.downloadFile({ // 这个qrImg就是上面获取的小程序码 url: qrImg, success: function(res) { context.drawImage(res.tempFilePath, 165, 360, 100, 100); context.draw(true); } }); // 绘制完成,让canvas显示【这里看自己项目,是否有loading动画】 this.show = true; }, // 商品名称文字换行 drawText(context, x, y, canvas) { let strArr = []; let n = 11; for (let i = 0, l = context.length; i < l / n; i++) { let a = context.slice(n * i, n * (i + 1)); strArr.push(a); } strArr.forEach((item, index) => { // 限制只能显示4行文字 if (index > 3) { return; } y += 20; canvas.setFontSize(12); canvas.setFillStyle('#333333'); canvas.fillText(item, x, y); }); }, // 长按保存生成的海报 saveSharePic() { uni.showModal({ title: '提示', content: '确定要保存分享海报吗?', success: function(res) { if (res.confirm) { // canvas生成图片 uni.canvasToTempFilePath({ // 这里修改保存的图片格式 fileType: 'jpg', canvasId: 'myCanvas', quality: 1, success: function(res) { // 保存带哦本地 uni.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success: function() { uni.showToast({ title: '保存海报成功', icon: 'none', duration: 3000 }); }, fail: function() { uni.showToast({ title: '保存海报失败', icon: 'none', duration: 3000 }); } }); } }); } } }); } } } </script> <style> .my-canvas-box { width: 750rpx; height: 100%; position: fixed; background-color: rgba(0, 0, 0, 0.6); z-index: 99; } .canvas-tip { color: #ffffff; font-size: 24rpx; margin-top: 30rpx; text-align: center; } /* #ifdef MP-WEIXIN */ .my-canvas { width: 550rpx; height: 950rpx; background-color: #ffffff; margin: 200rpx auto; } /* #endif */ /* #ifdef APP-PLUS || H5 */ .my-canvas { width: 550rpx; height: 950rpx; background-color: #ffffff; margin: 220rpx auto; } /* #endif */ </style>
网友回复