午夜91福利视频,午夜成人在线观看,午夜在线视频免费观看,午夜福利短视频,精品午夜成人免费视频APP

小程序模板網

Canvas繪圖在微信小程序中的應用:生成個性化海報

發布時間:2018-10-07 09:30 所屬欄目:小程序開發教程
一、Canvas應用的背景(個人理解)及基礎語法
背景
從2012年開始,微信那個時候用戶的積累的量已經非常大了,推出公眾號,當然大屏智能手機在那個時候也流行,傳統的大眾媒體逐步消亡,像微信公眾號這樣的新媒體盛行。企業的廣告投入開始從電視等傳統媒體向基于圈層文化的新媒體精準營銷轉移,甚至很多企業尤其互聯網企業開始思考如何利用用戶的自傳播這種方式去宣傳企業、實現商業目標。而用戶的自傳播很好的途徑就是生產個性化的海報。舉個最常見的例子,我第一次使用Keep是因為在朋友圈看到朋友分享她運動量的一個截圖,當時在我看來非常酷,有心率脈搏呀、時速運動量啊、消耗的卡路里等,還有一個二維碼,然后我就點了下載了Keep,這整個獲客成本幾乎為0,秒秒鐘就多了一個用戶。而實現這一過程的技術手段就可以用canvas。所以,canvas的盛行,與企業的精準營銷和用戶的自傳播有很大的關系。
如極客時間的一些實現案例:



大家看第一張圖的話是在2017年末的時候,Qcon全球軟件開發大會預熱階段的海報。然后我們為程序員做了一個生成2018年關鍵字的一張海報,文案都非常有趣啊。第二張的話是在2018年元旦的時候做的極客時間助手,這個小程序當初主要是為程序員做的2018年新年簽。那面就是一些極客時間的專欄,包括用戶留言,你留言隨手可以生成一張海報,可以轉發等等大概就是這樣。

基礎語法
Canvas本質是一個可以使用腳本(通常為JavaScript)來繪制圖形的 HTML 元素,默認大小為300像素×150像素(寬×高,像素的單位是px),通過JavaScript上下文對象動態創建圖像。比如,畫線、畫矩形、涂顏色甚至生成帶二維碼的海報。原理就是一筆一筆的畫,畫一條橫線,再畫一條橫線等等,就是不斷地創建路徑、繪制路徑,然后把這個路徑封閉起來可以涂色之類的,他的底層的封裝就是放到一個數組里形成一個路徑的數組,將這個數組傳到js底層的一個方法,然后去繪制。

舉個栗子:畫一個頭像




首先,你需要把這張圖片畫canvas上面,比如說你畫你這個頭像就是正方形,就在(0,0)開始畫一個圖片。那么你在這個圖片的中心,作為原點,然后你畫一個圓形。然后你再利用canvas語法畫一個圓弧,在這個圓弧路徑以外設置不可見以內設置可見,這個時候就形成了一個圓形頭像。

  <canvas id="canvas" width="300" height="300"></canvas>
  <script>
    const canvas = document.getElementById('canvas')
    const ctx = canvas.getContext('2d')
    const img = new Image()
    img.onload = function() {
      circleImg(ctx, img, 100, 100, 50)
    }
    img.src="//avatar-static.segmentfault.com/289/811/2898115528-58c35e9b79717_big64"
    function circleImg(ctx, img, x, y, r) {
      ctx.save()
      let d = 2 * r
      let cx = x + r
      let cy = y + r
      ctx.arc(cx, cy, r, 0, 2 * Math.PI)
      ctx.stroke();
      ctx.clip()
      ctx.drawImage(img, x, y, d, d)
      ctx.restore()
    }

    // 微信小程序中的[canvas](//developers.weixin.qq.com/miniprogram/dev/component/canvas.html)與HTML5的canvas在語法有些區別,比如API就不一樣,
    // 另外小程序中的canvas因為是原生組件的層級是最高的,所以頁面中的其他組件無論設置 z-index 為多少,都無法覆蓋原生組件
  </script>

二、常用的"生成海報"的方式

我們會經(jing)常在朋(peng)友圈看到什么(me)算(suan)命、性(xing)格(ge)分(fen)析、測算(suan)你的(de)(de)(de)智商、情商等等這(zhe)些東西,都是(shi)(shi)由(you)用戶分(fen)享出一張圖(tu)片(pian)(海(hai)報(bao)(bao)),這(zhe)個(ge)圖(tu)片(pian)就是(shi)(shi)用canvas做(zuo)成的(de)(de)(de),上面畫了二維碼,二維碼是(shi)(shi)一個(ge)數組兩個(ge)或(huo)循(xun)環嵌套畫小黑點(dian)用戶識別這(zhe)個(ge)二維碼之(zhi)后(hou)就進入他(ta)的(de)(de)(de)程序,經(jing)過程序跑出來(lai)的(de)(de)(de)測試結果啊什么(me)的(de)(de)(de),點(dian)保(bao)存的(de)(de)(de)時候,就會生成一張個(ge)性(xing)海(hai)報(bao)(bao)明白。怎么(me)生成這(zhe)種個(ge)性(xing)化(hua)海(hai)報(bao)(bao)呢?

2.1 字符串模板

此(ci)處應有案例

主要實現:與服務端約定好數據格式-->前端做好模板-->服務端用第三方工具渲染返回到客戶端img
首先與服務端約定好數據格式,比如關鍵字是什么、頭像URL、昵稱等等,把所有放數據格式的地方用{{{}}}嵌套,告訴后端位置;然后,將前端模擬數據摳去,比如user.tags,把這一段html的字符串模板給到服務端,最后服務端拿到數據通過html2canvas這樣的第三方工具把圖片渲染返回給客戶端展示,讓用戶可以長按這張圖片保存到手機相冊。這是比較傳統的方式早些年基本上都是通過這種方式。
有什么弊端呢?
 一是(shi)第三方工具維護不(bu)及時(shi)、不(bu)支持flex布局、ES6等語法,二是(shi)調試(shi)不(bu)方便,三是(shi)高(gao)并發的(de)時(shi)候(hou)會(hui)出問題,特別(bie)是(shi)生(sheng)成的(de)是(shi)高(gao)清無碼的(de)海(hai)報(bao)的(de)時(shi)候(hou)

2.2 canvas繪制

案例: '極客時間小助手'小程序
主要實現:前端直接通過canvas生成海報
搖晃手機抽取新年簽跳到第一個頁面,需要繪制頭像、關鍵字以及保存按鈕,黃色的保存按鈕其實就是呃一張透明的png圖片,把它畫上去。那在這個button上面兒需要固定一個寬高和它差不多大小的一個空的、透明的div,在這個div上加點擊事件,這個事件就是調第二張要保存的那個canvas。第二張這個是沒有保存按鈕的但有二維碼。帶二維碼的這張canvas放哪里呢?一種方案是定位,給一個特別大的top或left,讓它不顯示在屏幕里邊;另一個方案是層級,預覽的這張canvas在真正要保存canvas圖片之上,但是會有問題。手機瀏覽器版本低的話,定了層級不管用,一些安卓手機也會有問題,有時候會浮上來沒被蓋住。
當然,如果要實現保存高清圖的話,還是需要處理的,那就是放大,不過這個是笨方法。最優的方法是拆解這張圖像,確保導出的canvas是最高清的,而且對用戶來說也是最省流量的。
解析(xi):進(jin)到(dao)首頁其實關鍵字在本(ben)(ben)地就(jiu)隨機取(qu)完了(le),在首頁index.js中的(de)(de)(de)onShow方法中就(jiu)通過wx.getStorageSync緩存了(le)要(yao)畫(hua)的(de)(de)(de)元素,比如(ru)關鍵字(這(zhe)里是圖(tu)(tu)片(pian))、關鍵字解析(xi)語(也(ye)是圖(tu)(tu)片(pian),畢竟微信(xin)小程序的(de)(de)(de)canvas不(bu)支持字體)等(deng)等(deng)。搖一(yi)搖觸發重力感應事件(jian)(jian)wx.onAccelerometerChange監(jian)聽里面的(de)(de)(de)事件(jian)(jian),獲取(qu)用戶(hu)授權(quan)(quan)拿到(dao)頭像并跳轉(zhuan)到(dao)poster頁面。直接就(jiu)開(kai)始畫(hua)兩張(zhang)圖(tu)(tu)片(pian),一(yi)張(zhang)有二維(wei)碼的(de)(de)(de)(shakepage1),一(yi)張(zhang)有button的(de)(de)(de)(shakepage2),這(zhe)里二維(wei)碼是'死碼',button也(ye)是在圖(tu)(tu)片(pian)的(de)(de)(de)基(ji)礎上覆蓋(gai)一(yi)個view,畫(hua)完之后調canvasToTempFilePath保導(dao)出那張(zhang)帶碼的(de)(de)(de),此時帶碼的(de)(de)(de)這(zhe)張(zhang)通過css設置visibility: hidden隱(yin)藏(zang)起來。點擊(ji)(ji)按鈕觸發saveImageToPhotosAlbum將導(dao)出的(de)(de)(de)這(zhe)張(zhang) 圖(tu)(tu)片(pian)保存到(dao)手機相冊,這(zhe)里需(xu)(xu)要(yao)授權(quan)(quan)相應的(de)(de)(de)要(yao)做一(yi)些處理,比如(ru)用戶(hu)拒(ju)絕授權(quan)(quan)之后再次(ci)點擊(ji)(ji)需(xu)(xu)要(yao) wx.showModal再次(ci)請用戶(hu)授權(quan)(quan)。基(ji)本(ben)(ben)代碼如(ru)下:(詳細源(yuan)碼))

      wx.canvasToTempFilePath({
        x: 0,
        y: 0,
        width: this.data.screenWidth,
        height: this.data.screenHeight,
        destWidth: this.data.screenWidth * this.data.pixelRatio,  // pixelRatio為設備的像素比  
        destHeight: this.data.screenHeight * this.data.pixelRatio,
        canvasId: "canvasid",
        success: function(e) {
          console.log(e)
          this.setData({
            bjtempFilePath: e.tempFilePath  // 拿到要保存的圖片路徑
          }, function() {});
        },
        fail: function(e) {
          console.log(e);
        }
      })
  onUserSaveImageRight: function () {
    console.log("-click-");
    var _this = this;
    if (!wx.saveImageToPhotosAlbum) return wx.showModal({
      title: "提示",
      content: "當前微信版本過低,無法使用該功能,請升級到最新微信版本后重試。"
    }), void console.log("version low");
    wx.getSetting({
      success: function (res) {
        res.authSetting["scope.writePhotosAlbum"] ? (console.log("1-已經授權《保存圖片》權限"), _this.saveimgfn()) : wx.authorize({
          scope: "scope.writePhotosAlbum",
          success: function () {
            console.log("用戶對相冊-授權成功"), _this.saveimgfn();
          },
          fail: function () {
            wx.showModal({
              title: "提示",
              content: "請您授權保存到系統相冊",
              showCancel: !1,
              success: function (res) {
                res.confirm && wx.openSetting({
                  success: function (res) {
                    res.authSetting["scope.writePhotosAlbum"] ? setTimeout(function () {
                      _this.saveimgfn();
                    }, 500) : wx.showModal({
                      title: "提示",
                      content: "您未授權,無法將海報保存到相冊,你可以截屏得到海報,或者再次點擊'保存海報'按鈕并授權",
                      showCancel: !1
                    });
                  }
                });
              }
            });
          }
        });
      }
    });
  },
  saveimgfn: function () {
    var filePath = this.data.bjtempFilePath;
    console.log(filePath), filePath ? wx.saveImageToPhotosAlbum({
      filePath: filePath,
      success: function (res) {
        wx.showToast({
          title: "保存成功",
          icon: "success",
          duration: 1500
        });
      },
      fail: function () {
        wx.showToast({
          title: "保存失敗",
          icon: "fail",
          duration: 1500
        });
      }
    }) : this.saveImage()

三、極客時間小程序-生成各種海報的解決方案

微信小程序canvas與HTM5的canvas對比

  1. 微信小程序canvas中層級z-index失效,小程序中canvas擁有最高級,無法二次設置;
  2. 微信小程序canvas不支持字體功能,特殊字體只能用圖片代替;
  3. 微信小程序canvas不支持繪制在線圖片,需要下載再繪制(安全域名的鍋)
  4. 微信小程序canvas可以實現不同尺寸屏幕自適應
    var rpx;
    //獲取屏幕寬度,獲取自適應單位
    wx.getSystemInfo({
      success: function(res) {
        rpx = res.windowWidth/750
      },
    })
    // 在繪制方法中將參數乘以相對單位即可實現自適應
    const s = wx.createCanvasContext("canvas")
    s.drawImage(Url, 0, 0, 265 * rpx, 262.5 * rpx) 

如何導出高清海報、如何封裝;

wx.canvasToTempFilePath({
    canvasId: 'image-save',
    x: 0,
    y: 0,
    success: res => {
       wx.saveImageToPhotosAlbum({
         filePath: res.tempFilePath,
         success: () => {
           this.setData({saving: false})
           utils.success('保存成功')
           setTimeout(() => {wx.navigateBack()}, 500)
         },
         fail: err => {
           this.setData({saving: false})
           wx.getSetting({
             success: res => {
               if(!res.authSetting || !res.authSetting['scrop.writePhotoAlbum']){
                 wx.openSetting()
               }
             }
           })
         }
       })
    }
})


易(yi)優小程序(xu)(企業(ye)版)+靈活(huo)api+前后代碼開源(yuan) 碼云倉庫:
本文地址://www.jinyoudianli.com/wxmini/doc/course/24851.html 復制鏈接 如需(xu)定制請(qing)聯系(xi)易優客服咨詢:

工作日 8:30-12:00 14:30-18:00
周六及部分節假日提供值班服務

易小優
轉人工(gong) ×