//生成图片时显示,其余时间隐藏起来,根据css一起使用
/*再外侧包一个view,然后给view定位出去,就达到了隐藏的效果*/
.canvas-box{
position: fixed;
left: 10000px;
}
const { roundRect, roundImage, drawTextOverflow } = require("../../utils/util.js");
let rpx; //宽度%比 适配手机宽度
let xh; //高宽比 适配手机高度
page({
data: {
windowW: '', //设备宽高
windowH: '',
canvasQr: '', //二维码图片
canvasDetail: '', //详情项目图片地址
clip_left: '',//左偏移值,
clip_top: '', //上偏移值
clip_width: '',//截取宽度,截取高度
clip_height: '',
hideCanvas:false, //canvas的隐藏
detailData: {}, //我的数据,自行改动
}
_downImg:function(e){
wx.getSystemInfo({
success: function(res) {
rpx = res.windowWidth / 375;
xh = res.windowHeight / res.windowWidth
_this.setData({
windowW: res.windowWidth,
windowH: res.windowHeight,
scrollerHeight: res.windowHeight - (res.windowWidth / 750) * 120
})
}
});
console.log(e)
//这里是我调的接口得到的动态图片,你们根据自己要求去改
this.wxFileImg(e.detail.codeUrl);
wx.showLoading({
title: '正在生成图片中',
mask: true
})
this.setData({
hideCanvas:true,
})
},
//网络图片转临时 所有的网络图都要转一下,要不然有的真机不显示网络图片。 画布图片太多,就会很卡
wxFileImg: function (codeUrl) {
let _this = this;
wx.downloadFile({
url: codeUrl,
success: function (resQrFile) {
_this.setData({
canvasQr: resQrFile.tempFilePath
})
wx.downloadFile({
url: _this.data.detailData.logo,
success: function (resDetailFile) {
wx.getImageInfo({
src: resDetailFile.tempFilePath,
success(resDetailInfo) {
let img_width = resDetailInfo.width,
img_height = resDetailInfo.height;
//左偏移值,上偏移值,截取宽度,截取高度
let clip_left, clip_top, clip_width, clip_height;
clip_height = img_width ;
if (clip_height > img_height) {
clip_height = img_height;
clip_width = clip_height;
clip_left = (img_width - clip_width) / 2;
clip_top = 0;
} else {
clip_left = 0;
clip_top = (img_height - clip_height) / 2;
clip_width = img_width;
}
_this.setData({
canvasDetail: resDetailFile.tempFilePath,
clip_left,
clip_top,
clip_width,
clip_height
})
//画布id
let canvas = wx.createCanvasContext('canvas');
_this.canvasdraw(canvas);
}
})
}
})
}
})
},
canvasdraw: function (canvas) {
let _this = this;
let windowW = _this.data.windowW;
let windowH = _this.data.windowH;
let canvasQr = _this.data.canvasQr;
let canvasDetail = _this.data.canvasDetail;
let clip_left = _this.data.clip_left;
let clip_top = _this.data.clip_top;
let clip_width = _this.data.clip_width;
let clip_height = _this.data.clip_height;
let detailData = _this.data.detailData;
// 整画布 背景
canvas.setFillStyle('#EFEFEF');
canvas.fillRect(0, 0, windowW, windowH);
canvas.draw(true);
// 主画布
console.log(xh)
// 由于手机的高宽比不同,适配主画布的高度,可以根据自己的画布要求自行调整
if (xh > 1.9) {
roundRect(canvas, 15 * rpx, 100 * rpx, windowW * 0.92, windowH * 0.65, 10 * rpx, '#FFFFFF');
} else if (xh > 1.8) {
roundRect(canvas, 15 * rpx, 80 * rpx, windowW * 0.92, windowH * 0.75, 10 * rpx, '#FFFFFF');
}else{
roundRect(canvas, 15 * rpx, 80 * rpx, windowW * 0.92, windowH * 0.8, 10 * rpx, '#FFFFFF');
}
//详情图片
roundImage(canvas, 10 * rpx, canvasDetail, clip_left, clip_top, clip_width, clip_height, 15 * rpx, 30 * rpx, 345 * rpx, 245 * rpx, '#ffffff');
//遮挡图片圆角
roundRect(canvas, 15 * rpx, 210 * rpx, windowW * 0.92, 90 * rpx, 10 * rpx, '#FFFFFF');
// 项目名称 2行展示
drawTextOverflow(canvas, detailData.title, 305 * rpx, 2, 24, "#333", 28, 35 * rpx, 260 * rpx);
// 项目价格
canvas.setFontSize(20);
canvas.fillStyle = "#DD2534";
canvas.setTextAlign('left');
//文字加粗 这里是利用了两个文字重叠实现的加粗效果 坐标偏移了半个像素的位置
canvas.fillText(detailData.priceText, 35 * rpx, 319.5 * rpx);
canvas.fillText(detailData.priceText, 34.5 * rpx, 320 * rpx);
// 项目区域
canvas.setFontSize(16);
canvas.fillStyle = "#666666";
canvas.setTextAlign('left');
canvas.fillText(detailData.district, 35 * rpx, 350 * rpx);
// 项目面积
canvas.setFontSize(16);
canvas.fillStyle = "#666666";
canvas.setTextAlign('left');
canvas.fillText(detailData.landAreaText || detailData.houseSizeText, 35 * rpx, 380 * rpx);
//二维码
canvas.drawImage(canvasQr, 35 * rpx, 410 * rpx, 100 * rpx, 100 * rpx);
//名字
canvas.setFontSize(16);
canvas.fillStyle = "#333333";
canvas.setTextAlign('left');
canvas.fillText(detailData.userName, 155 * rpx, 445 * rpx);
// 线
canvas.beginPath();
// 这里要是设置为1 线的颜色就很深而且线比较粗
canvas.setLineWidth(0.1);
canvas.setFillStyle('#EFEFEF');
canvas.moveTo(155 * rpx, 460 * rpx);
canvas.lineTo(325 * rpx, 460 * rpx);
canvas.stroke();
// 提示
canvas.setFontSize(16);
canvas.fillStyle = "#999999";
canvas.setTextAlign('left');
canvas.fillText('微信长按或扫一扫打开', 155 * rpx, 490 * rpx);
canvas.draw(true, setTimeout(function () {
_this.daochu()
}, 1000));
},
//整个画布图片
daochu: function () {
let _this = this;
let windowW = _this.data.windowW;
let windowH = _this.data.windowH;
//这里没有处理生产图片时间过长的操作,我还没试着做,产品决定直接就不用画布了,
//毕竟太耗性能,等待时间也不可控,有懂得大佬能告知一下吗?
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: windowW,
height: windowH,
destWidth: windowW * 3, //3倍像素 更清晰
destHeight: windowH * 3,
canvasId: 'canvas',
success: function (res) {
// console.log(res)
wx.hideLoading();
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(res) {
}
})
wx.previewImage({
urls: [res.tempFilePath],
})
_this.setData({
hideCanvas: false
})
},
fail:function(err){
wx.hideLoading();
// console.log(err)
}
})
},
})
/**
* canvas绘制圆角矩形
* @param {Object} context - canvas组件的绘图上下文
* @param {Number} x - 矩形的x坐标
* @param {Number} y - 矩形的y坐标
* @param {Number} w - 矩形的宽度
* @param {Number} h - 矩形的高度
* @param {Number} r - 矩形的圆角半径
* @param {String} [c = 'transparent'] - 矩形的填充色
*/
const roundRect = (context, x, y, w, h, r, c = 'transparent') => {
if (w < 2 * r) {
r = w / 2;
}
if (h < 2 * r) {
r = h / 2;
}
context.beginPath();
context.fillStyle = c;
context.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
context.moveTo(x + r, y);
context.lineTo(x + w - r, y);
context.lineTo(x + w, y + r);
context.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
context.lineTo(x + w, y + h - r);
context.lineTo(x + w - r, y + h);
context.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);
context.lineTo(x + r, y + h);
context.lineTo(x, y + h - r);
context.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI);
context.lineTo(x, y + r);
context.lineTo(x + r, y);
context.fill();
context.closePath();
};
/**
* canvas绘制圆角图片
* @param {Object} context - canvas组件的绘图上下文
* @param {Number} r - 圆角半径
* @param {String} path - 图片地址
* @param {Number} sx - 源图像的矩形选择框的左上角 x 坐标
* @param {Number} sy - 源图像的矩形选择框的左上角 y 坐标
* @param {Number} sWidth - 源图像的矩形选择框的宽度
* @param {Number} sHeight - 源图像的矩形选择框的高度
* @param {Number} dx - 图像的左上角在目标 canvas 上 x 轴的位置
* @param {Number} dy - 图像的左上角在目标 canvas 上 y 轴的位置
* @param {Number} dWidth - 在目标画布上绘制图像的宽度,允许对绘制的图像进行缩放
* @param {Number} dHeight - 在目标画布上绘制图像的高度,允许对绘制的图像进行缩放
* @param {String} c - 矩形的填充色
*/
const roundImage = (context, r, path, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, c) => {
context.save();
roundRect(context, dx, dy, dWidth, dHeight, r, c);
context.fill();
context.clip();
context.drawImage(path, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
context.restore();
};
/**
* 绘制圆形图片
* @param {Object} context - canvas组件的绘图上下文
* @param {String} path - 图片地址
* @param {Number} x - 图片的x坐标
* @param {Number} y - 图片的y坐标
* @param {Number} r - 图片的半径
*/
const circleImage = (context, path, x, y, r) => {
let d = 2 * r;
let cx = x + r;
let cy = y + r;
context.save();
context.beginPath();
context.arc(cx, cy, r, 0, 2 * Math.PI);
context.fill();
context.clip();
context.drawImage(path, x, y, d, d);
context.restore();
};
/**
* canvas多行文本溢出
* @param {Object} context - canvas组件的绘图上下文
* @param {String} text - 文本内容
* @param {Number} maxWidth - 文本最大宽度
* @param {Number} maxRow - 文本最多显示行数
* @param {Number} fontSize - 字体样式
* @param {String} color - 文本颜色
* @param {Number} lineHeight - 文本行高
* @param {Number} x - 文本的x坐标
* @param {Number} y - 文本的y坐标
*/
const drawTextOverflow = (context, text, maxWidth, maxRow, fontSize, color, lineHeight, x, y) => {
let arr = [];
let temp = '';
let row = [];
text = text.replace(/[\r\n]/g, ''); // 去除回车换行符
arr = text.split('');
context.setFontSize(fontSize); // 注意:一定要先设置字号,否则会出现文本变形
context.fillStyle = color;
if (context.measureText(text).width <= maxWidth) {
row.push(text);
} else {
for (let i = 0; i < arr.length; i++) {
// 超出最大行数且字符有剩余,添加...
if (row.length == maxRow && i < arr.length - 1) {
row[row.length - 1] += '...';
break;
}
// 字符换行计算
if (context.measureText(temp).width < maxWidth) {
temp += arr[i];
// 遍历到最后一位字符
if (i === arr.length - 1) {
row.push(temp);
}
} else {
i--; // 防止字符丢失
row.push(temp);
temp = '';
}
}
}
// 绘制文本
for (let i = 0; i < row.length; i++) {
context.fillText(row[i], x, y + i * lineHeight, maxWidth);
}
return row.length * lineHeight; // 返回文本高度
};
util转载于https://www.jianshu.com/p/6c600e740194