First of all we know that CSS3 added a lot of useful, fun CSS3 style can be used. Today we're talking about masks. Its use is not complex, and background use the same way. Use Mask-image to use, so that you can synthesize a picture with the shape of a composite diagram, do not need to directly use PS processing. CSS Matte--How to use masks in CSS, this article has explained in detail how masks are used, and I'm not going to dwell on them here. What I want to illustrate here today is how to make the logic of creating a synthetic picture through this. It is done in two ways: Front end Js+canvas, back end Nodejs+canvas, the basic idea is the same, but two ways, the latter compatibility slightly better. Based on the image synthesis, the whole idea is: first, according to the size of the mask layer, create a picture, followed by the original image according to a certain rule according to the mask layer size cut (drawImage) a picture and then synthesized to the mask layer above The last very important setting is: Globalcompositeoperation, when you set up a picture composition, combine operations.
front-end JS implementation
/** * Generate canvas matte (due to compatibility problem on Android phone, unused, with server interface generated) * @param imglist */utils.canvasmasking = function (imglist) { var _imgaddmask = function (img) {var deferred = $. Deferred (); var newimg = document.createelement (' img '); Newimg.setattribute (' Crossorigin ', ' Anonymous '); Solve cross-domain problem newimg.src = img.src; Source picture failed to load Newimg.onerror = function () {deferred.reject (' source picture failed to load '); }; Source picture loaded successfully 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 picture load Failed Mask.onerror = function () {Deferred.reject (' mask picture failed '); }; Mask picture loaded successfully 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; /** * Handle the original picture rotation, zoom *//move to the center point of the picture, consistent with the CSS center point Imagecontext.translate (IMAGECANVAS.WIDTH/2, IMAGECANVAS.HEIGHT/2); Imagecontext.scale (scale, scale); Imagecontext.rotate (angle); Restore the canvas center point to do Vertex imagecontext.translate (-IMAGECANVAS.WIDTH/2,-IMAGECANVAS.HEIGHT/2); Imagecontext.drawimage (IMG, 0, 0, imagecanvas.width, imagecanvas.height); /** * Combined mask and processed original figure */maskcontext.drawimage (mask, 0, 0, maskw Idth, Maskheight); Draws a source (new) image to the target (already existing) on the image 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 (); };
Because canvas is prohibited from cross-domain, there are two conditions that can be controlled:
- Header information for the picture must be set to allow cross-domain headers (access-control-allow-origin:*)
- The image tag created must also allow cross-domain (Img.setattribute (' Crossorigin ', ' Anonymous '))
The approximate implementation process is as follows:
Back-end node implementationThe back-end implementation of the general idea and the front-end JS operation Canvas basically almost. The backend needs to rely on the Node-canvas module, providing an almost identical API to the browser, so you can switch seamlessly. Detailed implementation instructions above, here is not described in detail, the main explanation may be Node-canvas installation and normal use. Because it is processing the picture, there are some requirements for the installation environment, which is slightly higher than the other module requirements. First he relied on Cairo. Some dependencies need to be installed, mainly to deal with the image of the library, to see the specific needs, mainly processing three kinds of pictures: 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 |
The information on this table is from GitHub. Here I explain the pit I've stepped on:
- The first time because there is no JPEG installation resulting in the processing of JPG pictures, there is a load failure prompt, encountered this situation can check their own library dependencies is not installed completely;
- After installing the JPEG library for the second time, I found that the problem was that my JPEG library was installed after I had finished installing Node-canvas.
- The third time you copy the node-modules installed on your Mac to the CentOS server, you find that the canvas is not ready for use. The reason is that their picture processing library is different and must be reinstalled Node-canvas
Sum up:
the prerequisite for installing Node-canvas is to install all dependent library files, and in different environments, you need to re-download the Node-canvas for installation, because Node-canvas compiles it every time. Other questions that are outside the question:
- What do I do if I need to move, zoom, or rotate when I compose a picture? You can do this using canvas's tranlate, scale, and rotate, and it is important to note that the rendering effect on the Web page is consistent with the composition processing.
- When multiple masks are synthesized on the front end, compatibility issues with different phones
- The page cannot download the generated image via the download button, and the picture of Canvas.otdataurl () cannot be long pressed to save
- When using Html2canvas to generate a picture of the DOM, you need to set the Allow cross-domain, if you want to use proxy, you can refer to the implementation.
- In addition Html2canvas generated canvas information when uploading base64, may appear 413,body entity too big hint, this time need to check the server or server language allowed body size is limited.
I am currently encountering a problem: the size of the browser at different resolutions and the image generated by my server is inconsistent? Being resolved ... Reference: https://github.com/niklasvh/html2canvashttps://github.com/Automattic/node-canvashttps:// Developer.mozilla.org/zh-cn/docs/web/api/canvasrenderingcontext2d
Canvas Create matte Picture