canvas生成遮罩图片

首先我们知道css3中增加了不少好用、好玩的css3样式可以使用。今天我们要说到是遮罩。

它的使用方式也不复杂,和background使用方式差不多。使用mask-image就可以使用,这样就可以通过图片合成一张带有形状的合成图了,不需要直接使用PS处理了。CSS遮罩——如何在CSS中使用遮罩,这篇文章已经详细说明了遮罩如何使用了,我这里就不赘述了。今天我这里想要说明的是,如何通过这个完成生成一个合成图片的逻辑。

它通过两种方式:前端JS+canvas,后端nodejs+canvas,完成基本思路是一样的,但是两种方式,后者的兼容性稍好一些。

基础的图片合成,整体的思路是:首先按照遮罩层的大小,生成一张图片;其次把原图片按照一定的规则按照遮罩层大小剪切(drawImage)一张图片然后合成到遮罩层上面;最后一个非常重要设置是:globalCompositeOperation,设置图片合成时,组合操作。

前端JS实现

/**
     * 生成canvas遮罩(由于在安卓手机上的兼容问题,未使用,采用服务端接口产生)
     * @param imgList
     */
    utils.canvasMasking = function(imgList) {
        var _imgAddMask = 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 imageCanvas = document.createElement(‘canvas‘);
                    var imageContext = imageCanvas.getContext(‘2d‘);

                    var maskWidth = $(img).parents(‘.mask-wrapper‘).width();
                    var maskHeight = $(img).parents(‘.mask-wrapper‘).height();

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

                    var _x = $(img).data(‘x‘) + ‘‘;
                    var _y = $(img).data(‘y‘) + ‘‘;
                    var x = Math.abs(_x.indexOf(‘%‘) > -1 ? imageWidth * parseFloat(_x)/100 : parseFloat(_x));
                    var y = Math.abs(_y.indexOf(‘%‘) > -1 ? imageHeight * parseFloat(_y)/100 : parseFloat(_y));
                    var scale = parseFloat($(img).data(‘scale‘));
                    var angle = parseFloat($(img).data(‘angle‘));

                    imageCanvas.width = imageWidth * scale;
                    imageCanvas.height = imageHeight * scale;

                    /**
                     * 处理原始图片旋转、缩放
                     */
                        //移动到图片中心点,与css中心点保持一致
                    imageContext.translate(imageCanvas.width/2, imageCanvas.height/2);
                    imageContext.scale(scale, scale);
                    imageContext.rotate(angle);
                    //恢复canvas中心点到做顶点
                    imageContext.translate(-imageCanvas.width/2, -imageCanvas.height/2);
                    imageContext.drawImage(img, 0, 0, imageCanvas.width, imageCanvas.height);

                    /**
                     * 合并mask与处理后的原始图
                     */
                    maskContext.drawImage(mask, 0, 0, maskWidth, maskHeight);
                    //将一个源(新的)图像绘制到目标(已有)的图像上
                    maskContext.globalCompositeOperation = ‘source-in‘;
                    maskContext.drawImage(imageCanvas, x, y, maskWidth, maskHeight, 0, 0, maskWidth, maskHeight);

                    img.src = maskCanvas.toDataURL();

                    $(‘body‘).prepend(imageCanvas, maskCanvas);

                    $(img).siblings(‘.mask‘).hide();
                    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的大小是否有限制。

我目前遇到一个问题:浏览器不同分辨率下展现的大小和我服务端生成的图片不一致?正在解决。。。

参考资料:

https://github.com/niklasvh/html2canvas

https://github.com/Automattic/node-canvas

https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D

时间: 2024-10-17 06:57:57

canvas生成遮罩图片的相关文章

js 利用canvas 生成文字图片

// text,需要生成的文字 // font,字体样式 drawLogo: function(text, font) { // 创建画布 let canvas = document.createElement('canvas'); // 绘制文字环境 let context = canvas.getContext('2d'); // 设置字体 context.font = font; // 获取字体宽度 let width = context.measureText(text).width;

Canvas 生成base64的PNG图片快照,So Amazing!!!

function canvasSupport(){     return Modernizr.canvas;}function callCanvasApps(){  var canvasOne=document.getElementById("canvasOne");  //if(!canvasSupport())      //return;  var context=canvasOne.getContext("2d");  context.fillStyle =

小程序---canvas画图,生成分享图片,画图文字换行

小程序目前只支持转发,不支持分享朋友圈,为了能实现分享,很多线上小程序通过生成分享图片,保存到相册来给用户增加分享的可能. 具体思路及简要代码如下: 一:canvas画图 drawCanvas:function(){ var that = this; var contentPic = '/images/[email protected]' wx.downloadFile({ //当图片为网络图片时,需要先下载到本地,再进行操作, url: contentPic, //否则canvas会加载不到图

安卓中遮罩图片的处理

安卓开发中必不可少的就是各种图片的圆角,遮罩等等. 曾经我都是用shape处理的.发现背景图的圆角要设置成和界面父元素背景一样才干看不出现纰漏. 当遇到背景多变的情况,比方listview隔行背景颜色不同的情况就郁闷了.又要加一堆代码处理. 如今有一个方法能够统一处理,就是用画布Canvas,代码和方法例如以下: 方法步骤说明: 1.画布Canvas 2.在画布上把要显示的图画上去 3.把遮罩图片画上去,盖在要显示的图片上面 4.对这个遮罩图片设置一个非常重要的属性PorterDuff.Mode

android 开发 对图片编码,并生成gif图片

demo场景: 将2张静态的png格式图片组合生成一个gif图片,间隔500毫秒,关键类:AnimatedGifEncoder 如需要解析gif获取每帧的图片,可参考上一篇博客:<android 开发 解码gif图片,获取每帧bitmap> 使用方法: /** * 生成gif图片 */ void makeGif() { String path = Environment.getExternalStorageDirectory().getAbsolutePath() +"/data/d

网页保存为图片及高清截图的优化 | canvas跨域图片配置

本次技术调研来源于H5项目中的一个重要功能需求:实现微信长按网页保存为截图. 这里有个栗子(请用微信打开,长按图片即可保存):3分钟探索你的知识边界 将整个网页保存为图片是一个十分有趣的功能,常见于H5活动页的结尾页分享.以下则是项目中调研和踩坑的一些小结和汇总. 一.实现HTML网页保存为图片 1.1 已知可行方案 现有已知能够实现网页保存为图片的方案包括: 方案1:将DOM改写为canvas,然后利用canvas的toDataURL方法实现将DOM输出为包含图片展示的data URI 方案2

RoundedBitmapDrawable生成圆角图片

Bitmap src = BitmapFactory.decodeResource(getResources(), imageId); //获取Bitmap图片 RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), src); //创建RoundedBitmapDrawable对象 roundedBitmapDrawable.setCornerRadius

javaweb学习总结(九)—— 通过Servlet生成验证码图片

一.BufferedImage类介绍 生成验证码图片主要用到了一个BufferedImage类,如下: 创建一个DrawImage Servlet,用来生成验证码图片 1 package gacl.response.study; 2 import java.awt.Color; 3 import java.awt.Font; 4 import java.awt.Graphics; 5 import java.awt.Graphics2D; 6 import java.awt.image.Buff

python生成测试图片

直接代码 1 import cv2.cv as cv 2 saveImagePath = 'E:/ScreenTestImages/' 3 4 colorRed = [0,0,255] 5 colorGreen = [0,255,0] 6 colorBlue = [255,0,0] 7 colorWhite = [255,255,255] 8 colorBlack = [0,0,0] 9 colorAqua = [255,255,0] 10 colorFuchsia = [255,0,255]