<template>
|
<view style="position: fixed;z-index: -9999;">
|
<canvas id="myQrcode" :canvas-id="canvasID" :style="{width:canvasWidth+'px',height:canvasHeight+'px'}"></canvas>
|
<view v-if="qrCode == ''">
|
<QRCode ref="qrcode" />
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import QRCode from "../qr_code/qrcode.vue"
|
var _this;
|
export default {
|
name: 'canvas-images',
|
props: {
|
// canvasID 等同于 canvas-id
|
canvasID: {
|
Type: String,
|
default: 'myQrcode'
|
},
|
canvasWidth: { // 画布宽度
|
Type: 'int',
|
default: 375
|
},
|
canvasHeight: { // 画布高度
|
Type: 'int',
|
default: 650
|
},
|
shareTitle: { // 分享标题
|
Type: 'String',
|
default: '我是这张图片的标题'
|
},
|
goodsTitle: { // 商品宣传标题
|
Type: 'String',
|
default: ''
|
},
|
goodsTitle2: { // 商品宣传标题
|
Type: 'String',
|
default: ''
|
},
|
|
shareImage: { // 分享图片
|
Type: 'String',
|
default: ''
|
},
|
qrSize: { // 二维码大小
|
Type: 'int',
|
default: 100
|
},
|
qrUrl: { // 生成二维码的链接
|
Type: 'String',
|
default: 'https://ext.dcloud.net.cn/plugin?id=5747'
|
}
|
},
|
components: {
|
QRCode
|
},
|
data() {
|
return {
|
qrCode: '', // 二维码
|
localImgPath: '',
|
canvas: undefined
|
}
|
},
|
mounted() {
|
_this = this;
|
},
|
methods: {
|
// downloadImg() {
|
// let that = this
|
// const query = uni.createSelectorQuery()
|
// console.log('canvasID',this.canvasID)
|
// query.select('#myQrcode')
|
// .fields({
|
// node: true,
|
// size: true
|
// })
|
// .exec((res) => {
|
// console.log('query',res)
|
// var canvas = res[0].node
|
// uni.canvasToTempFilePath({
|
// canvasId: this.canvasID,
|
// canvas: canvas,
|
// x: 0,
|
// y: 0,
|
// width: this.canvasWidth,
|
// height: this.canvasHeight,
|
// destWidth: this.canvasWidth,
|
// destHeight: this.canvasHeight,
|
// success(res) {
|
// console.log('二维码临时路径:', res.tempFilePath)
|
// uni.saveImageToPhotosAlbum({
|
// filePath: res.tempFilePath,
|
// success: function() {
|
// console.log('save success');
|
// uni.showToast({
|
// title: '保存成功'
|
// })
|
// },
|
// fail(res) {
|
// console.error(res)
|
// uni.showToast({
|
// title: '保存失败。',
|
// icon: 'error'
|
// })
|
// }
|
// })
|
// },
|
// fail(res) {
|
// console.error('fail', res)
|
|
// uni.showToast({
|
// title: '保存失败',
|
// icon: 'error'
|
// })
|
// }
|
// })
|
|
// })
|
|
// },
|
|
// 创建二维码
|
canvasCreate() {
|
this.localImgPath = this.shareImage
|
console.log('this.shareImage', this.shareImage)
|
if (this.shareImage && this.shareImage.startsWith('https://')) {
|
uni.getImageInfo({
|
src: _this.shareImage,
|
success(res) {
|
console.log('getImageInfo res', res)
|
_this.localImgPath = res.path
|
_this.$refs.qrcode.make({
|
size: _this.qrSize,
|
text: _this.qrUrl
|
})
|
.then(res => {
|
// 返回的res与uni.canvasToTempFilePath返回一致
|
// console.log(res)
|
_this.qrCode = res.tempFilePath;
|
_this.onCanvas();
|
});
|
},
|
fail(error) {
|
this.$message.showToast('加载图片错误')
|
}
|
})
|
} else {
|
_this.$refs.qrcode.make({
|
size: _this.qrSize,
|
text: _this.qrUrl
|
})
|
.then(res => {
|
// 返回的res与uni.canvasToTempFilePath返回一致
|
// console.log(res)
|
_this.qrCode = res.tempFilePath;
|
_this.onCanvas();
|
});
|
}
|
|
|
},
|
// 画图
|
async onCanvas() {
|
uni.showLoading({
|
title: "分享图片生成中..."
|
});
|
const ctx = uni.createCanvasContext(_this.canvasID, _this);
|
// 设置 canvas 背景色
|
ctx.setFillStyle('#FFFFFF');
|
ctx.fillRect(0, 0, _this.canvasWidth, _this.canvasHeight);
|
ctx.setFillStyle('#000000');
|
// 背景图片
|
//需要下载图片
|
|
if (_this.localImgPath) {
|
console.log('localImgPath', _this.localImgPath)
|
ctx.drawImage(_this.localImgPath, 20, 20, 335, 500);
|
}
|
// ctx.setFontSize(18);
|
// ctx.setTextAlign('center');
|
// ctx.fillText(_this.shareTitle, _this.canvasWidth / 2, 30);
|
// 左边标题
|
ctx.setTextAlign('left')
|
ctx.setFontSize(22)
|
_this.writeTextOnCanvas(ctx, 20, 21, _this.goodsTitle, 20, 560);
|
ctx.setTextAlign('left')
|
ctx.setFontSize(16)
|
_this.writeTextOnCanvas(ctx, 20, 21, _this.goodsTitle2, 20, 585);
|
// 设置虚线
|
// ctx.setStrokeStyle('#333333');
|
// ctx.setLineDash([5, 10], 2);
|
// ctx.beginPath();
|
// ctx.moveTo(220, 340);
|
// ctx.lineTo(220, 420);
|
// ctx.stroke();
|
// 二维码
|
ctx.drawImage(_this.qrCode, 250, 520, 100, 100);
|
// ctx.draw();
|
|
// 延迟后渲染至canvas上
|
let pic = await _this.setTime(ctx)
|
_this.$emit('success', pic);
|
},
|
/**
|
* @param {Object} ctx_2d getContext("2d") 对象
|
* @param {int} lineheight 段落文本行高
|
* @param {int} bytelength 设置单字节文字一行内的数量
|
* @param {string} text 写入画面的段落文本
|
* @param {int} startleft 开始绘制文本的 x 坐标位置(相对于画布)
|
* @param {int} starttop 开始绘制文本的 y 坐标位置(相对于画布)
|
*/
|
writeTextOnCanvas(ctx_2d, lineheight, bytelength, text, startleft, starttop) {
|
// 获取字符串的真实长度(字节长度)
|
function getTrueLength(str) {
|
var len = str.length,
|
truelen = 0;
|
for (var x = 0; x < len; x++) {
|
if (str.charCodeAt(x) > 128) {
|
truelen += 2;
|
} else {
|
truelen += 1;
|
}
|
}
|
return truelen;
|
}
|
// 按字节长度截取字符串,返回substr截取位置
|
function cutString(str, leng) {
|
var len = str.length,
|
tlen = len,
|
nlen = 0;
|
for (var x = 0; x < len; x++) {
|
if (str.charCodeAt(x) > 128) {
|
if (nlen + 2 < leng) {
|
nlen += 2;
|
} else {
|
tlen = x;
|
break;
|
}
|
} else {
|
if (nlen + 1 < leng) {
|
nlen += 1;
|
} else {
|
tlen = x;
|
break;
|
}
|
}
|
}
|
return tlen;
|
}
|
for (var i = 1; getTrueLength(text) > 0; i++) {
|
var tl = cutString(text, bytelength);
|
ctx_2d.fillText(text.substr(0, tl).replace(/^\s+|\s+$/, ""), startleft, (i - 1) * lineheight +
|
starttop);
|
text = text.substr(tl);
|
}
|
},
|
// 彻底改成同步 防止拿到的图片地址为空
|
setTime(ctx) {
|
return new Promise((resole, err) => {
|
setTimeout(() => {
|
ctx.draw(false, async () => {
|
let pic = await _this.getNewPic();
|
resole(pic)
|
});
|
}, 600)
|
})
|
},
|
// 获取新的图片地址
|
getNewPic() {
|
return new Promise((resolve, errs) => {
|
setTimeout(() => {
|
uni.canvasToTempFilePath({
|
canvasId: _this.canvasID,
|
quality: 1,
|
complete: (res) => {
|
// 在H5平台下,tempFilePath 为 base64
|
// 关闭showLoading
|
uni.hideLoading();
|
// 储存海报地址 也是分享的地址
|
resolve(res.tempFilePath)
|
}
|
}, _this);
|
}, 200)
|
})
|
},
|
},
|
mounted() {
|
_this = this;
|
}
|
}
|
</script>
|