用canvas绘制矩形覆盖图像。

时间:2021-08-04 16:50:08

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

我想通过HTML5 canvas达到以下目标:

用canvas绘制矩形覆盖图像。

My code: jsfiddle

我的代码: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..

为什么我画的矩形没有覆盖之前的图像?同样奇怪的是,当重新加载站点时,画布的绘制方式会有所不同。

2 个解决方案

#1


2  

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.

在异步回调onload中绘制映像。结果将根据图像的加载顺序而变化,或者首先调用画布。

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/

为了更有效的剪切,您可以使用非零卷取顺序规则: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.

TLDR:连续的canvas draw调用将根据点的顺序是顺时针还是逆时针的,来增加或减去之前的调用。

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

参见: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.

编辑:这就不需要画两次。效率、增值。

#2


1  

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(); 

#1


2  

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.

在异步回调onload中绘制映像。结果将根据图像的加载顺序而变化,或者首先调用画布。

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/

为了更有效的剪切,您可以使用非零卷取顺序规则: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.

TLDR:连续的canvas draw调用将根据点的顺序是顺时针还是逆时针的,来增加或减去之前的调用。

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

参见: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.

编辑:这就不需要画两次。效率、增值。

#2


1  

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();