项目场景:
提项目场景:在uniapp中制作分享海报,使用canvas制作并保存到本地,做了好久终于做完了!
解决方案:
第一步:制作页面:
<view class="popup">
<uni-popup ref="popup" type="center" background-color="none">
<view class="hb" ref="imageTest" id="imageTest">
<view class="hb-bg" ref="bgImage" id="bgImage">
<u-image width="300px" :src="backgroundPath" mode="widthFix"></u-image>
</view>
<view class="hb-content">
<view class="hb-content-box">
<u-avatar size="100" :src="avatarPath" id="imageAvatar"></u-avatar>
<view class="hb-box-text">
<view class="hb-name">{{agentName}}</view>
<view class="hb-text">
邀请您参加活动
</view>
</view>
</view>
<view class="hb-code">
<u-image width="50px" :src="qrcodePath" mode="widthFix"></u-image>
</view>
</view>
</view>
<u-button plain type="info" @click="setCanvas" :custom-style="customStyle" style="
width: 85%;
">
保存图片
</u-button>
</uni-popup>
<u-popup v-model="show" mode="center">
<canvas id='canvas' class='canvas' canvas-id="firstCanvas" :style="'width: '+canvasWidth+'px; height: '+canvasHeight+'px;'"></canvas>
</u-popup>
</view>
第二步:将所有的图片转换为临时文件
// 生成二维码临时文件
getNetworkImage(option) {
// var projectId = option.projectId
// if (projectId && projectId != undefined && projectId != "undefined" && projectId != null && projectId !=
// "null") {
// option.projectId = projectId
// } else {
// option.projectId = ""
// }
// var projectDId = option.projectDId
// if (projectDId && projectDId != undefined && projectDId != "undefined" && projectDId != null &&
// projectDId != "null") {
// option.projectDId = projectDId
// } else {
// option.projectDId = ""
// }
// var agentId = option.agentId
// if (agentId && agentId != undefined && agentId != "undefined" && agentId != null && agentId != "null") {
// option.agentId = agentId
// } else {
// option.agentId = ""
// }
// console.log("===getShareCode===")
// console.log("projectId:", option.projectId, ";projectDId:", option.projectDId, ';agentId:', option.agentId)
return new Promise((resolve, reject) => {
// console.log("分享二维码链接:", process.env.VUE_APP_URL +
// "/ins/app/share/project/project/getShareCode?projectId=" + option.projectId +
// "&projectDId=" + option.projectDId + "&agentId=" + option.agentId + "&shareWay=" + "3")
uni.downloadFile({
url: "http://img1.gtimg.com/sh/pics/hv1/209/239/1533/99744479.jpg",
success: (e) => {
const p = e.tempFilePath
if (p.indexOf('json') > -1) {
uni.showToast({
title: '二维码生成失败,花花加急处理中,请优先使用一键分享!',
icon: "none",
duration: 3000
})
this.disabled = true
console.log("disabled", this.disabled)
reject(p)
return false
}
this.qrcodePath = p
resolve(p)
},
fail: (r) => {
uni.showToast({
title: '二维码生成失败,花花加急处理中,请优先使用一键分享!',
icon: "none",
duration: 3000
})
this.disabled = true
reject(r)
}
})
})
},
//生成海报背景图临时文件
async getBackgroundImage() {
this.backgroundPath = await this.imageDownloadFile(
'http://5b0988e595225.cdn.sohucs.com/images/20190725/9af6a5c7aaad426a8926f7bd4a93f41a.jpeg')
},
//生产头像临时文件
async getAvatarImage() {
this.avatarPath = await this.imageDownloadFile(
'http://img.touxiangwu.com/2020/3/uq6Bja.jpg')
},
//图片临时文件
imageDownloadFile(image) {
return new Promise((resolve, reject) => {
uni.downloadFile({
url: image,
success: (e) => {
const p = e.tempFilePath
if (p.indexOf('json') > -1) {
uni.showToast({
title: '二维码生成失败,花花加急处理中,请优先使用一键分享!',
icon: "none",
duration: 3000
})
this.disabled = true
console.log("disabled", this.disabled)
reject(p)
return false
}
resolve(p)
},
fail: (r) => {
uni.showToast({
title: '二维码生成失败,花花加急处理中,请优先使用一键分享!',
icon: "none",
duration: 3000
})
this.disabled = true
reject(r)
}
})
})
},
第三步:使用canvas绘制,并且保存到本地,
// 保存海报
setCanvas() {
// console.log("qrcodePath",this.qrcodePath)
// this.$refs.popup.open('center')
this.show = true
setTimeout(() => {
this.drawPoster()
}, 1000)
},
drawPoster() {
var that = this
const ctx = uni.createCanvasContext('firstCanvas', this)
var drawImageBackground = that.backgroundPath
var drawAvatarImage = that.avatarPath
var drawImageqrcodePath = this.qrcodePath
// 获取海报背景宽/高
uni.createSelectorQuery().in(this).select('#imageTest').boundingClientRect(function(
rect) { //查询节点信息的对象 返回一个对象
let canvasWidth = that.canvasWidth = rect.width;
let canvasHeight = that.canvasHeight = rect.height;
ctx.clearRect(0, 0, canvasWidth, canvasHeight) // 清除画布
ctx.beginPath(); //开始创建一个路径
ctx.rect(0, 0, canvasWidth, canvasHeight);
ctx.setFillStyle("#FFFFFF") // 背景色
ctx.stroke();
ctx.fill(); //填充
return rect
}).exec();
// 获取海报大图
uni.createSelectorQuery().in(this).select('#bgImage').boundingClientRect(function(rect) {
console.log("海报大图:", rect)
ctx.beginPath()
//绘制图片
ctx.drawImage(drawImageBackground, 0, 0, rect.width, rect.height - 5); //图片
ctx.fill();
ctx.save()
console.log("rect.height", rect.height)
ctx.arc(38, rect.height + 30, 28, 0, 2 * Math.PI) //画一条弧线。创建一个圆
ctx.clip() //从原始画布中剪切任意形状和尺寸。
}).exec()
uni.createSelectorQuery().in(this).select('#bgImage').boundingClientRect(function(rect) {
console.log("头像高度和宽度:", rect)
// 绘制头像
ctx.beginPath()
console.log("drawAvatarImage", drawAvatarImage)
ctx.drawImage(drawAvatarImage, 10, rect.height, 56, 56); //绘制图片
ctx.restore() //任意时间对其进行恢复
ctx.fill();
//绘制文字
ctx.beginPath()
ctx.setFillStyle('#000000'); //文本颜色
ctx.setTextAlign('left') //对齐方式
ctx.setFontSize(15) //字号
ctx.fillText(that.agentName, 80, rect.height + 25) //文本内容及文本位置
ctx.setFillStyle('#999999'); //文本颜色
ctx.setTextAlign('left') //对齐方式
ctx.setFontSize(13) //字号
ctx.fillText(that.activityText, 80, rect.height + 50) //文本内容及文本位置
//绘制二维码
ctx.drawImage(drawImageqrcodePath, rect.width - 60, rect.height + 5, 50, 50); //绘制图片
ctx.fill();
}).exec()
setTimeout(function() { //必须延迟执行 不然H5不显示
ctx.stroke();
// //绘制结束
ctx.draw(false, () => { //必须加上 uniapp 没这儿玩意儿 显示不出来不比原生 不加可以显示
//保存绘图图片,产生临时文件
uni.canvasToTempFilePath({
canvasId: 'firstCanvas',
quality: 1,
complete(reset) {
console.log("保存绘图图片,产生临时文件",reset)
//保存图片
uni.saveImageToPhotosAlbum({
filePath: reset.tempFilePath,
success(resSave) {
setTimeout((resSave) => {
uni.showToast({
title: '保存成功',
icon: 'success'
})
}, 2000)
},
fail(err) {
console.log("err", err)
if (err.errMsg ===
"saveImageToPhotosAlbum:fail:auth denied" ||
err.errMsg ===
"saveImageToPhotosAlbum:fail auth deny" || err
.errMsg ===
"saveImageToPhotosAlbum:fail authorize no response"
) {
uni.showModal({
title: '提示',
content: '未授权相册,请重新授权!',
showCancel: false,
success: modalSuccess => {
//获取权限
uni.openSetting({
success(
settingdata
) {
if (settingdata
.authSetting[
'scope.writePhotosAlbum'
]
) {
console
.log(
'获取权限成功,给出再次点击图片保存到相册的提示。'
)
} else {
console
.log(
'获取权限失败,给出不给权限就无法正常使用的提示'
)
}
}
})
}
})
}
}
})
}
},that)
})
}, 200)
},
最近在做海报,本来打算使用组件的,但是我发现那些组件不怎么好用,所以自己写了一个,如果有哪里写的不对的,请大佬指点一下