canvas生成遮罩圖片

     首先咱們知道css3中增長了很多好用、好玩的css3樣式可使用。今天咱們要說到是遮罩。
 
     它的使用方式也不復雜,和background使用方式差很少。使用mask-image就可使用,這樣就能夠經過圖片合成一張帶有形狀的合成圖了,不須要直接使用PS處理了。 CSS遮罩——如何在CSS中使用遮罩,這篇文章已經詳細說明了遮罩如何使用了,我這裏就不贅述了。今天我這裏想要說明的是,如何經過這個完成生成一個合成圖片的邏輯。
 
     它經過兩種方式:前端JS+canvas,後端nodejs+canvas,完成基本思路是同樣的,可是兩種方式,後者的兼容性稍好一些。
 
     基礎的圖片合成,總體的思路是:首先按照遮罩層的大小,生成一張圖片;其次把原圖片按照必定的規則按照遮罩層大小剪切(drawImage)一張圖片而後合成到遮罩層上面;最後一個很是重要設置是:globalCompositeOperation,設置圖片合成時,組合操做。
 
      前端JS實現
     
utils.canvasMasking = function(img) {
    var deferred = $.Deferred();
    var newImg = document.createElement('img');

    newImg.setAttribute('crossOrigin', 'Anonymous'); //解決跨域問題
    newImg.src = img.src;

    //源圖片加載失敗
    newImg.onerror = function() {
        deferred.reject('源圖片加載失敗');
    };

    //源圖片加載成功
    newImg.onload = function() {
        var imageWidth = img.width;
        var imageHeight = img.height;
        var mask = document.createElement('img');

        mask.setAttribute('crossOrigin', 'Anonymous');
        mask.src = img.getAttribute('data-mask');

        //遮罩圖片加載失敗
        mask.onerror = function() {
            deferred.reject('遮罩圖片加載失敗');
        };

        //遮罩圖片加載成功
        mask.onload = function() {
            var maskCanvas = document.createElement('canvas');
            var maskContext = maskCanvas.getContext('2d');

            var maskWidth = mask.width;
            var maskHeight = mask.height;

            maskCanvas.width  = maskWidth;
            maskCanvas.height = maskHeight;

            /**
             * 合併mask與處理後的原始圖
             */
            maskContext.drawImage(mask, 0, 0, maskWidth, maskHeight);
            //將一個源(新的)圖像繪製到目標(已有)的圖像上
            maskContext.globalCompositeOperation = 'source-in';
            maskContext.drawImage(img, 0, 0, maskWidth, maskHeight);

            img.src = maskCanvas.toDataURL();

            deferred.resolve(maskCanvas);
        };
    };

    return deferred.promise();
};

  

     因爲canvas是禁止跨域的,因此有兩個條件能夠進行控制:
  • 圖片的頭信息必須設置容許跨域的頭(Access-Control-Allow-Origin:*)
  • 建立的image標籤必須也能容許跨域(img.setAttribute(‘crossOrigin’, 'Anonymous'))
 
     大概實現過程以下:
 
      後端node實現
     
     後端實現的大體思路和前端js操做canvas基本上差很少。後端須要依賴node-canvas模塊,提供與瀏覽器幾乎徹底一致的api,因此能夠無縫切換。詳細的實現說明同上,這裏就不詳細說明,主要說明的多是node-canvas的安裝和正常使用。
 
      由於是處理圖片,因此對安裝的環境有一些要求,相對比其它的模塊要求稍高一些。首先他依賴 Cairo。有一些依賴關係須要安裝,主要是處理圖片的庫,看具體需求,主要有處理三種圖片:png、jpeg、gif。
 
OS Command
OS X brew install pkg-config cairo libpng jpeg giflib
Ubuntu sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++
Fedora sudo yum install cairo cairo-devel cairomm-devel libjpeg-turbo-devel pango pango-devel pangomm pangomm-devel giflib-devel
Solaris pkgin install cairo pkg-config xproto renderproto kbproto xextproto
Windows Instructions on our wiki
 
     上表的信息來自 github
 
     這裏我說明一下我踩過的坑:
  • 第一次因爲沒有安裝jpeg致使處理jpg圖片時,出現加載失敗的提示,遇到這種狀況能夠檢查本身的庫依賴是否是沒有安裝徹底;
  • 第二次安裝了jpeg的庫以後,發現依然不行,最後發現問題在於個人jpeg的庫是在我已經安裝完成node-canvas以後才安裝的
  • 第三次把在mac安裝好的node-modules複製到centos的服務器上,發現canvas不能夠用。緣由是他們的圖片處理庫不同,必須從新安裝node-canvas
 
     綜上所述: 安裝node-canvas的前提條件是安裝全部依賴的庫文件,不一樣的環境下,須要從新下載node-canvas進行安裝,緣由是node-canvas每次都要編譯一遍。
 
     另一些題外的問題:
 
  1. 合成圖片的時候,若是須要移動、縮放或者旋轉怎麼處理?可使用使用canvas的tranlate、scale、rotate進行完成,這裏須要注意的是網頁上的呈現效果和合成處理是否一致的問題。
  2. 前端合成多張遮罩圖片的時候,不一樣的手機的兼容性問題
  3. 微信裏的頁面沒法經過下載按鈕,下載生成的圖片;而且canvas.otDataURL()的圖片沒法長按保存
  4. 使用html2canvas將dom生成圖片的時候,須要設置容許跨域,若是要使用proxy的話,能夠參考進行實現。  
  5. 另外html2canvas生成的canvas信息在上傳base64的時候,可能出現413,body實體太大的提示,這時候須要檢查服務器或者服務器語言的容許body的大小是否有限制。
 
     我目前遇到一個問題:瀏覽器不一樣分辨率下展示的大小和我服務端生成的圖片不一致?正在解決。。。
 
   2015-11-23 新增:效果頁面
     
參考資料:
相關文章
相關標籤/搜索