效果
封装组件,父组件 ref 调用 downImgUrl()函数,其他根据自己需求改
<template><view><view class="bgpart"><canvas class="canvas-wrap" canvas-id="canvasID" type="2d"></canvas><view class="popPart"><view><view class="share-list"><view class="share-item flexaround flexalign" @click="shareToFriend(1)"><view class="iconImg flexalign flexaround"><image src="/static/sharePop/share1.png" mode=""></image></view><text class="font26" style="margin-top: 16rpx;">微信</text></view><view class="share-item flexaround flexalign" @click="shareToFriend(2)"><view class="iconImg flexalign flexaround"><image src="/static/sharePop/share2.png" mode=""></image></view><text class="font26" style="margin-top: 16rpx;">朋友圈</text></view><view class="share-item flexaround flexalign" @click="downCli"><view class="iconImg flexalign flexaround" style="width: 88rpx;height: 88rpx;"><u-icon name="download" size="30"></u-icon></view><text class="font26" style="margin-top: 16rpx;">下载</text></view></view></view><view class="share-header flexalign flexaround" style="background: #fff;" @click="$emit('close')">取消</view></view></view></view>
</template><script>import {indexsettingPoster} from "@/api/all.js"export default {name: "sharePoster",props: {},data() {return {logo: '/static/logo.png',bgimg: '',detail: {},imgUrl:'',//完成海报图qrCode:''};},created() {},methods: {// 下载downCli() {if( this.imgUrl && this.imgUrl != ''){{uni.saveImageToPhotosAlbum({filePath: this.imgUrl,success: function () {console.log('save success'); uni.showToast({icon:"none",title:'已下载'})}});}},async downImgUrl(e,url,type) {await indexsettingPoster({url:url}).then(res => {this.bgimg = res.data.posterThumb this.qrCode = res.data.qrCode})let canW = 320;let canH = 450;let ctx = uni.createCanvasContext('canvasID', this);// ctx.setFillStyle("transparent"); //设置canvas背景颜色// ctx.fillRect(0, 0, 346, 500) //设置canvas画布大小ctx.drawImage(this.bgimg, 0, 0, canW, canH) //背景ctx.drawImage(this.logo, 18, 20, 36, 36) //logo// ctx.drawImage(e.dynamicQRcode, 255, 370, 70, 70) //二维码ctx.drawImage(this.qrCode, 230, 370, 70, 70) //二维码//绘制圆形头像this.drawCircular(ctx, e.headPortrait, 26, 398, 40, 40) // 名字ctx.setFontSize(14)ctx.setFillStyle("#ffffff")ctx.fillText(e.nickName, 74, 424)// 绘制标题,多余文字自动换行ctx.setFontSize(26)ctx.setFillStyle("#2C3E68")ctx.textAlign = "center"let str = type ? e.teamName : e.dynamicTitle// 字符串总长度let _strLength = str.length > 24 ? 24 : str.length// 总结截取次数let _strNum = Math.ceil(_strLength / 8)// 每次开始截取字符串的索引let _strHeight = 0// 绘制的字体 x,y的初始位置let _strX = 345 / 2,_strY = 90let strIndex = 223// 开始截取for (let i = 0; i < _strNum; i++) {strIndex = _strY + i * 40ctx.fillText(str.substr(_strHeight + i * 9, 9), _strX, _strY + i * 34)}// 绘制内容ctx.setFontSize(13)ctx.setFillStyle("#4FB0FF")let cont = type ? e.teamContent : e.dynamicDescribe// 字符串总长度let _contLength = cont.length > 120 ? 120 : cont.length// 总结截取次数let _contNum = Math.ceil(_contLength / 20)// 每次开始截取字符串的索引let _contHeight = 0// 绘制的字体 x,y的初始位置let _contX = 345 / 2,_contY = 180let contIndex = 223// 开始截取for (let i = 0; i < _contNum; i++) {contIndex = _contY + i * 20ctx.fillText(cont.substr(_contHeight + i * 20, 20), _contX, _contY + i * 22)}//详情图let img = type ? e.teamPics : e.dynamicPics //团队,动态img.split(',').forEach((el,index)=>{if(index == 0){ctx.drawImage( el , 50, 290, 70, 70) //二维码}else if(index == 1){ctx.drawImage( el , 130, 290, 70, 70) //二维码}else if(index == 2){ctx.drawImage( el , 210, 290, 70, 70) //二维码}})ctx.draw(false, () => {// 返回canvas图片信息uni.canvasToTempFilePath({canvasId: 'canvasID',success: (res) => {this.imgUrl = res.tempFilePath},fail: function(err) {console.log(err)}})})},// 绘制圆形头像drawCircular(ctx, url, x, y, width, height) {//画圆形头像var avatarurl_width = width;var avatarurl_heigth = height;var avatarurl_x = x;var avatarurl_y = y;ctx.save(); //先保存状态,已便于画完园再用ctx.beginPath(); //开始绘制ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);ctx.setFillStyle("#FFFFFF")ctx.fill() //保证图片无bug填充ctx.clip(); //剪切ctx.drawImage(url, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); //推进去图片ctx.restore();},}}
</script><style scoped lang="scss">
.flexaround{display: flex;justify-content: space-around;
}
.flexalign{display: flex;align-items: center;
}
.font26{font-size: 26rpx;font-family: PingFang-SC-Medium;
}.canvas-wrap {margin: 20% 45rpx;width: calc(100% - 90rpx);height: 940rpx;// background-color: }.bgpart {width: 100vw;height: 100vh;background-color: rgba(0, 0, 0, 0.5);position: fixed;left: 0;top: 0;z-index: 99;.popPart {width: 100%;height: 360rpx;background-color: border-radius: 20rpx 20rpx 0 0;position: fixed;left: 0;bottom: 0;z-index: 99;}}.share-header {line-height: 80rpx;}.share-list {margin: 20rpx 0 60rpx 0;display: flex;/* flex-direction: row; */flex-wrap: wrap;.share-item {margin-top: 30rpx;min-width: 20%;flex-direction: column;.iconImg {background-color: border-radius: 50%;image {width: 88rpx;height: 88rpx;}}}}
</style>