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 新增:效果页面
     
参考资料:
相关文章
相关标签/搜索