1、Canvas 2D
<view class="main_box">
<!--weui加载中动画-如果不需要可去掉--->
<mp-loading show="{{showLoad}}"></mp-loading>
<canvas style="width: {{canvas_width}}px;height: {{canvas_height}}px;" type="2d" id="myCanvas" class="canvas"></canvas>
</view>
<view class="btn_box">
<button class="btn " bind:tap="saveImg">保存海报</button>
</view>
<view class="" style="height: 60rpx;"></view>
.json文件
{
"usingComponents": {
"mp-loading": "weui-miniprogram/loading/loading"
}
}
const APP = new getApp();
Page({
data: {
userInfo:{},
goodsId:'',
canvasImg:{},
helpData:{},
help_id:'',
canvas_width:'',
canvas_height:'',
showLoad:true,
rpx:1,
canvas:{},
qrcode:"",
},
onLoad(options) {
this.setData({goodsId:options.id,help_id:options.help_id});
this.getUserinfo();
},
init(){//初始化canvas
const query = wx.createSelectorQuery();
const dpr = wx.getSystemInfoSync().pixelRatio;
let rpx = wx.getSystemInfoSync().windowWidth / 375; //适配
query.select('#myCanvas')
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node
const ctx = canvas.getContext('2d')
canvas.width = 355*rpx*dpr;
canvas.height = 600*rpx*dpr;
ctx.fillStyle="#fff";//背景颜色
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle="#000000";
this.setData({
canvas_width:355*rpx,
canvas_height:600*rpx,
canvas:canvas
})
ctx.scale(dpr, dpr)
// ctx.fillRect(0, 0, 100, 100)
this.crateCanvas(canvas,ctx)
})
},
crateCanvas(canvas,ctx){
let that = this;
let rpx = wx.getSystemInfoSync().windowWidth / 375;
that.setData({rpx:rpx})
ctx.save(); // 先保存状态 已便于画完圆再用
ctx.beginPath()
ctx.arc(50 * rpx, 50 * rpx, 30 * rpx, 0, Math.PI * 2, false); //false代表顺时针 图片的位置加半径
ctx.strokeStyle="#fff" //线条颜色
ctx.stroke();
// ctx.fillStyle="yellow" //填充圆形
// ctx.fill()
// ctx.draw(true)
ctx.clip();//画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
let img = canvas.createImage();
img.src = that.data.userInfo.wx_avatar_url; // 引入本地图片
img.onload = (e) => {
ctx.drawImage(img, 20*rpx, 10*rpx, 60*rpx, 60*rpx);
}
ctx.restore()//恢复之前保存的绘图上下文 恢复之前保存的绘图上下文即状态 可以继续绘制
// ctx.clearRect(0, 0, canvas.width, canvas.height)// 清空画布
ctx.font = "bold 18px Microsoft YaHei";
ctx.fillText(that.data.userInfo.nick_name, 90*rpx, 40*rpx);
ctx.font = "15px Microsoft YaHei";
ctx.fillText("正在参加助力活动!",90*rpx, 65*rpx);
let img_goods = canvas.createImage();
img_goods.src = that.data.helpData.images; // 引入本地图片
img_goods.onload = (e) => {
ctx.drawImage(img_goods, 15*rpx, 80*rpx, 330*rpx, 320*rpx );
}
ctx.font = "14px Microsoft YaHei";
ctx.fillText( that.data.helpData.goods_title,20*rpx,420*rpx );
ctx.fillStyle = '#d5313a';
ctx.fillText("价格¥",20*rpx, 470*rpx);
ctx.font = "20px Microsoft YaHei";
ctx.fillText(that.data.helpData.extend_data.selling_price,60*rpx, 470*rpx);
ctx.fillStyle = '#666';
ctx.font = "14px Microsoft YaHei";
ctx.fillText("原价¥"+that.data.helpData.extend_data.show_price,20*rpx, 500*rpx);
ctx.fillText("已售"+that.data.helpData.extend_data.selling_num,20*rpx, 540*rpx);
ctx.fillText("仅剩"+that.data.helpData.extend_data.remain_num,80*rpx, 540*rpx);
let img_code = canvas.createImage();
img_code.src = that.data.qrcode; // 引入本地图片
img_code.onload = (e) => {
ctx.drawImage(img_code, 240*rpx, 440*rpx, 100*rpx, 100*rpx);
}
ctx.font = "12px Microsoft YaHei";
ctx.fillStyle = '#666';
// ctx.textAlign = 'center'
ctx.fillText("长按识别小程序码",242*rpx,560*rpx);
this.setData({
showLoad:false
})
},
getGoods(){ //获取商品信息
let that = this;
APP.request.get(APP.api.goods, {
m: "goodsDetail",
id: this.data.id,
record:1
}, (res) => {
this.setData({
helpData: res,
});
// wx.downloadFile({ //获本地临时路径
// url: res.img,
// success: function (res2) {
// that.setData({
// qrcode: res2.tempFilePath
// });
// }
// })
that.init();
});
},
getUserinfo(){
let that = this;
APP.request.get(APP.api.user, {
m: "getUserInfo",
}, (res) => {
that.setData({userInfo: res});
that.getGoods();
})
},
saveImg(){
var that = this;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: that.data.canvas_width * 3,
height: that.data.canvas_height * 3,
destWidth:that.data.canvas_width *3,
destHeight: that.data.canvas_height*3,
canvas: this.data.canvas,
success: function (res) {
//调取小程序当中获取图片
console.log(res.tempFilePath);
that.setData({isrc:res.tempFilePath})
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(res) {
wx.showToast({
title: '保存成功',
})
}
})
},
})
},
})
.main_box{width:calc(100% - 40rpx) ;background-color: #f5f5f5;padding: 20rpx;}
.canvas{width: 100%;height: 100%;background-color: #fff;}
.btn_box{width: 90%;margin: auto;margin-top: 30rpx;}
.btn_box .btn{
width: 80%;
height: 70rpx;
line-height: 70rpx;
margin: auto;
background-color: #f9592e;
color:#f5f5f5;
}
2、老版接口
<canvas canvas-id="myCanvas" style="width:{{375 * rpx}}px;height:{{723 * rpx}}px"/>
<view class="bottom_box">
<view bindtap='saveImg' class='btn'>保存海报</view>
</view>
//图片需要先下载到本地,获取本地连接,然后再画到canvas
getbg(){
let that = this;
wx.downloadFile({
url: "https://img.alicdn.com/imgextra-2-tps-206-240.png",
success: function (res3) {
that.setData({
bg_img: res3.tempFilePath
});
}
})
},
canvasImg() {
let that = this;
var res = wx.getSystemInfoSync();
var rpx = res.windowWidth / 375; //iphone6
console.log("rpx",rpx)
that.setData({
rpx: res.windowWidth / 375
})
const ctx = wx.createCanvasContext('myCanvas');
ctx.setFillStyle('#f5f5f5'); //为创建的canvans上下文添充颜色 如果没有设置 fillStyle,默认颜色为 black。
ctx.fillRect(0, 0, 375 * rpx, 724 * rpx)
ctx.save(); // 先保存状态 已便于画完圆再用
ctx.beginPath(); //开始绘制
ctx.drawImage(that.data.bg_img, 0, 0, 375 * rpx, 724 * rpx);//绘制背景图片
//先画个圆
ctx.arc(190 * rpx, 140 * rpx, 30 * rpx, 0, Math.PI * 2, false); //false代表顺时针 图片的位置加半径
// ctx.setStrokeStyle('#ffffff')
ctx.stroke(); //画出当前路径的边框。默认颜色色为黑色。
ctx.clip();//画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
ctx.drawImage(https://mhsimg.flashnet.cn/9a611f4e3108db22/7e63628891c50f7b.png, 160 * rpx, 110 * rpx, that.data.image.width * rpx, that.data.image.heigth * rpx); // 推进去图片
ctx.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下文即状态 可以继续绘制
ctx.setFillStyle("#f5f5f5");
ctx.setFontSize(16 * rpx); //字大小
ctx.setTextAlign('center'); //是否居中显示,参考点画布中线
ctx.fillText(半仙儿, 188 * rpx, 200 * rpx);
ctx.setFillStyle("#f5f5f5");
ctx.setFontSize(14 * rpx); //字大小
ctx.setTextAlign('center');
ctx.fillText('向您推荐了一个好东西!', 190 * rpx, 220 * rpx);
// 裁剪一个圆角区域,显示图片二维码
const x = 155 * rpx, y = 580 * rpx, w = 70 * rpx, h = 70 * rpx, r = 10 * rpx;
ctx.beginPath();
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
ctx.lineTo(x + w - r, y);
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
ctx.lineTo(x + w, y + h - r);
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);
ctx.lineTo(x + r, y + h);
ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI);
ctx.closePath();
ctx.clip();
ctx.drawImage(that.data.code, x, y, w, h);
// ctx.draw(true);
ctx.draw();
wx.hideLoading()
},
saveImg() {
let that = this;
var res = wx.getSystemInfoSync()
var rpx = res.windowWidth / 375
that.setData({
rpx: res.windowWidth / 375
})
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 375 * rpx, //画布宽高
height: 724 * rpx,
destWidth: 375 * 3 * rpx, //画布宽高*dpr 以iphone6为准
destHeight: 724 * 3 * rpx, //放大2倍以上,解决保存的图片模糊的问题
canvasId: 'myCanvas',
fileType:'png',
success: function (res) {
console.log(res.tempFilePath) //生成的临时图片路径
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: function (res) {
console.log(res);
wx.showToast({
title: '保存成功',
})
},
fail: function () {
console.log('a')
}
})
}
})
},
<image src="{{canvasImgSrc}}" mode="aspectFit" style="width:100vw;height:calc(100vh - 120rpx)"></image>
covertImg(){ //把canvas转换为图片,方便修改样式
var res = wx.getSystemInfoSync()
var rpx = res.windowWidth / 375
setTimeout(() => {
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 375 *3* rpx,
height: 700 *3* rpx,
canvasId: 'myCanvas',
success: (res) => {
this.setData({ canvasImgSrc: res.tempFilePath });
wx.hideLoading();
}
});
},500)
},