简体   繁体   中英

Make rectangle overlay image with canvas

I'd like to reach the following with HTML5 canvas:

目标

My code: jsfiddle

// Options
var maxImageWidth = 250,
    maxImageHeight = 196,
    radius = 50;

var canvas = $('#ddayCanvas'),
    canvasWidth = canvas.width(),
    canvasHeight = canvas.height(),
    sectorColor = $('.product-box').css('background-color'),
    context = canvas[0].getContext('2d'),
    imageSrc = canvas.data('image');  


function drawDday (option) {

    var imageObj = new Image();
    imageObj.onload = function() {

        if (option == 'clip'){
            context.save();
            context.clip();
        }

        var imageWidth = imageObj.width,
            imageHeight = imageObj.height;

        if (imageWidth > maxImageWidth){
            imageHeight = imageHeight - (imageWidth - maxImageWidth);
            imageWidth = maxImageWidth;
        }

        if (imageHeight > maxImageHeight) {
            imageWidth = imageWidth - (imageHeight - maxImageHeight);
            imageHeight = maxImageHeight;
        }

        context.drawImage(imageObj, Math.ceil((canvasWidth - imageWidth) / 2), Math.ceil((canvasHeight - imageHeight) / 2), imageWidth, imageHeight);

    };

    imageObj.src = imageSrc;  

}

drawDday(); 

// Why does this rectangle not overlay the previous image?
context.fillStyle = sectorColor;
context.fillRect(0, 0, canvasWidth, canvasHeight);

drawDday('clip');      

context.restore();
context.moveTo(0, 0);
context.beginPath();
context.fillStyle = '#fff';
context.arc(canvasWidth / 2, canvasHeight/2, radius, 0, 2*Math.PI);
context.fill();

Why does the rectangular I'm drawing not overlay the previous image? It's also weird that the canvas is drawn differently sometimes when reloading the site..

You have the image being drawn in the asynchronous callback onload. The result will change depending on if the image loads first, or the canvas draw is called first.

Try moving your draw code into the same callback.

For more efficient clipping you can use the non-zero winding order rule: http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/

TLDR: Consecutive canvas draw calls will add or subtract from the previous calls depending on whether the order of points is clockwise or anti-clockwise.

See: http://jsfiddle.net/jJjt7/2/

context.fillStyle = sectorColor;
context.rect(0, 0, canvasWidth, canvasHeight);
context.arc(canvasWidth/2, canvasHeight/2, radius, 0, Math.PI*2, true);
context.fill();

The above example draws a rectangle with a clockwise point order, then subtracts the arc (circle) by using an anti-clockwise point order. The last argument of the arc method defines 'anti-clockwise'. In this case true.

Edit: This negates the need to draw twice. Efficiency, FTW.

You need to change the order that you're drawing the objects.

// Why does this rectangle not overlay the previous image?
context.fillStyle = sectorColor;
context.fillRect(0, 0, canvasWidth, canvasHeight);

drawDday('clip');      
drawDday(); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM