575 lines
16 KiB
JavaScript
575 lines
16 KiB
JavaScript
import drawQrcode from '../utils/weapp.qrcode.esm.js'
|
||
|
||
module.exports = Behavior({
|
||
behaviors: [],
|
||
properties: {
|
||
isshow:{
|
||
value:false,
|
||
type:Boolean
|
||
},
|
||
poster_id: {
|
||
type:null
|
||
},
|
||
showcarrfootBol:{
|
||
type:null
|
||
},
|
||
iPnoneBottomBol:{
|
||
type:null
|
||
}
|
||
},
|
||
data: {
|
||
errorFlag:false,
|
||
errorMsg:'',
|
||
poster:'',
|
||
loading:0,
|
||
getFlag:true,
|
||
step:1,
|
||
skipError:false, //是否跳过错误强制生成,将不显示错误信息,该功能还没做
|
||
|
||
unsafeList:[],
|
||
image_security_verification:false,//安全域名验证
|
||
},
|
||
observers:{
|
||
'isshow':function(isshow){
|
||
if(isshow && this.data.poster=='' && this.data.getFlag){
|
||
this.getPosterPic();
|
||
this.data.getFlag=false;
|
||
}
|
||
}
|
||
},
|
||
attached: function(){},
|
||
methods: {
|
||
loadImgError(err){
|
||
this.setData({
|
||
errorFlag:true,
|
||
errorMsg:err.detail.errMsg
|
||
})
|
||
},
|
||
// 隐藏二维码
|
||
clicktapshow() {
|
||
this.setData({
|
||
isshow: false
|
||
});
|
||
this.triggerEvent('closeMethod',{isshow:this.data.isshow})
|
||
// wx.showTabBar({})
|
||
},
|
||
previewImage() {
|
||
wx.showToast({
|
||
title: '长按图片分享好友',
|
||
icon: 'none',
|
||
duration: 1800
|
||
})
|
||
// wx.previewImage({
|
||
// urls: [this.data.poster] // 当前显示图片的链接
|
||
// })
|
||
},
|
||
|
||
|
||
//绘制图片
|
||
drawCanvasImage(ctx,imgInfo){
|
||
|
||
let step = this.data.step;
|
||
ctx.drawImage(imgInfo.img,
|
||
imgInfo.left*step,
|
||
imgInfo.top*step,
|
||
imgInfo.width*step,
|
||
imgInfo.height*step); // 推进去图片
|
||
},
|
||
//绘制圆形图片
|
||
drawCanvasCircular(ctx,imgInfo){
|
||
let step = this.data.step;
|
||
let left = imgInfo.left*step;
|
||
let top = imgInfo.top*step;
|
||
let width = imgInfo.width*step;
|
||
let height = imgInfo.height*step;
|
||
ctx.save();
|
||
ctx.beginPath(); //开始绘制
|
||
ctx.arc(width / 2 + left, height / 2 + top, width / 2, 0, Math.PI * 2, false);
|
||
ctx.clip();
|
||
ctx.drawImage(imgInfo.img,
|
||
left,
|
||
top,
|
||
width,
|
||
height); // 推进去图片
|
||
ctx.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 还可以继续绘制
|
||
},
|
||
//绘制矩形
|
||
drawCanvasFillRect(ctx,obj){
|
||
let step = this.data.step;
|
||
let left = obj.left*step;
|
||
let top = obj.top*step;
|
||
let width = obj.width*step;
|
||
let height = obj.height*step;
|
||
ctx.setFillStyle(obj.color)
|
||
ctx.fillRect(left, top, width, height);
|
||
//ctx.draw();
|
||
},
|
||
//绘制文字
|
||
drawCanvasText(ctx,textInfo){
|
||
let step = this.data.step;
|
||
let size = textInfo.size*step;
|
||
let top = (textInfo.top+textInfo.size)*step;
|
||
let left = (textInfo.left) * step;
|
||
ctx.setFillStyle(textInfo.color);
|
||
|
||
let bold = "normal";
|
||
let italic="normal";
|
||
if(textInfo.bold && textInfo.bold == 1){ //加粗
|
||
bold = "bold";
|
||
}
|
||
if(textInfo.italic && textInfo.italic == 1){ //字体倾斜
|
||
italic="italic";
|
||
}
|
||
ctx.font=italic+" small-caps "+bold+" 30px arial,sans-serif";
|
||
ctx.setFontSize(size);
|
||
if(textInfo.slide && textInfo.slide == 1){ //有删除线
|
||
this.drawCanvasFillRect(ctx,{
|
||
left:textInfo.left,
|
||
top:textInfo.top+(textInfo.size/2),
|
||
width:(ctx.measureText(textInfo.src).width/step),
|
||
height:3,
|
||
color:textInfo.color
|
||
})
|
||
}else if(textInfo.under && textInfo.under == 1){ //有下划线
|
||
this.drawCanvasFillRect(ctx,{
|
||
left:textInfo.left,
|
||
top:textInfo.top+textInfo.size,
|
||
width:(ctx.measureText(textInfo.src).width/step),
|
||
height:3,
|
||
color:textInfo.color
|
||
})
|
||
}
|
||
|
||
ctx.fillText(textInfo.src,left,top);
|
||
},
|
||
/**
|
||
* 绘制多行文字
|
||
* @param {*} ctx
|
||
* @param {*} textInfo
|
||
* width 宽度
|
||
* line 行数
|
||
*/
|
||
drawCanvasLineText(ctx,textInfo){
|
||
let step = this.data.step;
|
||
let size = textInfo.size*step;
|
||
let top = (textInfo.top+textInfo.size)*step;
|
||
let text = textInfo.src; //这是要绘制的文本';
|
||
let chr = text.split(""); //这个方法是将一个字符串分割成字符串数组
|
||
let temp = "";
|
||
let row = [];
|
||
ctx.setFontSize(size)
|
||
ctx.setFillStyle(textInfo.color)
|
||
for (let a = 0; a < chr.length; a++) {
|
||
if (ctx.measureText(temp).width < (textInfo.width*step)) {
|
||
temp += chr[a];
|
||
} else {
|
||
a--; //这里添加了a-- 是为了防止字符丢失,效果图中有对比
|
||
row.push(temp);
|
||
temp = "";
|
||
}
|
||
}
|
||
row.push(temp); //如果数组长度大于2 则截取前两个
|
||
if (row.length > textInfo.line) {
|
||
let rowCut = row.slice(0, row.length);
|
||
let rowPart = rowCut[(textInfo.line-1)];
|
||
let test = "";
|
||
let empty = [];
|
||
for (let a = 0; a < rowPart.length; a++) {
|
||
if (ctx.measureText(test).width < (textInfo.width*step)) {
|
||
test += rowPart[a];
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
empty.push(test);
|
||
let group = empty[0] + "..."
|
||
//这里只显示两行,超出的用...表示
|
||
rowCut.splice((textInfo.line-1), 1, group);
|
||
row = rowCut;
|
||
}
|
||
for (let b = 0; b < row.length; b++) {
|
||
if(b<textInfo.line){
|
||
let bold = "normal";
|
||
let italic="normal";
|
||
if(textInfo.bold && textInfo.bold == 1){ //加粗
|
||
bold = "bold";
|
||
}
|
||
if(textInfo.italic && textInfo.italic == 1){ //字体倾斜
|
||
italic="italic";
|
||
}
|
||
ctx.font=italic+" small-caps "+bold+" 30px arial,sans-serif";
|
||
ctx.setFontSize(size);
|
||
if(textInfo.slide && textInfo.slide == 1){ //有删除线
|
||
this.drawCanvasFillRect(ctx,{
|
||
left:textInfo.left,
|
||
top:textInfo.top+(textInfo.size/2)+(b * textInfo.size+(b*10/step)),
|
||
width:(ctx.measureText(row[b]).width/step),
|
||
height:3,
|
||
color:textInfo.color
|
||
})
|
||
}else if(textInfo.under && textInfo.under == 1){ //有下划线
|
||
this.drawCanvasFillRect(ctx,{
|
||
left:textInfo.left,
|
||
top:textInfo.top+textInfo.size+(b * textInfo.size+(b*10/step)),
|
||
width:(ctx.measureText(row[b]).width/step),
|
||
height:3,
|
||
color:textInfo.color
|
||
})
|
||
}
|
||
ctx.fillText(row[b],textInfo.left*step,top + (b * size+(b*10)))
|
||
}
|
||
|
||
}
|
||
|
||
},
|
||
/**
|
||
* 测量文字width
|
||
* @param {*} ctx
|
||
* @param {*} obj
|
||
* width 宽度
|
||
*/
|
||
measureTextWidth(ctx,obj){
|
||
let {width,text,size} = obj;
|
||
//size = size*contentScale;
|
||
let step = this.data.step;
|
||
let chr = text.split(""); //这个方法是将一个字符串分割成字符串数组
|
||
let temp = "";
|
||
let row = [];
|
||
ctx.setFontSize(size*step)
|
||
for (let a = 0; a < chr.length; a++) {
|
||
if (ctx.measureText(temp).width < (width*step)) {
|
||
temp += chr[a];
|
||
} else {
|
||
a--; //这里添加了a-- 是为了防止字符丢失,效果图中有对比
|
||
row.push(temp);
|
||
temp = "";
|
||
}
|
||
}
|
||
row.push(temp);
|
||
let actualWidth = ctx.measureText(temp).width;
|
||
let actualText = temp;
|
||
if(row.length>1){
|
||
actualWidth = ctx.measureText((row[0]+"...")).width;
|
||
actualText = (row[0]+"...");
|
||
}
|
||
return {actualWidth:((actualWidth)/step),actualText};
|
||
|
||
},
|
||
//导出图片
|
||
toimage(canvasId,posterSize) {
|
||
|
||
return new Promise((resolve,reject)=>{
|
||
wx.canvasToTempFilePath({
|
||
x: 0,
|
||
y: 0,
|
||
// quality:1,
|
||
width: posterSize.width,
|
||
height:posterSize.height,
|
||
destWidth: posterSize.width * 4,
|
||
destHeight: posterSize.height * 4,
|
||
canvasId: canvasId,
|
||
success: (res) => {
|
||
var tempFilePath = res.tempFilePath;
|
||
resolve(tempFilePath);
|
||
},
|
||
fail: (res) => {
|
||
wx.showToast({
|
||
title: '图片导出失败'+res,
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
|
||
}
|
||
},this)
|
||
})
|
||
|
||
},
|
||
drawRoundRectPath(ctx, width, height, radius) {
|
||
ctx.beginPath(0);
|
||
//从右下角顺时针绘制,弧度从0到1/2PI
|
||
ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
|
||
//矩形下边线
|
||
ctx.lineTo(radius, height);
|
||
//左下角圆弧,弧度从1/2PI到PI
|
||
ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
|
||
//矩形左边线
|
||
ctx.lineTo(0, radius);
|
||
//左上角圆弧,弧度从PI到3/2PI
|
||
ctx.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
|
||
//上边线
|
||
ctx.lineTo(width - radius, 0);
|
||
//右上角圆弧
|
||
ctx.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
|
||
//右边线
|
||
ctx.lineTo(width, height - radius);
|
||
ctx.closePath();
|
||
ctx.clip();
|
||
},
|
||
downImage(item){
|
||
if(this.data.image_security_verification){
|
||
return this.readDownPicInfo(item.src)
|
||
}else {
|
||
return this.unsafeReadDownPicInfo(item);
|
||
}
|
||
},
|
||
//下载和读取图片
|
||
readDownPicInfo(url){
|
||
return new Promise((resolve,reject)=>{
|
||
wx.downloadFile({
|
||
url, //仅为示例,并非真实的资源
|
||
success:(res)=> {
|
||
wx.getImageInfo({
|
||
src: res.tempFilePath,
|
||
success (res1) { //确保是一张图片
|
||
resolve({img:res.tempFilePath,width:res1.width,height:res1.height});
|
||
},
|
||
fail:(err)=>{
|
||
this.data.getFlag=true;
|
||
let msg = "确认图片地址是否为404,微信临时地址格式是不是png,不是的话,在服务端响应的 header 中指定合理的 Content-Type 字段,以保证客户端正确处理文件类型。";
|
||
this.setData({
|
||
errorFlag:true,
|
||
errorMsg:"图片读取出错,错误原因:"+err.errMsg+",图片地址:"+url+",微信临时文件地址格式:"+res.tempFilePath+","+msg
|
||
})
|
||
reject({error:'错误'});
|
||
}
|
||
})
|
||
},
|
||
fail:(err)=>{
|
||
this.data.getFlag=true;
|
||
let msg = "未知原因,自行检查图片地址是否存在";
|
||
if(err.errMsg == "downloadFile:fail createDownloadTask:fail url not in domain list" || err.errMsg == "downloadFile:fail url not in domain list"){
|
||
msg = "请查看是否设置downloadFile安全域名";
|
||
}
|
||
this.setData({
|
||
errorFlag:true,
|
||
errorMsg:"图片下载出错,错误原因:"+err.errMsg+",图片地址:"+url+','+msg
|
||
})
|
||
}
|
||
})
|
||
});
|
||
},
|
||
unsafeReadDownPicInfo(item){
|
||
return new Promise((resolve,reject)=>{
|
||
const query = this.createSelectorQuery()
|
||
query.select('#temp_security_id')
|
||
.fields({ node: true, size: true })
|
||
.exec((res) => {
|
||
const canvas = res[0].node
|
||
const ctx = canvas.getContext('2d');
|
||
let frontImg = canvas.createImage()
|
||
frontImg.src = item.src;
|
||
frontImg.onload = (res) => {
|
||
let width = item.width ? item.width : frontImg.width;
|
||
let height = item.height ? item.height : frontImg.height;
|
||
canvas.width = width;
|
||
canvas.height = height;
|
||
ctx.drawImage(frontImg, 0, 0, width, height);
|
||
let imgSrc = canvas.toDataURL('image/png');
|
||
var imgPath = wx.env.USER_DATA_PATH+'/poster_'+this.randomWord(5,10)+ '.png';
|
||
var imageData = imgSrc.replace(/^data:image\/\w+;base64,/, "");
|
||
var fs = wx.getFileSystemManager();
|
||
fs.writeFileSync(imgPath, imageData, "base64");
|
||
this.data.unsafeList.push(imgPath);
|
||
resolve({img:imgPath,width,height});
|
||
}
|
||
frontImg.onerror = (e) => {
|
||
let msg = "图片加载出错,检查图片地址是否存在,能不能在浏览器正常打开,能的话在服务端响应的 header 中指定合理的 Content-Type 字段,以保证客户端正确处理文件类型。";
|
||
this.setData({
|
||
errorFlag:true,
|
||
errorMsg:"图片地址:"+item.src+','+msg
|
||
})
|
||
|
||
}
|
||
})
|
||
|
||
})
|
||
},
|
||
removeUnsafeList(){
|
||
var fs = wx.getFileSystemManager();
|
||
for(let item of this.data.unsafeList){
|
||
fs.unlinkSync(item);
|
||
}
|
||
this.data.unsafeList=[];
|
||
},
|
||
randomWord(min,max){ //随机获取字符串
|
||
let str=(new Date()).valueOf();
|
||
let range=min;
|
||
let arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
|
||
if(arguments.length==2){
|
||
range=Math.round(Math.random()*(max-min))+min;
|
||
}
|
||
for (var i = 0; i < range; i++) {
|
||
let pos = Math.round(Math.random() * (arr.length - 1));
|
||
str += arr[pos];
|
||
}
|
||
return str;
|
||
},
|
||
// 获取海报画布宽高
|
||
getMyCanvasMessage(w,h) {
|
||
return new Promise((resolve,reject)=>{
|
||
wx.getSystemInfo({
|
||
success: (res) => {
|
||
let scale = h/w;
|
||
let width = res.screenWidth - (res.screenWidth*0.2);
|
||
let height = width*scale;
|
||
let contentScale = width/w;
|
||
width=width*this.data.step,height=height*this.data.step;
|
||
resolve({
|
||
//width,height,contentScale
|
||
width:(w*this.data.step),height:(h*this.data.step),contentScale:1
|
||
});
|
||
|
||
},
|
||
fail:(res)=>{
|
||
this.data.getFlag=true;
|
||
}
|
||
})
|
||
})
|
||
|
||
},
|
||
getQRCodeUrl(item){
|
||
return new Promise((resolve,reject)=>{
|
||
let step=this.data.step;
|
||
this.setData({
|
||
tempQRCodeCanvasWidth:item.width*step,
|
||
tempQRCodeCanvasHeight:item.height*step
|
||
},async ()=>{
|
||
|
||
drawQrcode({
|
||
width: (item.width-10)*step,
|
||
height: (item.height-10)*step,
|
||
canvasId: 'tempQRCode',
|
||
background:'#fff',
|
||
_this:this,
|
||
x:5*step,
|
||
y:5*step,
|
||
text: item.src,
|
||
callback:()=>{
|
||
setTimeout(async ()=>{
|
||
let img = await this.toimage('tempQRCode',{
|
||
width:item.width*step,
|
||
height:item.height*step
|
||
});
|
||
resolve(img);
|
||
},500);
|
||
}
|
||
});
|
||
|
||
});
|
||
});
|
||
},
|
||
setProportion(sourceObj,targetObj){
|
||
if(targetObj.height>targetObj.width){
|
||
let p = (sourceObj.height)/targetObj.height;
|
||
targetObj.height = targetObj.height*p;
|
||
targetObj.width = targetObj.width*p;
|
||
}else {
|
||
let p = (sourceObj.width)/targetObj.width;
|
||
targetObj.width = targetObj.width*p;
|
||
targetObj.height = (targetObj.height*p);
|
||
}
|
||
if(targetObj.width>sourceObj.width){
|
||
targetObj.height = targetObj.height / (targetObj.width/sourceObj.width);
|
||
targetObj.width = sourceObj.width;
|
||
}
|
||
if(targetObj.height>sourceObj.height){
|
||
targetObj.width = targetObj.width / (targetObj.height/sourceObj.height);
|
||
targetObj.height = sourceObj.height;
|
||
}
|
||
},
|
||
pxToNum(px){
|
||
let num = px.substring(0,px.length-2);
|
||
return parseInt(num);
|
||
},
|
||
async checkWritePotosAlbum() {
|
||
var _this = this;
|
||
let writePhotosAlbum = await this.getAuthSetting('scope.writePhotosAlbum');
|
||
if(!writePhotosAlbum){
|
||
wx.showModal({
|
||
title: '请开启授权',
|
||
content: '是否跳转设置页开启授权',
|
||
success (res) {
|
||
if (res.confirm) {
|
||
wx.openSetting({
|
||
success(settingdata) {
|
||
if (settingdata.authSetting['scope.writePhotosAlbum']) {
|
||
_this.saveImg();
|
||
} else {
|
||
console.log("还是没授权");
|
||
}
|
||
}
|
||
});
|
||
} else if (res.cancel) {
|
||
console.log('用户点击取消')
|
||
}
|
||
}
|
||
});
|
||
return;
|
||
}
|
||
this.saveImg();
|
||
|
||
|
||
},
|
||
saveImg(){
|
||
|
||
var imgSrc = this.data.poster;
|
||
wx.downloadFile({
|
||
url: imgSrc,
|
||
success: function(res) {
|
||
wx.saveImageToPhotosAlbum({
|
||
filePath: res.tempFilePath,
|
||
success: (data)=> {
|
||
wx.showToast({
|
||
title: '保存成功',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
},
|
||
fail: function(err) {
|
||
console.log(err);
|
||
}
|
||
})
|
||
},
|
||
fail:(err)=>{
|
||
wx.saveImageToPhotosAlbum({
|
||
filePath: imgSrc,
|
||
success: (data)=> {
|
||
wx.showToast({
|
||
title: '保存成功',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
},
|
||
fail: function(err) {
|
||
console.log(err);
|
||
}
|
||
})
|
||
//console.log(err,this.data.poster,"图片下载出错");
|
||
}
|
||
})
|
||
},
|
||
getAuthSetting(authName){
|
||
return new Promise((resolve,reject)=>{
|
||
wx.getSetting({
|
||
success(res) {
|
||
if (!res.authSetting[authName]) {
|
||
wx.authorize({
|
||
scope: authName,
|
||
success() {
|
||
resolve(true);
|
||
},
|
||
fail(){
|
||
resolve(false);
|
||
}
|
||
})
|
||
}else resolve(true);
|
||
},
|
||
fail(){
|
||
resolve(false);
|
||
}
|
||
})
|
||
});
|
||
}
|
||
}
|
||
})
|