wx 使用canvas画海报

31 篇文章 0 订阅
26 篇文章 0 订阅

直接放代码   各个地方基本都有注释 

<template>
  <view class="poster">
    <canvas v-if="getImg==''" style="width: 315px;height: 502px;position: fixed;left: 999999rpx;" canvas-id="poster1" class="post"></canvas>
    <image  v-if="getImg!=''" :src="getImg" style="width: 630rpx;height: 1004rpx;" class="getimg" />
    <button @click="preservation" v-if="getImg!=''" class="width290 height76 radius38 font32 weight400 line76 colorFFFFFF absolute left58" style="background-color: #81D8D0;top:1150rpx;">保存至相册</button>
    <button open-type="share"  v-if="getImg!=''" class="width290 height76 radius38 font32 weight400 line76 colorFFFFFF absolute right48" style="background-color: #81D8D0;top:1150rpx;">推荐给好友</button>
  </view>
</template>


<script>
  import wepy from '@wepy/core';
  import lbajax from '../lbts/ajax.js';
  import testMixin from '../mixins/test.js';
  wepy.page({
    mixins: [ testMixin ],
    data: {
      getImg: '',
      imgUrl:'',
      show: false,
      QrCode:'',
      posterInfo:{},
      state:'',
      route:'',
      id:'',
    },
    onShareAppMessage(){
      return {
        title:this.posterInfo.shopName,
        path:this.route+'?ph='+this.posterInfo.phone+'&id='+this.id,
        imageUrl: this.imgUrl
      };
    },
   async onLoad(options) {
     console.log(getApp().$wepy.$options.globalData)
     new Promise(this.validityInfo)
     .then((res)=>{
       if(res==1){
         this.state = options.c;
         this.id=options.id;
         this.imgUrl=options.imgUrl;
            wx.showLoading({
              title: '加载中'
            });
            let data={
              storeId:getApp().$wepy.$options.globalData.poster.id,
            }
            if(options.c==0){
              this.route="/infoPages/temlete"
              data.paths="infoPages/temlete"
            }else{
              this.route="/power/temleteMore"
              data.paths="power/temleteMore"
            }
            console.log(data,'data')
            lbajax({
              url:'/wx/getQrCode2',
              method:'POST',
              data:data,
              }).then((res)=>{
                this.posterInfo=getApp().$wepy.$options.globalData.poster
                this.QrCode=res
                this.init();
              })
       }else{
         wx.showLoading({
           title: '请先登录!'
         });
         setTimeout(function () {
           wx.navigateTo({
               url: '/power/login'
           });
           wx.hideLoading()
         }, 2000)
         
       }
     }).catch((err)=>{
       console.log(err)
     })
     
    },
    methods: {
      /**
       * 验证是否登录
       * */
      validityInfo(resolve, reject){
        console.log(getApp().$wepy.$options.globalData.poster)
        let info = getApp().$wepy.$options.globalData.poster;
        if(info.phone && info.headImg){
          resolve(1);
        }else{
          resolve(0);
        }
      },
      /**
       * 保存到相册
       * */
      preservation() {
        wx.getSetting({
          success: (res) => {
            // 如果没有则获取授权
            if (!res.authSetting['scope.writePhotosAlbum']) {
              wx.authorize({
                scope: 'scope.writePhotosAlbum',
                success: () => {
                  wx.saveImageToPhotosAlbum({
                    filePath: this.getImg,
                    success: () => {
                      wx.showToast({
                        title: '保存成功'
                      })
                    },
                    fail() {
                      wx.showToast({
                        title: '保存失败',
                        icon: 'none'
                      })
                    }
                  })
                },
              })
            } else {
              // 有则直接保存
              wx.saveImageToPhotosAlbum({
                filePath: this.getImg,
                success() {
                  wx.showToast({
                    title: '保存成功'
                  })
                },
                fail() {
                  wx.showToast({
                    title: '保存失败',
                    icon: 'none'
                  })
                }
              })
            }
          },
        })
      },
      /**
       * 如果图片加载失败返回上一页
       * */
      toBack(){
        wx.navigateBack()
      },
      roundRect(ctx, x, y, w, h, r) {
        // 开始绘制
        ctx.beginPath()
        // 因为边缘描边存在锯齿,最好指定使用 transparent 填充
        // 这里是使用 fill 还是 stroke都可以,二选一即可
        ctx.setFillStyle('transparent')
        // ctx.setStrokeStyle('transparent')
        // 左上角
        ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)

        // border-top
        ctx.moveTo(x + r, y)
        ctx.lineTo(x + w - r, y)
        ctx.lineTo(x + w, y + r)
        // 右上角
        ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)

        // border-right
        ctx.lineTo(x + w, y + h - r)
        ctx.lineTo(x + w - r, y + h)
        //右下五角
        // ctx.lineTo(w, h)
        // ctx.lineTo(w, h)
        //右下有角
          ctx.lineTo(x + w, y + h - r)
          ctx.lineTo(x + w - r, y + h)
        // 右下角
        ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)

        // border-bottom
        ctx.lineTo(x, y + h)
        ctx.lineTo(x, y + h) //注释去掉左下角
        // 左下角
        ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)

        // border-left
        ctx.lineTo(x, y + r)
        ctx.lineTo(x + r, y)

        // 这里是使用 fill 还是 stroke都可以,二选一即可,但是需要与上面对应
        ctx.fill()
        // ctx.stroke()
        ctx.closePath()
        // 剪切
        ctx.clip()
      },
      headImg(contex, url) {
        var avatarurl_width = 37; //绘制的头像宽度
        var avatarurl_heigth = 37; //绘制的头像高度
        var avatarurl_x = 15; //绘制的头像在画布上的位置
        var avatarurl_y = 387; //绘制的头像在画布上的位置
        contex.save();
        contex.beginPath(); //开始绘制
        //先画个圆   前两个参数确定了圆心 (x,y) 坐标  第三个参数是圆的半径  四参数是绘图方向  默认是false,即顺时针
        contex.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y,
          avatarurl_width / 2, 0,
          Math.PI * 2, false);
        contex.clip(); //画好了圆 剪切  原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内 这也是我们要save上下文的原因
        contex.drawImage(url, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片,必须是https图片
        contex.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 还可以继续绘制
      },
      /**
       * 客片欣赏海报
       * */
       appreciate(backimg,ctx){
         if (true) { //店铺名字
           ctx.setFontSize(15);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText(this.posterInfo.shopName, 37, 292);
         }
         if(true){//客片风格
           ctx.setFontSize(13);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText('客片风格:大童', 15, 311+15);
         }
         if(true){//样片主题
           ctx.setFontSize(13);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText('样片主题:童真时刻', 159, 311+15);
         }
         if (true) { //消费
           ctx.setFontSize(13);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText('人均消费:'+this.posterInfo.seryPrice, 15, 344+15);
         }
         if (true) { //店评分
           ctx.setFontSize(13);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText('门店评分:', 159, 344+15);
         }
         if (true) { //分数星星
         var num = 4;
         if(!this.posterInfo.storeScore){
           this.posterInfo.storeScore=5
         }
         for(let i=0;i<this.posterInfo.storeScore;i++){
           ctx.drawImage('/static/img/score.png', 224+num, 344+5, 12, 12);
           num=num+4+12;
         }
         }
         ctx.save();
         //分割线
         ctx.beginPath(); //开始一个新的路径
         ctx.moveTo(300, 377)
         ctx.lineTo(15, 377)
         ctx.setStrokeStyle('#EBEBEB')
         ctx.stroke()
         ctx.restore()
         this.headImg(ctx, backimg[1])
         if (true) { //昵称
           ctx.setFontSize(12);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText(this.posterInfo.userName, 58, 397 + 15);
         }
         if (true) { //长按识别文字
           ctx.setFontSize(12);
           ctx.setFillStyle('#ADADAD');
           ctx.setTextAlign('left');
           ctx.fillText('长按识别小程序码', 15, 428 + 15);
         }
         if (true) { //即可查看精美样片!
           ctx.setFontSize(12);
           ctx.setFillStyle('#81D8D0');
           ctx.setTextAlign('left');
           ctx.fillText('即可查看精美样片!', 15, 449 + 15);
         }
         if (true) { //即可查看精美样片!
           ctx.setFontSize(12);
           ctx.setFillStyle('#AAAAAA');
           ctx.setTextAlign('left');
           ctx.fillText('还有更多精彩内容,等着你!', 15, 470 + 15);
         }
       },
      /**
       * 客片展示海报
       * */
       exhibition(backimg,ctx) {
         if (true) { //店铺名字
           ctx.setFontSize(15);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText(this.posterInfo.shopName, 37, 292);
         }
         if (true) { //消费
           ctx.setFontSize(13);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText('人均消费:'+this.posterInfo.seryPrice, 15, 311 + 17);
         }
         if (true) { //店评分
           ctx.setFontSize(13);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText('门店评分:', 159, 311 + 17);
         }
         if (true) { //分数星星
         var num = 4;
         if(!this.posterInfo.storeScore){
           this.posterInfo.storeScore=5
         }
         for(let i=0;i<this.posterInfo.storeScore;i++){
           ctx.drawImage('/static/img/score.png', 224+num, 317, 12, 12);
           num=num+4+12;
         }
         }
         if (true) { //门店位置
           ctx.setFontSize(13);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText('门店位置:', 15, 344 + 17);
         }
         if (true) { //详细位置
           ctx.setFontSize(13);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText(this.posterInfo.address, 80, 344 + 17);
         }
         ctx.save();
         //分割线
         ctx.beginPath(); //开始一个新的路径
         ctx.moveTo(300, 377)
         ctx.lineTo(15, 377)
         ctx.setStrokeStyle('#EBEBEB')
         ctx.stroke()
         ctx.restore()
         this.headImg(ctx, backimg[1])
         if (true) { //昵称
           ctx.setFontSize(12);
           ctx.setFillStyle('#000');
           ctx.setTextAlign('left');
           ctx.fillText(this.posterInfo.userName, 58, 397 + 15);
         }
         if (true) { //长按识别文字
           ctx.setFontSize(12);
           ctx.setFillStyle('#ADADAD');
           ctx.setTextAlign('left');
           ctx.fillText('长按识别小程序码', 15, 428 + 15);
         }
         if (true) { //即可查看精美样片!
           ctx.setFontSize(12);
           ctx.setFillStyle('#81D8D0');
           ctx.setTextAlign('left');
           ctx.fillText('即可查看精美样片!', 15, 449 + 15);
         }
         if (true) { //即可查看精美样片!
           ctx.setFontSize(12);
           ctx.setFillStyle('#AAAAAA');
           ctx.setTextAlign('left');
           ctx.fillText('还有更多精彩内容,等着你!', 15, 470 + 15);
         }
       },
      /**
       * 生成图片
       * */
      init() {
        wx.showLoading({
          title: '加载中',
        })
        //二维码
        let qrcode = new Promise((resolve) =>{
          wx.getImageInfo({
            src: this.QrCode,
            success: (res) => {
              resolve(res.path)
            },
            fail: (err) => {
              console.log(err)
              wx.showToast({
                title: '网络错误请重试',
                icon: 'loading'
              })
              this.toBack()
            }
          });
        });
        //头像
        let headImg = new Promise((resolve) =>{
          wx.getImageInfo({
            src: this.posterInfo.headImg,
            success: (res) => {
              resolve(res.path)
            },
            fail: (err) => {
              console.log(err)
              wx.showToast({
                title: '网络错误请重试',
                icon: 'loading',
                duration:2000,
                success:(res)=>{
                  this.toBack()
                }
              })
            }
          });
        });
        //大图
        let backimg = new Promise((resolve)=> {
          wx.getImageInfo({
            src:this.imgUrl,
            success: (res) => {
              resolve(res.path)
            },
            fail: (err) => {
              console.log(err)
             wx.showToast({
               title: '网络错误请重试',
               icon: 'loading',
               duration:2000,
               success:(res)=>{
                 this.toBack()
               }
             })
            }
          });
        });
        Promise.all([backimg, headImg,qrcode])
          .then((backimg) => {
            let ctx = wx.createCanvasContext('poster1', this)
            ctx.save()
            this.roundRect(ctx, 0, 0, 315, 502, 10);
            ctx.fillStyle = "#FFFFFF";
            ctx.fillRect(0, 0, 315, 502);
            ctx.drawImage(backimg[0], 0, 0, 315, 260);
            ctx.restore()
            ctx.drawImage('/static/img/shop.png', 15, 278, 16, 15);
            console.log(this.state)
            if(this.state==0){
              this.exhibition(backimg,ctx);
            }else{
              this.appreciate(backimg,ctx);
            }
            //二维码
            ctx.drawImage(backimg[2], 200, 387, 100, 100);
            ctx.draw(true, (res) => {
              wx.canvasToTempFilePath({
                canvasId: 'poster1',
                destWidth: 315*2,
                destHeight: 502*2,
                success: (res) => {
                  this.getImg = res.tempFilePath;
                  wx.hideLoading()
                },
                fail: function(res) {
                console.log(res)
                }
              });
            })
          });
      }
    }
  })
</script>
<style lang="scss" scoped>
  page {
    background-color: #ffffff;
  }
.getimg{
    position: absolute;
    top: 120rpx;
}
  .poster {
    display: flex;
    // align-items: center;
    justify-content: center;
    position: fixed;
    top: 0;
    width: 100%;
    height: 100%;
    text-align: center;
    background: rgba(0, 0, 0, 0.3);
  }
  button::after{
    border: none;
  }
</style>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值