效果
封装组件,父组件 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 = 90 let strIndex = 223 // 开始截取for ( let i = 0 ; i < _strNum; i++) { strIndex = _strY + i * 40 ctx.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 = 180 let contIndex = 223 // 开始截取for ( let i = 0 ; i < _contNum; i++) { contIndex = _contY + i * 20 ctx.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>