写这个的原因是在写一个小程序的需求的时候用到了,在此记录一下。
需求需要实现的点就是:在分享小程序个人资料页面的时候将个人信息和个人头像进行重叠放在一起然后分享出去,大概样子如下:
不同的用户头像不同,个人信息不同。写一个函数传入这两个信息,动态合成一张图片,然后再进行分享。
实现的完整代码如下:
// 图片文字合成 // 绘制文字 function canvasWraptitleText(ctx, text, x, y, maxWidth, lineHeight, maxRowNum,font,color) { return new Promise((resolve, reject) => { if (typeof text != 'string' || typeof x != 'number' || typeof y != 'number') { return; } ctx.font = font; //绘制文字的字号和大小 ctx.setFillStyle(color) //字体颜色 // 字符分隔为数组 var arrText = text.split(''); var line = ''; var rowNum = 1; for (var n = 0; n < arrText.length; n++) { var testLine = line + arrText[n]; var metrics = ctx.measureText(testLine); var testWidth = metrics.width; if (testWidth > maxWidth && n > 0) { if (rowNum >= maxRowNum) { var arrLine = testLine.split('') // arrLine.splice(-9) var newTestLine = arrLine.join("") newTestLine += "..." canvas.fillText(newTestLine, x, y); resolve(); return } canvas.fillText(line, x, y); line = arrText[n]; y += lineHeight; rowNum += 1 } else { line = testLine; } } ctx.fillText(line, x, y); resolve(); }) } // 获得合成后的图片路径 function getCanvasToTempFilePath(canvasData,id){ return new Promise((resolve, reject) => { wx.canvasToTempFilePath({ canvasId: id, success:(res) =>{ resolve(res.tempFilePath) } }) }) } // 合成前获取图片地址 function downloadFile(img) { return new Promise((resolve, reject) => { // 如果是腾讯云存储,下载前做一下裁剪,加快下载速度 if(img.indexOf('pubser-res.xxx.com/')>-1){ img += '?imageMogr2/scrop/300x240' } wx.downloadFile({ //下载图片 url: img, success(res){ if (res.statusCode === 200) { return resolve(res.tempFilePath) } else { return reject() } }, complete(err){ return reject('') } }) }) } // 获取图片信息 function getImgInfo(img) { return new Promise((resolve, reject) => { wx.getImageInfo({ src: img, success(res){ if (res.width) { return resolve(res.width) } }, complete(err){ return reject('') } }) }) } /** * @description: 图片文字合成 * @param {id} 必填 canvas的id * @param {canvasData} 可选 要合成的文字 * @param {bgImg} 可选 要合成的图片 */ function createShareImg(id, canvasData, bgImg){ return new Promise(async (resolve, reject) => { // 按照宽度为300 宽高比为5:4绘制 // var v = wx.getSystemInfoSync().windowWidth / 750 var width = 132; var height = 105.6; var ctx = wx.createCanvasContext(id); ctx.fillStyle = 'rgba(255,255,255,1)'; ctx.fillRect(0,0,width,height); try{ // 绘制头像 const bgImg1 = await downloadFile(bgImg) const realWidth = await getImgInfo(bgImg1) const realHeight = realWidth * 0.8 ctx.drawImage(bgImg1,0,0,realWidth, realHeight,0,0,width, height) // 绘制渐变背景 const bgImg2 = await downloadFile('https://file.zastatic.com/images/common-cms/it/20220222/1645523216476_180077.png') ctx.drawImage(bgImg2, 0,0,600,272, 0,0,width,height) // 绘制文字 let x = width * 0.05 let y = height * 0.95; // 从下往上排 for (const key in canvasData) { canvasWraptitleText(ctx,canvasData[key], x,y,200,30,5,'400 9px PingFangSC','#FFFFFF'); y-=14; } ctx.save(); // 完成 ctx.draw(true, ()=>{ getCanvasToTempFilePath(canvasData,id).then((DATA)=>{ resolve(DATA) }) }) }catch(err){ resolve('') } }) } export { createShareImg }