微信小程序2D canvas绘制分享海报
效果图:

wxml
<view>
<canvas type="2d" id="canvas_box" style="width:260px;height:430px "></canvas>
<button class='bottom' catchtap="bc" canvas-id="mycanvas"> 保存到相册 </button>
</view>
type:指定 canvas 类型
id:canvas 组件的唯一标识符
样式根据自己情况自定义
page{
background: rgb(223, 165, 165);
}
canvas{
margin:20rpx auto;
border: 1rpx solid #ccc;
background: #fff;
color: #fff;
}
js重点
(完整js代码在最下面)
onReady: function () {
const query = wx.createSelectorQuery()
query.select('#canvas_box')
.fields({
id: true,
node: true,
size: true
})
.exec(this.init.bind(this));
},
id:true 是否返回节点 id
node:true 是否返回节点对应的 Node 实例
size:true 是否返回节点尺寸(width height)
wx.createSelectorQuery()
生成一个 SelectorQuery 对象实例,在具有自定义组件的页面中,请确保您使用 this.createSelectorQuery() 来代替当前的方式。
select
在当前页面上定位首个匹配的selector节点,并通过获取该NodesRef对象来实现相关操作。
selector 语法
selector类似于 CSS 的选择器,但仅支持下列语法。
以下是对输入文本的同义改写版本
fields
查询节点相关信息。所需字段需从fields参数中进行指定设置。返回结果为 nodesRef 标识符与 selectorQuery 参数的组合体。
注意
computedStyle 被赋予了更高的 precedence over size;当同时在 computedStyle 中指定了 width 和 height 并且传入了 size: true 时,则会优先返回 computedStyle 所获取到的宽度和高度值。
init(res) {
console.log(res)
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const dpr = wx.getSystemInfoSync().pixelRatio
//新接口需显示设置画布宽高;
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr);
this.setData({
canvas,
ctx
});
//向画布方法
this.canvasDraw(ctx);
this.title(ctx);
this.name(ctx)
this.code(ctx).then(rrr=>{
this.hande(ctx)
})
},
wx.getSystemInfoSync() // wx.getSystemInfo 的同步版本
通过Canvas.getContext('d') API可以访问CanvasRenderingContext2D对象,并提供了HTML Canvas 2D Context所定义的功能
画图
canvasDraw(ctx) {
let img = this.data.canvas.createImage();
img.src = "img/2.jpg";
img.onload = () => {
this.data.ctx.drawImage(img, 0, 0, 260, 260);
};
},
let img = this.data.canvas.createImage(); //创建img对象
img.src = "图片地址"
img.onload 图片加载监听
this.data.ctx.drawImage(img, 10, 10, 260, 260); // (图片,左距离,上距离,宽,高)
画文字
title(ctx) {
// ctx.setFontSize(12)
let text = '接小程序开发,web开发,H5开发,小程序云开发,PHP开发'
let moy = '有需要的直接微信扫码'
ctx.font = 'normal bold 12px sans-serif';
ctx.fillStyle = "rgba(60, 59, 59)";
console.log('======,', text.length)
if (text.length <= 19) {
ctx.fillText(text, 10, 275, 280)
ctx.fillStyle = "rgba(0,0,0)";
ctx.font = 'normal bold 16px sans-serif';
ctx.fillStyle = "red";
ctx.fillText(moy, 10, 290, 280)
}
if (text.length <= 38) {
let firstLine = text.substring(0, 20);
let secondLine = text.substring(20, 38);
ctx.fillText(firstLine, 10, 275, 280)
ctx.fillText(secondLine, 10, 290, 280)
ctx.fillStyle = "rgba(0,0,0)";
ctx.font = 'normal bold 16px sans-serif';
ctx.fillStyle = "red";
ctx.fillText(moy, 10, 315, 280)
} else {
let firstLine = text.substring(0, 20);
let secondLine = text.substring(20, 38) + '...';
ctx.fillText(firstLine, 10, 280, 280)
ctx.fillText(secondLine, 10, 295, 280)
ctx.font = 'normal bold 16px sans-serif';
ctx.fillStyle = "red";
ctx.fillText(moy, 10, 320, 280)
}
},
保存到相册
普通的保存
wx.canvasToTempFilePath({
x: 100,
y: 200,
width: 50,
height: 50,
destWidth: 100,
destHeight: 100,
canvasId: 'myCanvas',
success(res) {
console.log(res.tempFilePath)
}
})
2d的保存
bc() {
// 保存到相册
console.log('保存canvasId',this.data.canvas._canvasId)
wx.canvasToTempFilePath({ //将canvas生成图片
canvas:this.data.canvas,
x: 0,
y: 0,
width: this.data._width,
height: this.data._height,
destWidth: this.data._width, //截取canvas的宽度
destHeight:this.data._height, //截取canvas的高度
success: function (res) {
console.log('生成图片成功:',res)
wx.saveImageToPhotosAlbum({ //保存图片到相册
filePath: res.tempFilePath,
success: function () {
wx.showToast({
title: "保存图片成功!",
duration: 2000
})
}
})
},
},this)
},
请留意区分二者的主要差别,请参考官方文档https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.canvasToTempFilePath.html


完整js代码
Page({
data: {
},
onLoad: function () {
},
onReady: function () {
const query = wx.createSelectorQuery()
query.select('#canvas_box')
.fields({
id: true,
node: true,
size: true
})
.exec(this.init.bind(this));
},
init(res) {
console.log(res)
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const dpr = wx.getSystemInfoSync().pixelRatio
//新接口需显示设置画布宽高;
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr);
this.setData({
canvas,
ctx
});
//向画布载入图片的方法
this.canvasDraw(ctx);
//向画布载入标题的方法
this.title(ctx);
this.name(ctx)
this.code(ctx).then(rrr=>{
// 头像加载
this.hande(ctx)
})
},
// 封面图
canvasDraw(ctx) {
let img = this.data.canvas.createImage(); //创建img对象
img.src = "img/2.jpg";
img.onload = () => {
console.log(img.complete); //true
this.data.ctx.drawImage(img, 0, 0, 260, 260);
};
},
// 标题
title(ctx) {
// ctx.setFontSize(12)
let text = '接小程序开发,web开发,H5开发,小程序云开发,PHP开发'
let moy = '有需要的直接微信扫码'
ctx.font = 'normal bold 12px sans-serif';
ctx.fillStyle = "rgba(60, 59, 59)";
console.log('======,', text.length)
if (text.length <= 19) {
// 一行字
ctx.fillText(text, 10, 275, 280)
ctx.fillStyle = "rgba(0,0,0)";
}else if (text.length <= 38) {
// 两行字
let firstLine = text.substring(0, 20);//第一行
let secondLine = text.substring(20, 38);第二行
ctx.fillText(firstLine, 10, 275, 280)
ctx.fillText(secondLine, 10, 290, 280)
} else {
// 超过两行省略多的加省略号
let firstLine = text.substring(0, 20);
let secondLine = text.substring(20, 38) + '...';
ctx.fillText(firstLine, 10, 280, 280)
ctx.fillText(secondLine, 10, 295, 280)
}
ctx.font = 'normal bold 16px sans-serif';
ctx.fillStyle = "red";
ctx.fillText(moy, 10, 320, 280)
},
// 头像
hande(ctx) {
let hande = this.data.canvas.createImage(); //创建img对象
hande.onload = () => {
console.log(hande.complete); //true
// 绘制头像图片
ctx.arc(30, 370, 40/2, 0, 2 * Math.PI) //画出圆
ctx.clip(); //裁剪上面的圆形
ctx.drawImage(hande, 10, 350, 40, 40)
ctx.restore();
};
hande.src = "img/1.jpg";
},
// 名字
name(ctx){
ctx.fillStyle = "rgba(60, 59, 59)";
ctx.font = 'normal bold 12px sans-serif';
ctx.fillText('Loust', 60, 365, 280)
ctx.fillStyle = "rgba(60, 59, 59)";
ctx.font = 'normal bold 10px sans-serif';
ctx.fillStyle = "#999";
ctx.fillText('希望大佬们能够多多指教', 60, 380, 280)
},
// 二维码
code(ctx) {
return new Promise(rrr=>{
let code = this.data.canvas.createImage(); //创建img对象
code.onload = () => {
console.log(code.complete); //true
this.data.ctx.drawImage(code, 180, 340, 60, 60);
};
code.src = "img/code.jpg";
setTimeout(() => {
rrr(true)
}, 100);
})
},
bc() {
// 保存到相册
console.log('保存canvasId',this.data.canvas._canvasId)
wx.canvasToTempFilePath({ //将canvas生成图片
canvas:this.data.canvas,
x: 0,
y: 0,
width: this.data._width,
height: this.data._height,
destWidth: this.data._width, //截取canvas的宽度
destHeight:this.data._height, //截取canvas的高度
success: function (res) {
console.log('生成图片成功:',res)
wx.saveImageToPhotosAlbum({ //保存图片到相册
filePath: res.tempFilePath,
success: function () {
wx.showToast({
title: "保存图片成功!",
duration: 2000
})
}
})
},
},this)
},
})
