wx 使用canvas畫海報

直接放代碼   各個地方基本都有註釋 

<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>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章