组件目录 /share-canvas.vue
<template>
<u-popup :show="visiable" closeable @close="hiddenCanvas" zIndex="999999">
<view class="shareModel" @touchstart="" @touchmove="" @touchend="">
<view class="title">分享店铺</view>
<template v-if="visiable">
<canvas canvas-id="posterid" :style="{width:screen_width*375+'px',height:screen_height*0.65+'px'}"
class="myCanvas" disable-scroll="true" @touchstart="" @touchmove="" @touchend=""></canvas>
</template>
<view class="share-bot" @click.stop>
<view class="share-btns">
<!-- <view class="btns-list" @click="handleCopyLink">
<u--image :showLoading="true" :src="copyLink" width="72rpx" height="72rpx" />
<text>复制链接</text>
</view> -->
<view class="btns-list">
<button class="btns-box" open-type="share">
<u--image :showLoading="true" :src="copyLink" width="72rpx" height="72rpx" />
<text>分享链接</text>
</button>
</view>
<view class="btns-list" @click="savePoster(100)">
<u--image :showLoading="true" :src="saveIcon" width="72rpx" height="72rpx" />
<text>保存二维码</text>
</view>
<view class="btns-list" @click="savePoster(200)">
<u--image :showLoading="true" :src="saveIcon" width="72rpx" height="72rpx" />
<text>保存海报</text>
</view>
</view>
</view>
</view>
</u-popup>
</template>
<script>
import {
mapState
} from 'vuex'
import {
createQrCode
} from '@/common/api.js'
export default {
props: {
storeInfo: {
type: Object,
default: () => {}
}
},
data() {
return {
saveIcon: require('../../static/download.png'),
copyLink: require('../../static/copyLink.png'),
goodsIcon: require('../../static/goodsIcon.png'),
qrCode: "",
visiable: false,
screen_height: 0,
screen_width: 0
}
},
computed: {
...mapState(['$userInfo'])
},
created() {
this.screen_height = uni.getSystemInfoSync().windowHeight;
this.screen_width = uni.getSystemInfoSync().windowWidth / 375;
console.log(this.screen_height,'screen_height');
},
methods: {
// 店铺二维码分享
createQrCodeFun() {
uni.showLoading({
title: '二维码加载中...',
mask: true
})
createQrCode({
path: 'pages/home/storePage/index?userGroupAuthId=' + this.storeInfo.userGroupAuthId,
width: 500
}).then(res => {
const {
filePath
} = res.data || {}
// 二维码图片,接口可使用网络地址模拟
this.qrCode = filePath
// 得到二维码绘画
this.setStopter();
}).finally(() => {
uni.hideLoading();
})
},
// 复制链接
handleCopyLink() {
// #ifdef MP-WEIXIN
var shareText = '【' + this.storeInfo.merchantName + '】' + '店铺欢迎您##长按复制此条消息,打开亿联乐购小程序首页即可跳转##' + this
.storeInfo.userGroupAuthId
uni.setClipboardData({
data: shareText,
showToast: false,
success(res) {
console.log("success:" + JSON.stringify(res));
uni.showToast({
title: '复制成功',
icon: 'success'
})
},
fail: () => {
uni.showToast({
title: '复制失败',
icon: 'error'
})
},
complete: () => {}
})
// #endif
},
//显示
showCanvas() {
this.visiable = true
// 得到二维码绘画
this.createQrCodeFun()
},
// 点击关闭
hiddenCanvas() {
this.visiable = false
},
// 绘制海报
async setStopter() {
uni.showLoading({
title: '加载中...',
mask: true
})
var _this = this
var ctx = uni.createCanvasContext('posterid', _this) //创建画笔
// 自适应屏幕关键
let rpx = this.screen_width
ctx.drawImage('/static/share/share.png', 20 * rpx, 0, 330 * rpx, 380 * rpx);
this.canvasFont(ctx, 16 * rpx, '#2D2D2D', this.storeInfo.merchantName, 100 * rpx, 50 * rpx)
this.drawRoundRect(ctx, 90 * rpx, 70 * rpx, 192 * rpx, 192 * rpx, 12 * rpx, '#F5F5F5')
let banerQrCode = await this.downloadImage(this.qrCode)
if (banerQrCode.tempFilePath) {
ctx.save()
ctx.drawImage(banerQrCode.tempFilePath, 100 * rpx, 80 * rpx, 172 * rpx, 172 * rpx);
ctx.restore()
}
this.canvasFont(ctx, 14 * rpx, '#999999', '(微信扫描二维码即可进入)', 100 * rpx, 280 * rpx)
ctx.drawImage('../../static/goodsIcon.png', 265 * rpx, 290 * rpx, 50 * rpx, 50 * rpx);
const {
portraitFile,
userName = "亿联乐购用户"
} = this.$userInfo
if (portraitFile && portraitFile.staticPath) {
let userPortraitFile = await this.downloadImage(portraitFile.staticPath)
ctx.save()
ctx.drawImage(userPortraitFile.tempFilePath, 50 * rpx, 300 * rpx, 32 * rpx, 32 * rpx);
ctx.restore()
} else {
ctx.drawImage('/static/share/user.png', 50 * rpx, 300 * rpx, 32 * rpx, 32 * rpx)
}
this.canvasFont(ctx, 12 * rpx, '#2D2D2D', userName, 90 * rpx, 320 * rpx)
// ctx.draw()
ctx.draw(true, () => {
uni.hideLoading()
})
console.log('绘画完成')
},
canvasFont(ctx, fs, color, txt, x, y) { //绘制文字
ctx.setFontSize(fs)
ctx.setFillStyle(color)
ctx.fillText(txt, x, y)
},
//圆角矩形
drawRoundRect(ctx, x, y, width, height, radius, color) {
ctx.save();
ctx.beginPath();
ctx.setFillStyle(color);
ctx.setStrokeStyle(color)
ctx.setLineJoin('round'); //交点设置成圆角
ctx.setLineWidth(radius);
ctx.strokeRect(x + radius / 2, y + radius / 2, width - radius, height - radius);
ctx.fillRect(x + radius, y + radius, width - radius * 2, height - radius * 2);
ctx.stroke();
ctx.closePath();
},
downloadImage(url) { //绘制网络图片,网络图片需要先缓存到本地再绘制
return new Promise((resolve, reject) => {
uni.downloadFile({ // 还可以使用 uni.getImageInfo 方法
url: url,
success: (res) => {
return resolve(res)
},
fail: (err) => {
return reject(err)
}
})
})
},
// 保存图片手机本地(二维码)
saveImageToPhotosQrCode() {
uni.showLoading({
title: '二维码下载中'
});
const that = this;
uni.downloadFile({
url: that.qrCode, //二维码的地址
success: function(res) {
const tempFilePath = res.tempFilePath //通过res中的tempFilePath 得到需要下载的图片地址
uni.saveImageToPhotosAlbum({
filePath: tempFilePath,
success: () => {
uni.hideLoading();
uni.showToast({
title: '二维码已存入相册'
});
},
fail: () => {
uni.hideLoading();
uni.showToast({
title: '下载失败',
icon: 'error'
});
},
complete: () => {}
});
}
})
},
// 保存海报
saveImageToPhotosPoster() {
uni.showLoading({
title: '海报下载中...'
});
uni.canvasToTempFilePath({
canvasId: 'posterid',
success: function(res) {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(result) {
uni.hideLoading()
uni.showToast({
title: '海报已存入相册',
icon: 'success',
duration: 2000
})
},
fail: () => {
uni.hideLoading()
}
})
},
complete(res) { //不管成功或者失败都会执行
console.log('canvas转成图片结果', res)
}
}, this);
},
//保存海报和二维码
saveImageToPhotosAlbumFun(flag) {
if (flag === 100) {
// 保存二维码
this.saveImageToPhotosQrCode()
} else {
// 保存海报
this.saveImageToPhotosPoster()
}
},
//保存图片到相册
savePoster(flag) {
const that = this;
// #ifdef MP-WEIXIN
uni.getSetting({
success: res => {
if (res.authSetting['scope.writePhotosAlbum']) {
that.saveImageToPhotosAlbumFun(flag)
} else {
uni.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
that.saveImageToPhotosAlbumFun(flag)
},
fail: () => {
uni.showModal({
title: '提示',
content: '请先在设置页面打开“保存相册”使用权限',
confirmText: '去设置',
cancelText: '算了',
success: data => {
if (data.confirm) {
uni.openSetting();
}
}
});
},
complete: res => {}
});
}
}
});
// #endif
}
}
}
</script>
<style lang="scss" scoped>
// 边框样式
button::after {
border: 0;
}
.shareModel {
width: 100%;
background-color: #F5F5F5;
color: #2D2D2D;
.title {
padding: 32rpx;
text-align: center;
font-size: 32rpx;
font-weight: bold;
}
.share-container {
margin: 0 80rpx 24rpx;
padding: 32rpx;
height: 100%;
background: rgba(255, 255, 255, 0.39);
box-shadow: 0 6rpx 20rpx rgba(110, 108, 108, 0.1);
border-radius: 24rpx;
.merchant-info {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.merchantName {
margin-bottom: 48rpx;
font-weight: bold;
font-size: 32rpx;
}
.tip {
padding: 24rpx 0 48rpx;
color: #999999;
font-size: 24rpx;
}
.store-img {
padding: 20rpx;
background-color: #F5F5F5;
.img {
width: 380rpx;
height: 380rpx;
}
}
}
.user-info {
display: flex;
align-items: center;
justify-content: space-between;
.header-name {
display: flex;
align-items: center;
text {
margin-left: 12rpx;
}
}
}
}
.share-bot {
width: 100%;
background: #FFFFFF;
.share-btns {
display: flex;
justify-content: space-around;
align-items: center;
width: 100%;
padding: 30rpx 0;
.btns-list,
.btns-share,
.btns-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #FFFFFF;
text {
color: #2D2D2D;
font-size: 28rpx;
margin-top: 8rpx;
}
}
}
}
}
</style>
父组件使用
父组件引入
<share-model-canvas ref="poster" :storeInfo="merchantInfo"></share-model-canvas>
<script>
import ShareModelCanvas from './shareModel/share-canvas.vue'
//显示绘制店铺海报
sharePoster() {
// canvas操作
this.$refs.poster.showCanvas()
}
</script>
效果图