javascriptcanvashtml5-canvascomposition

Canvas image masking / overlapping


In my project i have to implement one different color image on the other same size and pattern image using canvas and images are not in round or rectangle shapes. That all are in waves shape and it will apply on a single main background image for showing multiple graphics on every onclick function.

Overlapped image should be change in another selected color. My question Is there any way with using canvas from that we can change the image color which is draw by canvas or we need to use different images always and apply with CSS/jQuery.

I read about canvas image masking and overlapping. But cant understand with my images because that are not in square or circle shape then first thing is how i draw multiple wave shapes on a single image. I have no idea about that i searched but fail to search perfect solution.

My need is just draw one wave image on canvas and change its color from on click function and also set an another div with background-image and also more then two canvas will overlapped. Is this possible?

(That means : This functionality is for create or set multiple graphics on a car, for that each graphic image need to set in a canvas and for another graphic need to overlapped on div and first canvas)


Solution

  • You can use context compositing to replace part of an image.

    For example, if you have this blue logo already as an image:

    enter image description here

    Any you want the top part of the logo to be colored purple:

    enter image description here

    You can use compositing to recolor the top part of the image.

    First, use your favorite image editor to crop away any part you don’t want recolored.

    What’s left is called an overlay.

    This overlay part of the image is what we will programmatically recolor.

    enter image description here

    This overlay can be programatically recolored to any color.

    enter image description hereenter image description here

    How the overlay was programatically recolored:

    1. Draw the overlay on an empty canvas.
    2. Set the compositing mode to “source-in”.
    3. The Effect: Only existing pixels are replaced—transparent pixels remain transparent
    4. Now draw a rectangle of any color the covering the canvas
    5. (remember, only the existing overlay will be replaced with the new color)

    How to complete the logo with the changed overlay color

    1. Set the compositing mode to “destination-atop”
    2. The Effect: Only transparent pixels are replaced—existing pixels remain unchanged
    3. Now draw the original logo
    4. (remember, the existing colored overlay will not be replaced)

    This "destination-atop" compositing effect is sometimes called “drawing under”.

    This overlay can even be replace with textures!

    enter image description here

    Here is code and a Fiddle: http://jsfiddle.net/m1erickson/bfUPr/

    <!doctype html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    
    <style>
        body{ background-color: ivory; padding:20px; }
        #canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
    
        var truck,logo,overlay;
        var newColor="red";
    
        var imageURLs=[];
        var imagesOK=0;
        var imgs=[];
        imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/boxTruck.png");
        imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/TVlogoSmall.png");
        imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/TVlogoSmallOverlay.png");
        loadAllImages();
    
        function loadAllImages(){
            for (var i = 0; i < imageURLs.length; i++) {
              var img = new Image();
              imgs.push(img);
              img.onload = function(){ imagesOK++; imagesAllLoaded(); };
              img.src = imageURLs[i];
            }      
        }
    
        var imagesAllLoaded = function() {
          if (imagesOK==imageURLs.length ) {
             // all images are fully loaded an ready to use
             truck=imgs[0];
             logo=imgs[1];
             overlay=imgs[2];
             start();
          }
        };
    
    
        function start(){
    
            // save the context state
            ctx.save();
    
            // draw the overlay
            ctx.drawImage(overlay,150,35);
    
            // change composite mode to source-in
            // any new drawing will only overwrite existing pixels
            ctx.globalCompositeOperation="source-in";
    
            // draw a purple rectangle the size of the canvas
            // Only the overlay will become purple
            ctx.fillStyle=newColor;
            ctx.fillRect(0,0,canvas.width,canvas.height);
    
            // change the composite mode to destination-atop
            // any new drawing will not overwrite any existing pixels
            ctx.globalCompositeOperation="destination-atop";
    
            // draw the full logo
            // This will NOT overwrite any existing purple overlay pixels
            ctx.drawImage(logo,150,35);
    
            // draw the truck
            // This will NOT replace any existing pixels
            // The purple overlay will not be overwritten
            // The blue logo will not be overwritten
            ctx.drawImage(truck,0,0);
    
            // restore the context to it's original state
            ctx.restore();
    
        }
    
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <canvas id="canvas" width=500 height=253></canvas>
    </body>
    </html>