微信小程序分享海报开发总结

您所在的位置:网站首页 小程序制作海报 微信小程序分享海报开发总结

微信小程序分享海报开发总结

2023-08-15 15:19| 来源: 网络整理| 查看: 265

最近开发一个项目需要在微信小程序里合成海报图片,中间遇到过不少问题,记录一下以便日后查阅

效果展示

!

绘制流程简述 请求海报数据 加载图片 初始化canvas 绘制文字 绘制区块 微信小程序码获取 绘制图片 导出图片内容 小程序码解析 绘制关键点 Canvas 初始化

正常情况下,1px在屏幕上就显示1px,但是在高清屏幕上,这个情况就不一样了,以iPhone4S为例,它的devicePixelRatio为2,将看到100px的逻辑值等于200px的设备值。在元素的逻辑像素宽度上创建图像,当它们被绘制出来时,它们会被设备像素按比例放大,并且会变得模糊。解决这个问题的方法是创建按devicePixelRatio缩放的图像,然后使用CSS按相同的比例缩小.

image.png

canvas 的width 和 height控制元素位图的属性,如不设置默认为width=300,height=150

// 获取canvas function getCanvas() { return new Promise((resolve, reject) => { Taro.createSelectorQuery() .select('#myCanvas') .fields({ node: true, size: true }) .exec(res => { res ? resolve(res[0]) : reject(null); }); }); } /** * 初始化canvas并返回 ctx * * @param {Object} res * @returns {*} */ function setContext(res: Object): any { let {canvas, width, height} = res; const ctx = canvas.getContext('2d'); const dpr = Taro.getSystemInfoSync().pixelRatio; // 防止重复放大处理 if (canvas.width !== width * dpr) { // 设置画布绘画尺寸 = CSS尺寸 * 设备像素比率。 canvas.width = width * dpr; canvas.height = height * dpr; // 通过dpr缩放所有绘图操作 ctx.scale(dpr, dpr); } return ctx; } let {node: canvas, width, height} = await getCanvas(); let ctx = setContext({canvas, width, height}); // 绘制前先清除,以防被原有图案影响 ctx.clearRect(0, 0, width, height); ctx.fillStyle = '#ffffff'; 复制代码

canvas标签,微信对Canvas做了同层渲染的优化,特别注意不要将canvas标签放到子组件,必须放到page页,否则无法获取的canvas对象

复制代码 微信小程序码获取 接口 A: 适用于需要的码数量较少的业务场景 生成小程序码,可接受 path 参数较长,生成个数受限,数量限制见 注意事项,请谨慎使用。 接口 B:适用于需要的码数量极多的业务场景 生成小程序码,可接受页面参数较短,生成个数不受限。 接口 C:适用于需要的码数量较少的业务场景 生成二维码,可接受 path 参数较长,生成个数受限,数量限制见 注意事项。

我们使用的是接口B,需要注意的点,

scene参数只接收32的长度 小程序未发布时,page参数必须为空,scene=xxxx,才可以获取到二维码 接口返回的数据需要为base64格式方便canvas绘制时使用 图片绘制前获取 Taro.getImageInfo({ src: imgUrl }).than(res => { let { path } = res; let imgtag = canvas.createImage(); imgtag.src = path; imgtag.onload = res => { ctx.save(); ctx.drawImage(imgtag, 26, 615, 2 * 27, 2 * 27); ctx.restore(); }; }); 复制代码 图片裁剪 /** * 画圆 * * @export * @param {IDrawRound} options * @example * drawRound({ * ctx, * r: 19, * x: 22, * y: 15, * next() { * ctx.fillStyle = '#F5F5F5'; * ctx.fill(); * } * }); */ export function drawRound(options: IDrawRound) { let { ctx, r, x, y, next } = options; ctx.save(); // 保存之前的 let cx = x + r; // 圆弧坐标x let cy = y + r; // 圆弧坐标 y ctx.arc(cx, cy, r, 0, 2 * Math.PI); if (typeof next === 'function') { next(); } ctx.restore(); // 返回上一状态 } // 绘制圆形头像 drawRound({ ctx, r: 27, x: 26, y: 615, next() { ctx.clip(); ctx.drawImage(imgtag, 26, 615, 2 * 27, 2 * 27); // 画头像 } }); 复制代码 绘制圆角矩形 /** * 绘制圆角矩形,需自行填充颜色 * * @export * @param {IDrawRound} options * * @example * drawRoundRect({ * ctx, * r: 13, * x: 26, * y: 80, * w: 361, * h: 361, * next() { * ctx.clip(); * ctx.drawImage(imgtag, 26, 80, 361, 361); * } * }); */ export function drawRoundRect(options: IDrawRoundRect) { let {ctx, x, y, w, h, r, next} = options; ctx.save(); if (w < 2 * r) { r = w / 2; } if (h < 2 * r) { r = h / 2; } ctx.beginPath(); ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 3 / 2); ctx.lineTo(w - r + x, y); ctx.arc(w - r + x, r + y, r, Math.PI * 3 / 2, Math.PI * 2); ctx.lineTo(w + x, h + y - r); ctx.arc(w - r + x, h - r + y, r, 0, Math.PI * 1 / 2); ctx.lineTo(r + x, h + y); ctx.arc(r + x, h - r + y, r, Math.PI * 1 / 2, Math.PI); ctx.closePath(); if (typeof next === 'function') { next(); } ctx.restore(); // 返回上一状态 } // 底部粉色圆角矩形 drawRoundRect({ ctx, r: 15, x: 26, y: 687, w: 147, h: 23, next() { // 渐变填充 var grd = ctx.createLinearGradient(0, 0, 200, 0); grd.addColorStop(0, '#E828FF'); grd.addColorStop(0.7, '#FF1D74'); grd.addColorStop(1, '#FFB050'); ctx.fillStyle = grd; ctx.fill(); ctx.strokeStyle = grd; ctx.stroke(); } }); 复制代码 绘制文字 /** * 绘制文字 * * @export * @param {*} ctx canvas的 2d 对象 * @param {string} t 绘制的文字 * @param {number} x * @param {number} y * @param {number} w 文字宽度 * @param {number} [l=30] 行高 * @param {number} [limit=2] 行数 */ export function drawText(ctx: any, t: string, x: number, y: number, w: number, l:number = 30, limit:number = 2) { // 参数说明 // ctx:canvas的 2d 对象,t:绘制的文字,x,y:文字坐标,w:文字最大宽度 let chr = t.split(''); let temp = ''; let row = []; let limitIndex = 0; let wordsNum = 0; for (let a = 0; a < chr.length; a++) { wordsNum++; if (ctx.measureText(temp).width < w && ctx.measureText(temp + (chr[a])).width wordsNum) { temp = temp.substring(0, temp.length - 1) + '...'; } row.push(temp); for (let b = 0; b < row.length; b++) { ctx.fillText(row[b], x, y + (b + 1) * l);// 每行字体y坐标间隔30 } }; 复制代码 绘制完成导出图片 export async function draw() { let { node: canvas, width, height } = await getCanvas(); let ctx = setContext({ canvas, width, height }); // 绘制前先清除,以防原有图案被影响 ctx.clearRect(0, 0, width, height); ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, 414, 736); // 底部灰色块 ctx.fillStyle = '#f5f5f5'; ctx.fillRect(0, 596, 414, 140); // 底部粉色圆角矩形 drawRoundRect({ ctx, r: 15, x: 26, y: 687, w: 147, h: 23, next() { // 渐变填充 var grd = ctx.createLinearGradient(0, 0, 200, 0); grd.addColorStop(0, '#E828FF'); grd.addColorStop(0.7, '#FF1D74'); grd.addColorStop(1, '#FFB050'); ctx.fillStyle = grd; ctx.fill(); ctx.strokeStyle = grd; ctx.stroke(); } }); // 推荐人 ctx.fillStyle = '#666666'; ctx.font = '13px/1.2 PingFangSC-Regular'; ctx.fillText(`${nickName}`, 93, 635); // 推荐语 ctx.fillStyle = '#222222'; ctx.font = '15px/1.2 PingFangSC-Regular'; ctx.fillText(`${recommendation || '推荐你一个超值的变美项目'}`, 93, 660); // 底部文字 ctx.fillStyle = '#ffffff'; ctx.font = '13px/1.2 PingFangSC-Regular'; ctx.fillText('长按识别小程序购物', 43, 703); // 省略部分图片绘制代码 // 获取图片临时路径 let { tempFilePath } = await Taro.canvasToTempFilePath({ canvas } as any); return Promise.resolve(tempFilePath); }; 复制代码

以上导出的图片地址可以直接给img标签赋值

图片保存到相册 const res = await Taro.saveImageToPhotosAlbum({ filePath: tempFilePath }); if (res.errMsg === 'saveImageToPhotosAlbum:ok') { Taro.showToast({ title: '保存图片成功', icon: 'success', duration: 2000 }); } 复制代码 小程序码解析

小程序码的解析后,在page里收到的参数在scene里

componentWillMount() { let params = this.$router.params; // 通过小程序码进入,参数在scene里 if (params.scene) { let scene = decodeURIComponent(params.scene); let {id} = query2parmas(scene); this.setState({ goodsId: id }); } // 通过分享卡片进入参数直接在params里 if (params.id) { this.setState({ goodsId: params.id }); } } 复制代码


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3