微信小程序 canvas描绘文字图片 生成图片并保存到本地

在实现这个功能时,遇到以下的问题:

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'
          })
        }
      })
    }
  })
},

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mossbaoo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值