211 lines
4.8 KiB
Vue
211 lines
4.8 KiB
Vue
|
|
<template>
|
||
|
|
<!-- 分享海报 -->
|
||
|
|
<view class="share" @click="closeShow" catchtouchmove="preventD">
|
||
|
|
<view v-show="!showPrivacy">
|
||
|
|
<canvas class="canvas" id="myCanvas" canvas-id="myCanvas"></canvas>
|
||
|
|
<view class="btn" @tap.stop="saveImage">保存图片</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<!-- 隐私协议弹窗 -->
|
||
|
|
<privacy-popup :show-dialog="showPrivacy" @close="showPrivacy = false" @agree.stop="showPrivacy = false" @refuse="showPrivacy = false" />
|
||
|
|
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue'
|
||
|
|
import { getOldDay, saveImg, judgePrivacy } from '../common.js'
|
||
|
|
import { post } from '@/api/request.js'
|
||
|
|
import api from '@/api/index.js'
|
||
|
|
import privacyPopup from '../privacyPopup/index.vue'
|
||
|
|
|
||
|
|
export default {
|
||
|
|
components: {
|
||
|
|
privacyPopup
|
||
|
|
},
|
||
|
|
props: {
|
||
|
|
shareImage: {
|
||
|
|
type: String,
|
||
|
|
default: '',
|
||
|
|
}
|
||
|
|
},
|
||
|
|
setup(props, context) {
|
||
|
|
const data = reactive({
|
||
|
|
canvasWidth: {},
|
||
|
|
ctx: null,
|
||
|
|
showImage: '',
|
||
|
|
avatar: '',
|
||
|
|
faceImg: '',
|
||
|
|
Color: uni.getStorageSync('theme_color'),
|
||
|
|
showPrivacy: false,
|
||
|
|
shareImage: '',
|
||
|
|
rate: 0
|
||
|
|
})
|
||
|
|
|
||
|
|
// 关闭
|
||
|
|
function closeShow() {
|
||
|
|
context.emit('closeShow')
|
||
|
|
}
|
||
|
|
|
||
|
|
const getShareImg = async () => {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
uni.getImageInfo({
|
||
|
|
src: props.shareImage,
|
||
|
|
success: function(res) {
|
||
|
|
data.rate = res.height / res.width
|
||
|
|
resolve(res.path)
|
||
|
|
},
|
||
|
|
fail(err) {
|
||
|
|
reject()
|
||
|
|
}
|
||
|
|
})
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
function drawCanvas() {
|
||
|
|
console.log(data.ctx)
|
||
|
|
data.ctx.setFontSize(20)
|
||
|
|
data.ctx.setFillStyle('white')
|
||
|
|
data.ctx.fillRect(0, 0, data.canvasWidth.width, data.canvasWidth.height)
|
||
|
|
data.ctx.drawImage(data.avatar, 20, 20, 40, 40)
|
||
|
|
data.ctx.setFontSize(14)
|
||
|
|
data.ctx.setFillStyle('#222')
|
||
|
|
var nickname = uni.getStorageSync('nickname')
|
||
|
|
data.ctx.fillText(nickname, 70, 35)
|
||
|
|
data.ctx.setFontSize(13)
|
||
|
|
data.ctx.setFillStyle('#777')
|
||
|
|
data.ctx.fillText(getOldDay(), 70, 55)
|
||
|
|
data.ctx.drawImage(data.shareImage, 30, 80, 211, 211 * data.rate)
|
||
|
|
data.ctx.drawImage(data.faceImg, 90, 220, 92, 92)
|
||
|
|
|
||
|
|
data.ctx.draw()
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取单张图片信息
|
||
|
|
const getImageInfo = async (imgSrc) => {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
uni.getImageInfo({
|
||
|
|
src: imgSrc,
|
||
|
|
success: function(image) {
|
||
|
|
resolve(image.path)
|
||
|
|
},
|
||
|
|
fail(err) {
|
||
|
|
reject()
|
||
|
|
}
|
||
|
|
})
|
||
|
|
})
|
||
|
|
}
|
||
|
|
// 获取页面二维码
|
||
|
|
const getFaceImg = () => {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
uni.request({
|
||
|
|
url: api.url + '/api/v1/user/code',
|
||
|
|
method: 'POST',
|
||
|
|
data: {
|
||
|
|
page: 'pages/index/index'
|
||
|
|
},
|
||
|
|
header: {
|
||
|
|
Authorization: uni.getStorageSync('token') || '',
|
||
|
|
appid: api.appId
|
||
|
|
},
|
||
|
|
responseType: 'arraybuffer',
|
||
|
|
success: (res) => {
|
||
|
|
if (res.statusCode === 200) {
|
||
|
|
let base64 = ''
|
||
|
|
const bytes = new Uint8Array(res.data)
|
||
|
|
const len = bytes.byteLength
|
||
|
|
for (let i = 0; i < len; i++) {
|
||
|
|
base64 += String.fromCharCode(bytes[i])
|
||
|
|
}
|
||
|
|
base64 = `data:image/png;base64,${btoa(base64)}`
|
||
|
|
resolve(base64)
|
||
|
|
} else {
|
||
|
|
reject('')
|
||
|
|
}
|
||
|
|
}
|
||
|
|
})
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
onMounted(() => {
|
||
|
|
uni.showLoading({
|
||
|
|
title: '二维码生成中...'
|
||
|
|
})
|
||
|
|
const instance = getCurrentInstance()
|
||
|
|
setTimeout(() => {
|
||
|
|
const query = uni.createSelectorQuery().in(instance)
|
||
|
|
query.select('#myCanvas').boundingClientRect(async (res) => {
|
||
|
|
data.canvasWidth = res
|
||
|
|
data.ctx = uni.createCanvasContext('myCanvas', instance)
|
||
|
|
data.avatar = await getImageInfo(uni.getStorageSync('avatar'))
|
||
|
|
data.faceImg = await getFaceImg()
|
||
|
|
data.shareImage = await getShareImg()
|
||
|
|
await drawCanvas()
|
||
|
|
uni.hideLoading()
|
||
|
|
}).exec()
|
||
|
|
}, 200)
|
||
|
|
})
|
||
|
|
|
||
|
|
return {
|
||
|
|
...toRefs(data),
|
||
|
|
drawCanvas,
|
||
|
|
closeShow,
|
||
|
|
getFaceImg,
|
||
|
|
getImageInfo,
|
||
|
|
getShareImg
|
||
|
|
}
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
async saveImage() {
|
||
|
|
if(await judgePrivacy()) {
|
||
|
|
this.showPrivacy = true
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
//保存到相册
|
||
|
|
const _this = this
|
||
|
|
uni.canvasToTempFilePath({
|
||
|
|
canvasId: 'myCanvas',
|
||
|
|
success(res) {
|
||
|
|
saveImg(res.tempFilePath)
|
||
|
|
},
|
||
|
|
fail(err) {
|
||
|
|
}
|
||
|
|
}, _this)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style lang="scss" scoped>
|
||
|
|
.share {
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
position: fixed;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
background: rgba($color: #000000, $alpha: 0.7);
|
||
|
|
z-index: 202;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
justify-content: center;
|
||
|
|
.canvas {
|
||
|
|
width: 275px;
|
||
|
|
height: 355px;
|
||
|
|
box-sizing: border-box;
|
||
|
|
margin: 0 auto;
|
||
|
|
background-color: #fff;
|
||
|
|
}
|
||
|
|
.btn {
|
||
|
|
color: #fff;
|
||
|
|
background-color: v-bind('Color');
|
||
|
|
font-size: 28rpx;
|
||
|
|
width: 300rpx;
|
||
|
|
height: 70rpx;
|
||
|
|
line-height: 70rpx;
|
||
|
|
text-align: center;
|
||
|
|
margin: 60rpx auto 0;
|
||
|
|
border-radius: 10rpx;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|