| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- <template>
- <view >
- <view class="postcontent" v-if="isShow" @click.stop="isShow=false">
- <canvas id='canvas' @click.stop="" :style="{ width: canvasW + 'px', height: canvasH + 'px' }" canvas-id="my-canvas"></canvas>
- <!-- <view class="text-center text-white">长按保存图片</view> -->
- </view>
- <u-popup v-model="imgShow" mode="center" width="640" height="990" >
- <image class="calloutImg" :src="imgUrl" @click="preViewImg(imgUrl)"></image>
- <view class="text-center text-lg text-white" style="line-height: 50upx;background-color: #666666;">点击海报,然后长按图片保存</view>
- </u-popup>
- </view>
- </template>
- <script>
- import { pathToBase64, base64ToPath } from '@/common/utils/index.js'
- export default{
- props:{
- works: {
- type: Object,
- default: {}
- }
- },
- data(){
- return {
- canvasW: 0,
- canvasH: 0,
- ctx: null,
- isShow: false,
- imgUrl:'',
- imgShow: false,
- }
- },
- methods:{
- //显示
- showCanvas(){
- this.isShow = true;
- this.imgShow = 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(120)
- this.canvasH = this.canvasW*2 - uni.upx2px(330)
- //设置画布背景透明
- 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(10)),((this.canvasW-hW) / 2) - uni.upx2px(10),hW + uni.upx2px(20),hW + uni.upx2px(20),uni.upx2px(6))
- //绘制名称
- this.ctx.setFontSize(24);
- this.ctx.setFillStyle('#000000');
- this.ctx.fillText(this.works.title ,((this.canvasW-hW) / 2) + uni.upx2px(2),(((this.canvasW-hW) / 2) + hH + uni.upx2px(280)))
- //绘制副标题
- this.ctx.setFontSize(12);
- this.ctx.setFillStyle('#c7c7c7');
- this.ctx.fillText("赶紧为你的爱豆打榜吧" ,((this.canvasW-hW) / 2) + uni.upx2px(2),(((this.canvasW-hW) / 2) + hH + uni.upx2px(325)))
-
- //绘制热力值
- this.ctx.setFontSize(24);
- this.ctx.setFillStyle('#000000');
- this.ctx.fillText(this.works.hotValue ,((this.canvasW-hW) / 2) + uni.upx2px(2),(((this.canvasW-hW) / 2) + hH + uni.upx2px(390)))
-
- //绘制排名
- this.ctx.setFontSize(12);
- this.ctx.setFillStyle('#000000');
- this.ctx.fillText("热力榜第 "+this.works.rank ,((this.canvasW-hW) / 2) + uni.upx2px(2),(((this.canvasW-hW) / 2) + hH + uni.upx2px(430)))
-
- //提示文案
- this.ctx.setFontSize(12);
- this.ctx.setFillStyle('#858585');
- this.ctx.fillText('来自 '+ this.works.name +' 的分享',(((this.canvasW-hW) / 2)),(((this.canvasW-hW) / 2) + hH + uni.upx2px(500)))
- //底部广告
- // 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(450),(((this.canvasW-hW) / 2) + hH + uni.upx2px(360)), 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(){
- this.isShow = false;
- uni.canvasToTempFilePath({
- canvasId: 'my-canvas',
- quality: 1,
- success: (res) => {
- base64ToPath(res.tempFilePath).then(res => {
- this.imgUrl = res;
- });
- // this.imgUrl = res.tempFilePath.replace(/[\r\n]/g, "");
- }
- },this);
- },
- preViewImg(url) {
- uni.previewImage({
- urls: [url]
- });
- }
- }
- }
- </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;
- }
- }
- .calloutImg {
- width: 640rpx;
- height: 940rpx;
- -webkit-touch-callout: default;
- }
- </style>
|