canvas - 海报如此简单
小程序生成海报 canvas海报 百度小程序
下面以百度小程序为例,使用canvas生成海报
组件
canvas
api
swan.createCanvasContext
属性/方法
方法 参数 说明 .setFillStyle color 设置填充色 .fillRect (x,y,width,height) 填充一个矩形 .fill 无 填充内容 .setFontSize number 设置字体大小 .fillText (text,x,y) 绘制填充文本 .setTextAlign string 设置文字对齐方式 .drawImage ... 绘制图像到画布 .measureText string 测量文本尺寸 .draw 绘制到canvas上
开始之前
- canvas是分层级的 - js代码执行逻辑。默认情况下,写在越靠前的代码层级越低。
- 所有绘制的图形/形状必须给宽高。
- 后设置的setFillStyle会覆盖先设置的setFillStyle。如果想要回到原来设置的填充色,需要重新设置setFillStyle - 不会影响之前的效果。
- 默认情况下图形/文字/图片是靠左上的,并且canvas中没有提供靠右排版的api。
- canvas是没有让文本换行的api的
废话不多说,上代码
index.swan
<view class="container"> <view class="main"> <canvas canvas-id="myCanvas" style="width:100%;height:100%"> </canvas> </view> <view> <button bindtap="renderCanvas">绘制</button> </view> </view>index.css
.container{ background-color: #f1f1f1; } .main{ width: 750rpx; height: 100vh; box-sizing: border-box; padding: 20rpx 40rpx; }index.js
/* eslint-disable import/unambiguous, @babel/new-cap */ const app = getApp(); let ctx; Page({ data: { name: 'swan', windowHeight:app.globalData.windowHeight + 'px', windowWidth:app.globalData.windowWitdh + 'px', }, onLoad() { // Do something when page load. ctx = this.createCanvasContext('myCanvas'); }, // 绘制canvas画布大小 renderCanvas(){ let canvasWidth = app.globalData.windowWidth - 40 let canvasHeight = canvasWidth + 100 + 100 + 50; ctx.setFillStyle('#fff'); // 设置矩形的填充颜色为蓝色 ctx.fillRect(0, 0, canvasWidth, canvasHeight); let head_left = canvasWidth * 0.6; let head_center = canvasWidth * 0.15; let head_right = canvasWidth * 0.25 - 10; ctx.drawImage('../../static/images/head_bg.jpg',0,0,canvasWidth,100); ctx.drawImage('../../static/images/dfhm.png',10,15,head_left,70); ctx.drawImage('../../static/images/zb.png',head_left + head_center,15,head_right,35); ctx.setFillStyle('#000'); // 设置文字的填充颜色为黑色 ctx.setFontSize(12); ctx.fillText('12号', head_left + head_center, 65); ctx.fillText('12号', head_left + head_center, 80); // 顶部结束 - 顶部高为100 // 中间部分 ctx.setFillStyle('#e8e8e8') ctx.fillRect(0,100,canvasWidth,canvasWidth); ctx.setFillStyle('#f00');// 恢复填充颜色为之前设置的颜色 // 计算矩形中心坐标 let rectCenterX = canvasWidth / 2; let rectCenterY = canvasWidth / 2 + 100; ctx.setFillStyle('#ccc'); ctx.drawImage('../../static/images/head_bg.jpg',rectCenterX - 100, rectCenterY - 100, 200, 200); ctx.fillRect(0,canvasWidth + 100,canvasWidth,50) ctx.setFillStyle('#000'); ctx.setFontSize(24); ctx.setTextAlign('center'); ctx.fillText('商品名称',rectCenterX,canvasWidth + 100 + 24 + 10) // 顶部+中间部分结束 - 高度为canvasWidth + 100 + 50 // 底部二维码部分 ctx.drawImage('../../static/images/head_bg.jpg',20, canvasWidth + 100 + 50 + 15, 70, 70); ctx.setFontSize(14) ctx.setTextAlign('left'); this.drawTextWithWrap(ctx, '点击下方按钮,保存分享图,快乐分享每一天!', 110, 50 + canvasWidth + 100 + 50, canvasWidth / 2 - 20, 16); ctx.fill(); ctx.draw(); }, drawTextWithWrap(ctx, text, x, y, maxWidth, lineHeight) { let words = text.split(''); let line = ''; console.log('进入判断',words); for(let i = 0; i < words.length; i++) { let testLine = line + words[i] + ''; let metrics = ctx.measureText(testLine); console.log(metrics); let testWidth = metrics.width; if(testWidth > maxWidth && i > 0) { console.log('超出一行'); ctx.fillText(line, x, y); line = words[i] + ''; y += lineHeight; } else { line = testLine; } } ctx.fillText(line, x, y); }, });
逻辑
首先创建canvas上下文对象 - ctx = this.createCanvasContext('myCanvas');
创建一个矩形作为背景
let canvasWidth = app.globalData.windowWidth - 40;// let canvasHeight = canvasWidth + 100 + 100 + 50; ctx.setFillStyle('#fff'); // 设置矩形的填充颜色为蓝色 ctx.fillRect(0, 0, canvasWidth, canvasHeight); // x偏移0,y偏移0,canvasWidth矩形宽,canvasHeight矩形高开始绘制海报中需要的元素
let head_left = canvasWidth * 0.6; let head_center = canvasWidth * 0.15; let head_right = canvasWidth * 0.25 - 10; ctx.drawImage('../../static/images/head_bg.jpg',0,0,canvasWidth,100); ctx.drawImage('../../static/images/dfhm.png',10,15,head_left,70); ctx.drawImage('../../static/images/zb.png',head_left + head_center,15,head_right,35); // 先前提到的由于canvas不能设置靠右 // 要适配不同的微小偏差的机型,使用百分比的形式进行偏移 // 绘制的图像不要忘记给宽高,图像支持相对路径,网络图片,临时文件如何将元素居中
// 我们可以得知上面矩形的高是100,我们想将矩形放到下面矩形的正中间 // 我们就需要设置小矩形的中心点 // 计算大矩形中心坐标 - 由于默认坐标是左上,也就是默认情况下的0,0 ,我们需要将坐标设置到大矩形中心 let rectCenterX = canvasWidth / 2; let rectCenterY = canvasWidth / 2 + 100; ctx.setFillStyle('#ccc'); // rectCenterX - 100, rectCenterY - 100将坐标进行偏移 - 相当于以rectCenterX - 100, rectCenterY - 100,为起始点画200*200的正方形 ctx.drawImage('../../static/images/head_bg.jpg',rectCenterX - 100, rectCenterY - 100, 200, 200); ctx.fillRect(0,canvasWidth + 100,canvasWidth,50); ctx.setFillStyle('#000'); ctx.setFontSize(24); ctx.setTextAlign('center'); ctx.fillText('商品名称',rectCenterX,canvasWidth + 100 + 24 + 10)如何将文本自动换行
// ctx.measureText - 获取文本宽度 drawTextWithWrap(ctx, text, x, y, maxWidth, lineHeight) { let words = text.split('');// 将传入的文本分成数组 - 分别计算每一个字体的宽 let line = ''; console.log('进入判断',words); for(let i = 0; i < words.length; i++) { // 将文字进行拼接 let testLine = line + words[i] + ''; let metrics = ctx.measureText(testLine); console.log(metrics); let testWidth = metrics.width;// 每次拼接计算一次宽度 if(testWidth > maxWidth && i > 0) {// 当计算的宽度大于传入的容器宽度之后,绘制第一行文本,并准备第二行文本 console.log('超出一行'); ctx.fillText(line, x, y); line = words[i] + ''; y += lineHeight; } else { line = testLine; } } ctx.fillText(line, x, y); },
如此就结束啦。
关于如何将绘制的canvas保存成临时文件,那就是另一个api了
swan.canvasToTempFilePath
未完待续。。。