直接放代码 各个地方基本都有注释
<template>
<view class="poster">
<canvas v-if="getImg==''" style="width: 315px;height: 502px;position: fixed;left: 999999rpx;" canvas-id="poster1" class="post"></canvas>
<image v-if="getImg!=''" :src="getImg" style="width: 630rpx;height: 1004rpx;" class="getimg" />
<button @click="preservation" v-if="getImg!=''" class="width290 height76 radius38 font32 weight400 line76 colorFFFFFF absolute left58" style="background-color: #81D8D0;top:1150rpx;">保存至相册</button>
<button open-type="share" v-if="getImg!=''" class="width290 height76 radius38 font32 weight400 line76 colorFFFFFF absolute right48" style="background-color: #81D8D0;top:1150rpx;">推荐给好友</button>
</view>
</template>
<script>
import wepy from '@wepy/core';
import lbajax from '../lbts/ajax.js';
import testMixin from '../mixins/test.js';
wepy.page({
mixins: [ testMixin ],
data: {
getImg: '',
imgUrl:'',
show: false,
QrCode:'',
posterInfo:{},
state:'',
route:'',
id:'',
},
onShareAppMessage(){
return {
title:this.posterInfo.shopName,
path:this.route+'?ph='+this.posterInfo.phone+'&id='+this.id,
imageUrl: this.imgUrl
};
},
async onLoad(options) {
console.log(getApp().$wepy.$options.globalData)
new Promise(this.validityInfo)
.then((res)=>{
if(res==1){
this.state = options.c;
this.id=options.id;
this.imgUrl=options.imgUrl;
wx.showLoading({
title: '加载中'
});
let data={
storeId:getApp().$wepy.$options.globalData.poster.id,
}
if(options.c==0){
this.route="/infoPages/temlete"
data.paths="infoPages/temlete"
}else{
this.route="/power/temleteMore"
data.paths="power/temleteMore"
}
console.log(data,'data')
lbajax({
url:'/wx/getQrCode2',
method:'POST',
data:data,
}).then((res)=>{
this.posterInfo=getApp().$wepy.$options.globalData.poster
this.QrCode=res
this.init();
})
}else{
wx.showLoading({
title: '请先登录!'
});
setTimeout(function () {
wx.navigateTo({
url: '/power/login'
});
wx.hideLoading()
}, 2000)
}
}).catch((err)=>{
console.log(err)
})
},
methods: {
/**
* 验证是否登录
* */
validityInfo(resolve, reject){
console.log(getApp().$wepy.$options.globalData.poster)
let info = getApp().$wepy.$options.globalData.poster;
if(info.phone && info.headImg){
resolve(1);
}else{
resolve(0);
}
},
/**
* 保存到相册
* */
preservation() {
wx.getSetting({
success: (res) => {
// 如果没有则获取授权
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
wx.saveImageToPhotosAlbum({
filePath: this.getImg,
success: () => {
wx.showToast({
title: '保存成功'
})
},
fail() {
wx.showToast({
title: '保存失败',
icon: 'none'
})
}
})
},
})
} else {
// 有则直接保存
wx.saveImageToPhotosAlbum({
filePath: this.getImg,
success() {
wx.showToast({
title: '保存成功'
})
},
fail() {
wx.showToast({
title: '保存失败',
icon: 'none'
})
}
})
}
},
})
},
/**
* 如果图片加载失败返回上一页
* */
toBack(){
wx.navigateBack()
},
roundRect(ctx, x, y, w, h, r) {
// 开始绘制
ctx.beginPath()
// 因为边缘描边存在锯齿,最好指定使用 transparent 填充
// 这里是使用 fill 还是 stroke都可以,二选一即可
ctx.setFillStyle('transparent')
// ctx.setStrokeStyle('transparent')
// 左上角
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
// border-top
ctx.moveTo(x + r, y)
ctx.lineTo(x + w - r, y)
ctx.lineTo(x + w, y + r)
// 右上角
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
// border-right
ctx.lineTo(x + w, y + h - r)
ctx.lineTo(x + w - r, y + h)
//右下五角
// ctx.lineTo(w, h)
// ctx.lineTo(w, h)
//右下有角
ctx.lineTo(x + w, y + h - r)
ctx.lineTo(x + w - r, y + h)
// 右下角
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
// border-bottom
ctx.lineTo(x, y + h)
ctx.lineTo(x, y + h) //注释去掉左下角
// 左下角
ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
// border-left
ctx.lineTo(x, y + r)
ctx.lineTo(x + r, y)
// 这里是使用 fill 还是 stroke都可以,二选一即可,但是需要与上面对应
ctx.fill()
// ctx.stroke()
ctx.closePath()
// 剪切
ctx.clip()
},
headImg(contex, url) {
var avatarurl_width = 37; //绘制的头像宽度
var avatarurl_heigth = 37; //绘制的头像高度
var avatarurl_x = 15; //绘制的头像在画布上的位置
var avatarurl_y = 387; //绘制的头像在画布上的位置
contex.save();
contex.beginPath(); //开始绘制
//先画个圆 前两个参数确定了圆心 (x,y) 坐标 第三个参数是圆的半径 四参数是绘图方向 默认是false,即顺时针
contex.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y,
avatarurl_width / 2, 0,
Math.PI * 2, false);
contex.clip(); //画好了圆 剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内 这也是我们要save上下文的原因
contex.drawImage(url, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片,必须是https图片
contex.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 还可以继续绘制
},
/**
* 客片欣赏海报
* */
appreciate(backimg,ctx){
if (true) { //店铺名字
ctx.setFontSize(15);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText(this.posterInfo.shopName, 37, 292);
}
if(true){//客片风格
ctx.setFontSize(13);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText('客片风格:大童', 15, 311+15);
}
if(true){//样片主题
ctx.setFontSize(13);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText('样片主题:童真时刻', 159, 311+15);
}
if (true) { //消费
ctx.setFontSize(13);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText('人均消费:'+this.posterInfo.seryPrice, 15, 344+15);
}
if (true) { //店评分
ctx.setFontSize(13);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText('门店评分:', 159, 344+15);
}
if (true) { //分数星星
var num = 4;
if(!this.posterInfo.storeScore){
this.posterInfo.storeScore=5
}
for(let i=0;i<this.posterInfo.storeScore;i++){
ctx.drawImage('/static/img/score.png', 224+num, 344+5, 12, 12);
num=num+4+12;
}
}
ctx.save();
//分割线
ctx.beginPath(); //开始一个新的路径
ctx.moveTo(300, 377)
ctx.lineTo(15, 377)
ctx.setStrokeStyle('#EBEBEB')
ctx.stroke()
ctx.restore()
this.headImg(ctx, backimg[1])
if (true) { //昵称
ctx.setFontSize(12);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText(this.posterInfo.userName, 58, 397 + 15);
}
if (true) { //长按识别文字
ctx.setFontSize(12);
ctx.setFillStyle('#ADADAD');
ctx.setTextAlign('left');
ctx.fillText('长按识别小程序码', 15, 428 + 15);
}
if (true) { //即可查看精美样片!
ctx.setFontSize(12);
ctx.setFillStyle('#81D8D0');
ctx.setTextAlign('left');
ctx.fillText('即可查看精美样片!', 15, 449 + 15);
}
if (true) { //即可查看精美样片!
ctx.setFontSize(12);
ctx.setFillStyle('#AAAAAA');
ctx.setTextAlign('left');
ctx.fillText('还有更多精彩内容,等着你!', 15, 470 + 15);
}
},
/**
* 客片展示海报
* */
exhibition(backimg,ctx) {
if (true) { //店铺名字
ctx.setFontSize(15);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText(this.posterInfo.shopName, 37, 292);
}
if (true) { //消费
ctx.setFontSize(13);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText('人均消费:'+this.posterInfo.seryPrice, 15, 311 + 17);
}
if (true) { //店评分
ctx.setFontSize(13);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText('门店评分:', 159, 311 + 17);
}
if (true) { //分数星星
var num = 4;
if(!this.posterInfo.storeScore){
this.posterInfo.storeScore=5
}
for(let i=0;i<this.posterInfo.storeScore;i++){
ctx.drawImage('/static/img/score.png', 224+num, 317, 12, 12);
num=num+4+12;
}
}
if (true) { //门店位置
ctx.setFontSize(13);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText('门店位置:', 15, 344 + 17);
}
if (true) { //详细位置
ctx.setFontSize(13);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText(this.posterInfo.address, 80, 344 + 17);
}
ctx.save();
//分割线
ctx.beginPath(); //开始一个新的路径
ctx.moveTo(300, 377)
ctx.lineTo(15, 377)
ctx.setStrokeStyle('#EBEBEB')
ctx.stroke()
ctx.restore()
this.headImg(ctx, backimg[1])
if (true) { //昵称
ctx.setFontSize(12);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText(this.posterInfo.userName, 58, 397 + 15);
}
if (true) { //长按识别文字
ctx.setFontSize(12);
ctx.setFillStyle('#ADADAD');
ctx.setTextAlign('left');
ctx.fillText('长按识别小程序码', 15, 428 + 15);
}
if (true) { //即可查看精美样片!
ctx.setFontSize(12);
ctx.setFillStyle('#81D8D0');
ctx.setTextAlign('left');
ctx.fillText('即可查看精美样片!', 15, 449 + 15);
}
if (true) { //即可查看精美样片!
ctx.setFontSize(12);
ctx.setFillStyle('#AAAAAA');
ctx.setTextAlign('left');
ctx.fillText('还有更多精彩内容,等着你!', 15, 470 + 15);
}
},
/**
* 生成图片
* */
init() {
wx.showLoading({
title: '加载中',
})
//二维码
let qrcode = new Promise((resolve) =>{
wx.getImageInfo({
src: this.QrCode,
success: (res) => {
resolve(res.path)
},
fail: (err) => {
console.log(err)
wx.showToast({
title: '网络错误请重试',
icon: 'loading'
})
this.toBack()
}
});
});
//头像
let headImg = new Promise((resolve) =>{
wx.getImageInfo({
src: this.posterInfo.headImg,
success: (res) => {
resolve(res.path)
},
fail: (err) => {
console.log(err)
wx.showToast({
title: '网络错误请重试',
icon: 'loading',
duration:2000,
success:(res)=>{
this.toBack()
}
})
}
});
});
//大图
let backimg = new Promise((resolve)=> {
wx.getImageInfo({
src:this.imgUrl,
success: (res) => {
resolve(res.path)
},
fail: (err) => {
console.log(err)
wx.showToast({
title: '网络错误请重试',
icon: 'loading',
duration:2000,
success:(res)=>{
this.toBack()
}
})
}
});
});
Promise.all([backimg, headImg,qrcode])
.then((backimg) => {
let ctx = wx.createCanvasContext('poster1', this)
ctx.save()
this.roundRect(ctx, 0, 0, 315, 502, 10);
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, 315, 502);
ctx.drawImage(backimg[0], 0, 0, 315, 260);
ctx.restore()
ctx.drawImage('/static/img/shop.png', 15, 278, 16, 15);
console.log(this.state)
if(this.state==0){
this.exhibition(backimg,ctx);
}else{
this.appreciate(backimg,ctx);
}
//二维码
ctx.drawImage(backimg[2], 200, 387, 100, 100);
ctx.draw(true, (res) => {
wx.canvasToTempFilePath({
canvasId: 'poster1',
destWidth: 315*2,
destHeight: 502*2,
success: (res) => {
this.getImg = res.tempFilePath;
wx.hideLoading()
},
fail: function(res) {
console.log(res)
}
});
})
});
}
}
})
</script>
<style lang="scss" scoped>
page {
background-color: #ffffff;
}
.getimg{
position: absolute;
top: 120rpx;
}
.poster {
display: flex;
// align-items: center;
justify-content: center;
position: fixed;
top: 0;
width: 100%;
height: 100%;
text-align: center;
background: rgba(0, 0, 0, 0.3);
}
button::after{
border: none;
}
</style>