直接放代碼 各個地方基本都有註釋
<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>