小程序,js的canvas绘制方法封装
程序员文章站
2022-05-30 09:26:17
...
小程序绘制
1.wxml结构
<view id='canvas_box' class='canvas_box'>
<canvas canvas-id="canvas_cover" class="canvas_cover" ></canvas>
</view>
2. //引入base64.js
const base64 = require('../../utils/base64.js')
//创建base64.js文件,复制下面代码,保存
const fsm = wx.getFileSystemManager();
function base64src(base64data, cb) {
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || [];
if (!format) {
return (new Error('ERROR_BASE64SRC_PARSE'));
}
const filePath = `${wx.env.USER_DATA_PATH}/${new Date().getTime()}.${format}`;
const buffer = wx.base64ToArrayBuffer(bodyData);
fsm.writeFile({
filePath,
data: buffer,
encoding: 'binary',
success() {
setTimeout(() => {
fsm.removeSavedFile({
filePath
})
},100);
cb(filePath);
},
fail() {
return (new Error('ERROR_BASE64SRC_WRITE'));
},
});
};
export { base64src };
3.//封装方法
buildBossImg: function (download) {
let self = this;
new Promise((resolve,reject)=>{
// 排行数据
let self = this;
let value = wx.getStorageSync('userType'); // !!value?1:2 3-18都展示所有
statisticsService.getStatisticalRank({
businessId: self.data.businessId,
taskId: self.data.taskId,
sort: 1,
type: 0,
pageIndex: 1,
pageSize: 3
}, (err, res) => {
res.data.employeeList.forEach((item) => { //字数长度处理
if (item.name){
item.name = item.name.length > 4 ? item.name.substring(0, 4) : item.name;
}
if (item.nickname){
item.nickname = item.nickname.length > 4 ? item.nickname.substring(0, 4) : item.nickname;
}
})
res.data.customerList.forEach((item) => {
if (item.nickname){
item.nickname = item.nickname.length > 4 ? item.nickname.substring(0, 4) : item.nickname
}
})
self.setData({
rankList: res.data
})
resolve(self.data.rankList)
})
}).then((result)=>{
wx.createSelectorQuery().in(this).select('.canvas_box').fields({
size: true
}, (box) => {
console.log('开始绘图',box);
let rate = box.width / 580,
employeeList = result.employeeList,
customerList = result.customerList,
paintData = self.data.paintData;
let
qrcodeInfo = {
source: null,
size: {
width: 75,
height: 75
}
};
const ctx = wx.createCanvasContext('canvas_cover', this);
//绘制文字超出打点
function fillText(ctx, str, fontSize, color, x, y) {
ctx.setTextBaseline('top');
ctx.setFontSize(fontSize);
ctx.setFillStyle(color);
// ctx.fillText(str, x, y);
let maxWidth = box.width - x,
maxLength = Math.floor(maxWidth / fontSize);
if (str.length <= maxLength) {
ctx.fillText(str, x, y, maxWidth);
} else {
ctx.fillText(str.substring(0, maxLength - 3) + '...', x, y, maxWidth);
}
}
Promise.all([
new Promise((resolve, reject) => {
//图片转换
wx.getImageInfo({
src: 'https://xxx.cn/beta/00000000-0000-0000-0000-000000000000/KMA/miniapp/canvas-bg.png',
success: resolve,
fail: reject
})
// resolve('/images/report_img2.png');
}),
new Promise((resolve, reject) => { //转发标识接口
activityService.getforwardKey(option, (err, res) => {
if (!!res && res.status == 0) {
self.data.myforwardKey = res.data.forwardKey;
self.data.rootUserId = res.data.rootUserId;
}
resolve(null);
});
}).then((res)=>{
return new Promise((resolve,reject)=>{ //活动详情接口
activityService.activityInfo(self.data.taskId, (err, res) => {
if (err) return self.errMessage(err);
if (res.status !== 0) return self.errMessage(res.message);
self.setData({
h5Info: res.data,
type: res.data.manuscriptType
})
resolve(res.data)
});
})
}).then((result)=>{
return new Promise((resolve,reject)=>{ //绘制二维码
var id = self.data.taskId;
let _url = result.url;
_url = self.data.h5Info.manuscriptType == 3 ? _url.replace('//', '$').split('/')[0].replace('$', '//') + '/article?id=' + self.data.h5Info.relationId : _url;
console.log("转发id", self.data.myforwardKey, "url", `${_url}?rootUserId=${self.data.rootUserId}&forwardKey=${self.data.myforwardKey}`)
//请求获取二维码接口
activityService.creatQrcode(JSON.stringify({
"width": 430,
"type": 'link',
"id": id,
"src": `${_url}?rootUserId=${self.data.rootUserId}&forwardKey=${self.data.myforwardKey}`
}), function (err, res) {
if (res.status == 0) {
base64.base64src(res.data.file, res => {
console.log(res) // 返回图片地址,直接赋值到image标签即可
wx.getImageInfo({
src: res,
success: resolve,
fail: reject
})
});
}
})
})
})
]).then((result) => {
qrcodeInfo.source = result[1];
ctx.drawImage(result[0].path, 0, 0, 580 * rate, 534 * rate); //绘制背景
// 绘制小程序码
ctx.drawImage(qrcodeInfo.source.path, 21 * rate, 130 * rate, qrcodeInfo.size.width, qrcodeInfo.size.width);
fillText(ctx, '扫码参加本活动', 20 * rate, '#B1BFCD', 25 * rate, 280 * rate);
fillText(ctx, '累计总获客', 20 * rate, '#3C4A55', 243 * rate, 31 * rate);
ctx.setFontSize(40 * rate);
let target_left = ctx.measureText(String(utils.convertJoinCount(paintData.userCount))).width / 2,
textWidth = target_left.toFixed(1);
console.log("字体宽度", target_left, "222", textWidth, "计算", (box.width / 2) - textWidth)
fillText(ctx, `${utils.convertJoinCount(paintData.userCount)}`, 40 * rate, '#24D0C6', (box.width / 2) - textWidth, 56 * rate);
fillText(ctx, '总投入', 20 * rate, '#B1BFCD', 190 * rate, 150 * rate);
fillText(ctx, `¥${utils.convertJoinCount(paintData.totalInvestment)}`, 20 * rate, '#FA766B', 290 * rate, 150 * rate);
fillText(ctx, '总转发', 20 * rate, '#B1BFCD', 395 * rate, 150 * rate);
fillText(ctx, `${utils.convertJoinCount(paintData.totalForwardCount)}`, 20 * rate, 'rgba(36,208,198,1)', 490 * rate, 150 * rate);
fillText(ctx, '总浏览', 20 * rate, '#B1BFCD', 190 * rate, 195 * rate);
fillText(ctx, `${utils.convertJoinCount(paintData.totalBrowseCount)}`, 20 * rate, 'rgba(36,208,198,1)', 310 * rate, 195 * rate);
fillText(ctx, '总客户', 20 * rate, '#B1BFCD', 395 * rate, 195 * rate);
fillText(ctx, `${utils.convertJoinCount(paintData.totalUserCount)}`, 20 * rate, 'rgba(36,208,198,1)', 490 * rate, 195 * rate);
fillText(ctx, '总浏览时长', 20 * rate, '#B1BFCD', 190 * rate, 240 * rate);
fillText(ctx, `${(paintData.totalAccessTimeCount)}min`, 20 * rate, 'rgba(36,208,198,1)', 300 * rate, 240 * rate);
fillText(ctx, '总预约', 20 * rate, '#B1BFCD', 395 * rate, 240 * rate);
fillText(ctx, `${utils.convertJoinCount(paintData.totalServiceCount)}`, 20 * rate, 'rgba(36,208,198,1)', 490 * rate, 240 * rate);
fillText(ctx, '员工排行', 21 * rate, '#3C4A55', 40 * rate, 330 * rate);
fillText(ctx, '客户排行', 21 * rate, '#3C4A55', 310 * rate, 330 * rate);
// 员工排行
fillText(ctx, `${!!employeeList[0] ? (employeeList[0].name || employeeList[0].nickname) : '暂无'}`, 21 * rate, '#3C4A55', 95 * rate, 385 * rate);
fillText(ctx, `${!!employeeList[0] ? utils.convertJoinCount(employeeList[0].marketingForce) + '分' : '0分'}`, 21 * rate, '#F68411', 195 * rate, 385 * rate);
fillText(ctx, `${!!employeeList[1] ? (employeeList[1].name || employeeList[1].nickname) : '暂无'}`, 21 * rate, '#3C4A55', 95 * rate, 432 * rate);
fillText(ctx, `${!!employeeList[1] ? utils.convertJoinCount(employeeList[1].marketingForce) + '分' : '0分'}`, 21 * rate, '#F68411', 195 * rate, 432 * rate);
fillText(ctx, `${!!employeeList[2] ? (employeeList[2].name || employeeList[2].nickname) : '暂无'}`, 21 * rate, '#3C4A55', 95 * rate, 479 * rate);
fillText(ctx, `${!!employeeList[2] ? utils.convertJoinCount(employeeList[2].marketingForce) + '分' : '0分'}`, 21 * rate, '#F68411', 195 * rate, 479 * rate);
// 客户排行
fillText(ctx, `${!!customerList[0] ? customerList[0].nickname : '暂无'}`, 21 * rate, '#3C4A55', 360 * rate, 385 * rate);
fillText(ctx, `${!!customerList[0] ? utils.convertJoinCount(customerList[0].marketingForce) + '分' : '0分'}`, 21 * rate, '#F68411', 465 * rate, 385 * rate);
fillText(ctx, `${!!customerList[1] ? customerList[1].nickname : '暂无'}`, 21 * rate, '#3C4A55', 360 * rate, 434 * rate);
fillText(ctx, `${!!customerList[1] ? utils.convertJoinCount(customerList[1].marketingForce) + '分' : '0分'}`, 21 * rate, '#F68411', 465 * rate, 434 * rate);
fillText(ctx, `${!!customerList[2] ? customerList[2].nickname : '暂无'}`, 21 * rate, '#3C4A55', 360 * rate, 481 * rate);
fillText(ctx, `${!!customerList[2] ? utils.convertJoinCount(customerList[2].marketingForce) + '分' : '0分'}`, 21 * rate, '#F68411', 465 * rate, 481 * rate);
ctx.draw(true, setTimeout(() => {
self.saveImage();
}, 1000));
})
}).exec();
})
},
//canvas导出为图片
saveImage: function() {
let self = this;
wx.createSelectorQuery().in(this).select('.canvas_box').fields({
size: true
}, (box) => {
wx.canvasToTempFilePath({
fileType: "png",
destWidth: box.width * 6,
destHeight: box.height * 6,
canvasId: 'canvas_cover',
success: (res) => {
self.data.imgSrc = res.tempFilePath;
wx.hideLoading();
}
}, self)
}).exec();
},
// 下载图片
downloadImg: function() {
let self = this;
wx.showLoading({
title: '图片下载中'
});
wx.saveImageToPhotosAlbum({
filePath: self.data.imgSrc,
success: (res) => {
self.setData({
coverSaveStatus: 1
});
wx.hideLoading();
wx.showToast({
title: "图片下载成功"
})
},
fail: (err) => {
wx.hideLoading();
utils.toast.fail({
title: "图片下载失败"
});
console.error("图片下载失败", err);
self.setData({
coverSaveStatus: 2
});
}
}, self);
}
效果
js绘制海报
function IEVersion() {
//取得浏览器的userAgent字符串
var userAgent = navigator.userAgent;
//判断是否IE浏览器
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1;
if (isIE) {
var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
reIE.test(userAgent);
var fIEVersion = parseFloat(RegExp["$1"]);
if (fIEVersion < 10 || !isSupportPlaceholder()) {
return true;
}
} else {
return false;
}
}
let createPoster = (json, callback) => {
if(IEVersion()){
callback('');
return false;
}
let posterWrap = $('<div></div>');
let str = `<canvas id="poster_canvas" width="320" height="615" style="position:absolute;top:0;left:0;z-index:-10;background-color:red;"></canvas><div id="poster_qrcode"></div>`;
posterWrap.html(str);
$("body").append(posterWrap);
let canvas = posterWrap.find('#poster_canvas')[0];
let ctx = canvas.getContext('2d');
let img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.imageSmoothingEnabled = false; //抗锯齿
img.src = json.cover;
img.onload = (a)=> {
var timer = setInterval(function(){
if(img.complete) {
let cover_H = (img.height / img.width * 375);
// ctx.drawImage(img,0,0,250 * 1.5,cover_H);
// clearInterval(timer);
let ratio = window.devicePixelRatio || 1, //获取设备像素比
oldWidth = canvas.width,
oldHeight = canvas.height;
canvas.width = oldWidth * ratio;
canvas.height = oldHeight * ratio;
canvas.style.width = oldWidth + 'px';
canvas.style.height = oldHeight + 'px';
ctx.scale(ratio, ratio);
if(img.width > 320){ //大于默认尺寸则进行裁剪
ctx.drawImage(img,img.width/2 - 100, 0, img.width, img.height,0,0,img.width, img.height);
}else{
ctx.drawImage(img,0,0,img.width, img.height);
}
clearInterval(timer);
ctx.rect(0,335 * 1.5,250 * 1.5,80 * 1.5);
ctx.fillStyle="#ffffff";
ctx.fill();
new QRCode(posterWrap.find('#poster_qrcode')[0], {
text: '自定义',
width: 60*1.5,
height: 60*1.5,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
// 绘制标题、描述
ctx.font = "400 16px Arial"; //设置字体
ctx.textBaseline = 'top'; //在绘制文本时使用的当前文本基线
ctx.fillStyle="#000000";
if(ctx.measureText(json.name).width > 210 ){
let maxLength = Math.floor(210 / ctx.measureText('啊').width);
json.name = json.name.substring(0, maxLength-2) + '...';
}
ctx.fillText (json.name, 13 * 1.5, 355 * 1.5, 150 * 1.5);
ctx.font = "400 14px Arial"; //设置字体
ctx.textBaseline = 'top'; //在绘制文本时使用的当前文本基线
ctx.fillStyle="#999999";
ctx.fillText ('长按识别二维码有惊喜', 12 * 1.5, 375 * 1.5, 150 * 1.5);
//绘制二维码
posterWrap.find('#poster_qrcode').find('img').on('load', function(){
ctx.drawImage(posterWrap.find('#poster_qrcode').find('img')[0],145 * 1.5,343 * 1.5,60 * 1.5,60 * 1.5);
api.request("uploadImageForBase64", { base64Files: [{ content: canvas.toDataURL('image/png') }] }, result => {
posterWrap.remove();
callback(result.status == 0 ? result.data[0].file : "");
});
})
}
},50);
}
}
上一篇: 微信第三方代公众号发起网页授权
下一篇: 胖大海之秋天解燥良药篇