在实现这个功能时,遇到以下的问题:
1. canvas绘制文字的换行问题:
如果文字的长度大于你所定的宽度的话,文字会超出你所定宽度;
小程序的CanvasContext.fillText有一个maxWidth(需要绘制的最大宽度)参数,它的功能并不是超出该宽度换行,而是对文本进行挤压。
所以,光靠API是无法实现的,那么就有了以下的解决方法:
data: { text: '这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本' }, onReady: function () { const context = wx.createCanvasContext('myCanvas') var chr = this.data.text.split(""); var temp = ""; var row = []; context.setFontSize(18) context.setFillStyle("#000") for (var a = 0; a < chr.length; a++) { if (context.measureText(temp).width < 250) { temp += chr[a]; }else { a--; //添加a--,防止字符丢失 row.push(temp); temp = ""; } } row.push(temp); //如果数组长度大于2 则截取前两个 if (row.length > 2) { var rowCut = row.slice(0, 2); var rowPart = rowCut[1]; var test = ""; var empty = []; for (var a = 0; a < rowPart.length; a++) { if (context.measureText(test).width < 220) { test += rowPart[a]; }else { break; } } empty.push(test); var group = empty[0] + "..." rowCut.splice(1, 1, group); row = rowCut; } for (var b = 0; b < row.length; b++) { context.fillText(row[b], 10, 30 + b * 30, 300); } context.draw() }
2. canvas绘制图片在真机上不能显示的问题:
微信小程序canvas绘制图片必须用本地的图片路径,所以要把图片下载下来存为临时路径再绘制图片。微信提供了个api可用:wx.downloadFile和wx.getImageInfo。都需先配置download域名才能生效。
wx.downloadFile({ url: 'https://wx.qlogo.cn/mmopen/vi_32/xxxxxxx', success (res) { if (res.statusCode === 200) { console.log(res.tempFilePath) } } })
后面展示一下关于这个功能的案例!(该案例的图片为本地图片,使用网络图片请注意以上的问题)
效果图:
主要的wxml:
<canvas canvas-id="canvas"></canvas>
<view class="bottom">
<button bindtap="saveImage">保存图片</button>
</view>
主要的wxss:
canvas {
width: 300px;
height: 355px;
background: #fff;
border-radius: 10rpx;
margin: 20rpx auto;
box-shadow: 0 6rpx 6rpx rgba(0,0,0,.1);
}
.button {
display: flex;
justify-content: center;
padding-bottom: 25rpx;
}
.button button {
width: 180rpx;
height: 60rpx;
line-height: 60rpx;
padding: 0;
border-radius: 60rpx;
font-size: 26rpx;
border: 1px solid #f76c1d;
color: #F76C1D;
}
用到的data数据信息:
data: {
logo: '/images/logo.jpg',
img: '/images/product2.jpg',
title: '药用防脱生发营养液240ml护发养发精浓密发根增长液增长液',
text: '萃取植物精华,促进毛发再生。生发养发,强效增发,无效退款。',
price: '138.00',
code: '/images/code.jpg'
},
描绘canvas画布的 js:
onReady: function () {
// 生命周期函数--监听页面初次渲染完成
var ctx = wx.createCanvasContext('canvas')
// 设置背景
ctx.setFillStyle('#ffffff')
ctx.fillRect(0, 0, 300, 355)
// logo
ctx.drawImage(this.data.logo, 100, 9, 100, 33)
// logo下线条
ctx.setStrokeStyle("rgba(0,0,0,.1)")
ctx.setLineWidth(0.3)
ctx.moveTo(0, 49)
ctx.lineTo(300, 49)
ctx.stroke()
// 商品图片
ctx.drawImage(this.data.img, 0, 180, 750, 500, 10, 58, 280, 165)
// 商品名称
ctx.setFontSize(15)
ctx.setFillStyle("#333333")
textHandle(this.data.title, 10, 248, 170, 18);
// 商品介绍
ctx.setFontSize(12)
ctx.setFillStyle("#666666")
textHandle(this.data.text, 10, 290, 170, 15);
// 商品价格
ctx.setFontSize(18)
ctx.setFillStyle("#F62B19")
ctx.fillText('¥'+this.data.price, 12, 335);
// 二维码文字
ctx.setFontSize(10)
ctx.setFillStyle("#666666")
ctx.fillText('扫描或长按二维码', 210, 246);
// 二维码图片
ctx.drawImage(this.data.code, 210, 258, 80, 80);
/**
* @function textHandle 绘制文本的换行处理
* @param text 在画布上输出的文本
* @param numX 绘制文本的左上角x坐标位置
* @param numY 绘制文本的左上角y坐标位置
* @param textWidth 文本宽度
* @param lineHeight 文本的行高
* @author Moss
*/
function textHandle(text, numX, numY, textWidth, lineHeight) {
var chr = text.split(""); // 将一个字符串分割成字符串数组
var temp = "";
var row = [];
for (var a = 0; a < chr.length; a++) {
if (ctx.measureText(temp).width < textWidth) {
temp += chr[a];
}else {
a--; // 添加a--,防止字符丢失
row.push(temp);
temp = "";
}
}
row.push(temp);
// 如果数组长度大于2 则截取前两个
if (row.length > 2) {
var rowCut = row.slice(0, 2);
var rowPart = rowCut[1];
var test = "";
var empty = [];
for (var a = 0; a < rowPart.length; a++) {
if (ctx.measureText(test).width < textWidth-10) {
test += rowPart[a];
}else {
break;
}
}
empty.push(test);
var group = empty[0] + "..."; // 这里只显示两行,超出的用...展示
rowCut.splice(1, 1, group);
row = rowCut;
}
for (var b = 0; b < row.length; b++) {
ctx.fillText(row[b], numX, numY + b * lineHeight);
}
}
// 完成
ctx.draw()
},
如果只需要限制一行文字,那修改一下方法:
textHandle('Hello world!', 65, 42, 150);
/**
* @function textHandle 绘制文本的单行超出显示省略号
* @param {String} text 在画布上输出的文本
* @param {Number} numX 绘制文本的左上角x坐标位置
* @param {Number} numY 绘制文本的左上角y坐标位置
* @param {Number} textWidth 文本宽度
* @author Moss
*/
function textHandle(text, numX, numY, textWidth) {
var str = text.split("");
var temp = "";
var row = [];
for (var a = 0; a < str.length; a++) {
if (ctx.measureText(temp).width < textWidth) {
temp += str[a];
}else {
temp = temp+"...";
break;
}
}
row.push(temp);
for (var b = 0; b < row.length; b++) {
ctx.fillText(row[b], numX, numY);
}
}
},
生成图片并保存到本地的 js:
saveImage() {
wx.canvasToTempFilePath({
canvasId: 'canvas',
success(res) {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(res) {
wx.showToast({
title: '保存成功',
icon: 'success'
})
}
})
}
})
},