|
|
@@ -0,0 +1,246 @@
|
|
|
+<template>
|
|
|
+ <view >
|
|
|
+ <view class="postcontent" v-if="isShow" @click.stop="isShow=false">
|
|
|
+ <canvas @click.stop="" :style="{ width: canvasW + 'px', height: canvasH + 'px' }" canvas-id="my-canvas"></canvas>
|
|
|
+ <view class="text-center text-white">长按保存图片</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ export default{
|
|
|
+ props:{
|
|
|
+ works: {
|
|
|
+ type: Object,
|
|
|
+ default: {}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data(){
|
|
|
+ return {
|
|
|
+ canvasW: 0,
|
|
|
+ canvasH: 0,
|
|
|
+ ctx: null,
|
|
|
+ isShow: false,
|
|
|
+ imgUrl:'',
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods:{
|
|
|
+ //显示
|
|
|
+ showCanvas(){
|
|
|
+ this.isShow = true
|
|
|
+ this.__init()
|
|
|
+ },
|
|
|
+ //初始化画布
|
|
|
+ async __init(){
|
|
|
+ uni.showLoading({
|
|
|
+ title: '加载中...',
|
|
|
+ mask: true
|
|
|
+ })
|
|
|
+ this.ctx = uni.createCanvasContext('my-canvas', this)
|
|
|
+ // this.canvasW = uni.upx2px(550);
|
|
|
+ this.canvasW = uni.getSystemInfoSync().windowWidth-uni.upx2px(80)
|
|
|
+ this.canvasH = this.canvasW*2-uni.upx2px(400)
|
|
|
+ //设置画布背景透明
|
|
|
+ this.ctx.setFillStyle('rgba(255, 255, 255, 0)')
|
|
|
+ //设置画布大小
|
|
|
+ this.ctx.fillRect(0,0,this.canvasW,this.canvasH)
|
|
|
+ //绘制圆角背景
|
|
|
+ this.drawRoundRect(this.ctx, 0, 0, this.canvasW, this.canvasH,uni.upx2px(18),'#FFFFFF')
|
|
|
+ //获取标题图片
|
|
|
+ let headerImg = await this.getImageInfo(this.works.image)
|
|
|
+ let hW = uni.upx2px(560);
|
|
|
+ let hH = uni.upx2px(360);
|
|
|
+
|
|
|
+ //绘制标题
|
|
|
+ //绘制标题
|
|
|
+ this.ctx.setFontSize(12); //设置标题字体大小
|
|
|
+ this.ctx.setFillStyle('#333'); //设置标题文本颜色
|
|
|
+ let titleWidth = this.ctx.measureText(this.works.title).width
|
|
|
+ if(titleWidth > hW){
|
|
|
+ this.ctx.fillText(this.works.title.slice(0,25),((this.canvasW-hW) / 2),((this.canvasW-hW) / 2))
|
|
|
+ this.ctx.fillText(this.works.title.slice(25,50),((this.canvasW-hW) / 2),((this.canvasW-hW) / 2) + uni.upx2px(46))
|
|
|
+ } else{
|
|
|
+ this.ctx.fillText(this.works.title,((this.canvasW-hW) / 2),((this.canvasW-hW) / 2))
|
|
|
+ }
|
|
|
+
|
|
|
+ //绘制标题图
|
|
|
+ this.drawRoundImg(this.ctx,headerImg.path,((this.canvasW-hW) / 2-uni.upx2px(12)),((this.canvasW-hW) / 2) + uni.upx2px(80),hW + uni.upx2px(28),hW + uni.upx2px(28),uni.upx2px(16))
|
|
|
+
|
|
|
+ //绘制副标题
|
|
|
+ // this.ctx.setFontSize(14);
|
|
|
+ // this.ctx.setFillStyle('#858585');
|
|
|
+ // this.ctx.fillText(this.worksIntro.slice(0,19) ,((this.canvasW-hW) / 2) + uni.upx2px(20),(
|
|
|
+ // ((this.canvasW-hW) / 2) + hH + uni.upx2px(160)))
|
|
|
+ // this.ctx.fillText(this.worksIntro.slice(19,39) ,((this.canvasW-hW) / 2),(
|
|
|
+ // ((this.canvasW-hW) / 2) + hH + uni.upx2px(200)))
|
|
|
+ // this.ctx.fillText(this.worksIntro.slice(39,59) ,((this.canvasW-hW) / 2),(
|
|
|
+ // ((this.canvasW-hW) / 2) + hH + uni.upx2px(240)))
|
|
|
+ // this.ctx.fillText(this.worksIntro.slice(58,75)+'...' ,((this.canvasW-hW) / 2),(
|
|
|
+ // ((this.canvasW-hW) / 2) + hH + uni.upx2px(280)))
|
|
|
+ //绘制副标题
|
|
|
+ // this.ctx.setFontSize(14);
|
|
|
+ // this.ctx.setFillStyle('#858585');
|
|
|
+ // let ksWidth = this.ctx.measureText(this.product.dept).width
|
|
|
+ // if(ksWidth > hW){
|
|
|
+ // this.ctx.fillText('【'+this.str2+'】'+this.product.dept.slice(0,16) + '...',((this.canvasW-hW) / 2),(
|
|
|
+ // ((this.canvasW-hW) / 2) + hH + uni.upx2px(110))+uni.upx2px(50))
|
|
|
+ // }else{
|
|
|
+ // this.ctx.fillText('【'+this.str2+'】'+this.product.dept,((this.canvasW-hW) / 2),(
|
|
|
+ // ((this.canvasW-hW) / 2) + hH + uni.upx2px(110))+uni.upx2px(50))
|
|
|
+ // }
|
|
|
+ //绘制副标题
|
|
|
+ // this.ctx.setFontSize(14);
|
|
|
+ // this.ctx.setFillStyle('#858585');
|
|
|
+ // let qdWidth = this.ctx.measureText(this.product.investmentChannel).width
|
|
|
+ // if(qdWidth > hW){
|
|
|
+ // this.ctx.fillText('【'+this.str3+'】'+this.product.investmentChannel.slice(0,16) + '...',((this.canvasW-hW) / 2),(
|
|
|
+ // ((this.canvasW-hW) / 2) + hH + uni.upx2px(110))+uni.upx2px(100))
|
|
|
+ // }else{
|
|
|
+ // this.ctx.fillText('【'+this.str3+'】'+this.product.investmentChannel,((this.canvasW-hW) / 2),(
|
|
|
+ // ((this.canvasW-hW) / 2) + hH + uni.upx2px(110))+uni.upx2px(100))
|
|
|
+ // }
|
|
|
+ //绘制副标题
|
|
|
+ // this.ctx.setFontSize(14);
|
|
|
+ // this.ctx.setFillStyle('#858585');
|
|
|
+ // let dqWidth = this.ctx.measureText(this.product.investmentAreas).width
|
|
|
+ // if(dqWidth > hW){
|
|
|
+ // this.ctx.fillText('【'+this.str4+'】'+this.product.investmentAreas.slice(0,16) + '...',((this.canvasW-hW) / 2),(
|
|
|
+ // ((this.canvasW-hW) / 2) + hH + uni.upx2px(110))+uni.upx2px(150))
|
|
|
+ // }else{
|
|
|
+ // this.ctx.fillText('【'+this.str4+'】'+this.product.investmentAreas,((this.canvasW-hW) / 2),(
|
|
|
+ // ((this.canvasW-hW) / 2) + hH + uni.upx2px(110))+uni.upx2px(150))
|
|
|
+ // }
|
|
|
+ //提示文案
|
|
|
+ this.ctx.setFontSize(12);
|
|
|
+ this.ctx.setFillStyle('#858585');
|
|
|
+ this.ctx.fillText('长按识别二维码',(((this.canvasW-hW) / 2)),(((this.canvasW-hW) / 2) + hH + uni.upx2px(400)))
|
|
|
+ this.ctx.fillText('投票小程序',(((this.canvasW-hW) / 2)),(((this.canvasW-hW) / 2) + hH + uni.upx2px(440)))
|
|
|
+ //底部广告
|
|
|
+ // let BottomAdImg = await this.getImageInfo(this.abImg)
|
|
|
+ // this.ctx.drawImage(BottomAdImg.path,(((this.canvasW-hW) / 2)),(((this.canvasW-hW) / 2) + hH + uni.upx2px(310)),uni.upx2px(350),uni.upx2px(110))
|
|
|
+ //小程序码
|
|
|
+ let qrcodeImg = await this.getImageInfo(this.works.qrcode)
|
|
|
+ this.ctx.drawImage(qrcodeImg.path,uni.upx2px(470),(((this.canvasW-hW) / 2) + hH + uni.upx2px(340)), uni.upx2px(150), uni.upx2px(150))
|
|
|
+ //延迟渲染
|
|
|
+ setTimeout(()=>{
|
|
|
+ this.ctx.draw(true,()=>{
|
|
|
+ uni.hideLoading()
|
|
|
+ })
|
|
|
+ this.saveImage();
|
|
|
+ },500)
|
|
|
+ },
|
|
|
+ //绘制实心圆
|
|
|
+ drawEmptyRound(ctx,x,y,radius){
|
|
|
+ ctx.save()
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(x, y, radius, 0, 2 * Math.PI,true);
|
|
|
+ ctx.setFillStyle('rgba(0, 0, 0, .4)')
|
|
|
+ ctx.fill();
|
|
|
+ ctx.restore()
|
|
|
+ ctx.closePath()
|
|
|
+ },
|
|
|
+ //绘制虚线
|
|
|
+ drawDashLine(ctx,x1,y1,x2,y2,dashLength){
|
|
|
+ ctx.setStrokeStyle("#cccccc")//设置线条的颜色
|
|
|
+ ctx.setLineWidth(1)//设置线条宽度
|
|
|
+ var dashLen = dashLength,
|
|
|
+ xpos = x2 - x1, //得到横向的宽度;
|
|
|
+ ypos = y2 - y1, //得到纵向的高度;
|
|
|
+ numDashes = Math.floor(Math.sqrt(xpos * xpos + ypos * ypos) / dashLen);
|
|
|
+ //利用正切获取斜边的长度除以虚线长度,得到要分为多少段;
|
|
|
+ for(var i=0; i<numDashes; i++){
|
|
|
+ if(i % 2 === 0){
|
|
|
+ ctx.moveTo(x1 + (xpos/numDashes) * i, y1 + (ypos/numDashes) * i);
|
|
|
+ //有了横向宽度和多少段,得出每一段是多长,起点 + 每段长度 * i = 要绘制的起点;
|
|
|
+ }else{
|
|
|
+ ctx.lineTo(x1 + (xpos/numDashes) * i, y1 + (ypos/numDashes) * i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ctx.stroke();
|
|
|
+ },
|
|
|
+ //带圆角图片
|
|
|
+ drawRoundImg(ctx, img, x, y, width, height, radius){
|
|
|
+ ctx.beginPath()
|
|
|
+ ctx.save()
|
|
|
+ // 左上角
|
|
|
+ ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 1.5)
|
|
|
+ // 右上角
|
|
|
+ ctx.arc(x + width - radius, y + radius, radius, Math.PI * 1.5, Math.PI * 2)
|
|
|
+ // 右下角
|
|
|
+ ctx.arc(x + width - radius, y + height - radius, radius, 0, Math.PI * 0.5)
|
|
|
+ // 左下角
|
|
|
+ ctx.arc(x + radius, y + height - radius, radius, Math.PI * 0.5, Math.PI)
|
|
|
+ ctx.stroke()
|
|
|
+ ctx.clip()
|
|
|
+ ctx.drawImage(img, x, y, width, height);
|
|
|
+ ctx.restore()
|
|
|
+ ctx.closePath()
|
|
|
+ },
|
|
|
+ //圆角矩形
|
|
|
+ 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();
|
|
|
+ },
|
|
|
+ //获取图片
|
|
|
+ getImageInfo(imgSrc){
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ uni.getImageInfo({
|
|
|
+ src: imgSrc,
|
|
|
+ success: (image) => {
|
|
|
+ resolve(image);
|
|
|
+ console.log('获取图片成功',image)
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ reject(err);
|
|
|
+ console.log('获取图片失败',err)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ //保存图片到相册
|
|
|
+ saveImage(){
|
|
|
+ var that = this
|
|
|
+ uni.canvasToTempFilePath({
|
|
|
+ canvasId: 'my-canvas',
|
|
|
+ quality: 1,
|
|
|
+ complete: (res) => {
|
|
|
+ console.log('保存到相册', res);
|
|
|
+ that.imgUrl = this.getImageInfo(res.tempFilePath);
|
|
|
+ }
|
|
|
+ },this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.postcontent{
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ background: rgba(0,0,0,.4);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ z-index: 99999999;
|
|
|
+ .save-btn{
|
|
|
+ margin-top: 35rpx;
|
|
|
+ color: #FFFFFF;
|
|
|
+ background: linear-gradient(to right, #FE726B , #FE956B);
|
|
|
+ padding: 15rpx 40rpx;
|
|
|
+ border-radius: 50rpx;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|