How to clip canvas with CSS clip-path?

一世执手 提交于 2020-01-15 09:10:44

问题


I know that I can clip a canvas by creating a path with getContext('2d') and setting globalCompositeOperation.

I've noticed that sometimes I'm able to clip a canvas with -webkit-clip-path, or clip-path on other browsers (I'm on Chrome), and sometimes I'm not able to:

Using this HTML:

<canvas width="300" height="60"></canvas>

and CSS:

canvas { -webkit-clip-path: polygon(50% 33%, 75% 10%, 80% 80%, 60% 75%, 40% 60%, 20% 10%, 40% 20%, 50% 33%);
}

produces this:

Which appears to be correct.

However, I've noticed that if I change the height of the canvas, it fails to clip:

<canvas width="300" height="250"></canvas>

produces:

My assumption was that it has a problem clipping on floating points (where the percentages clip between pixels instead of on pixels), but changing from percents to pixel coordinates doesn't clip.

*Here are links to their jsfiddle pages respectively:

  • http://jsfiddle.net/bozdoz/hMTgc/
  • http://jsfiddle.net/bozdoz/5H2Y2/

Does anyone know why one works but the other doesn't?

Is there a stable way to clip canvas elements with CSS, or do I need to use the canvas context methods?

The reason I ask is that I'd like to use less js where possible. I have a string of coordinates which I can easily put into css; whereas, to use the ctx.beginPath()...ctx.moveTo()...ctx.lineTo()...ctx.lineTo()... method I'll need to do a for loop for the points.

Also, I'm very curious as to why the first example worked, if anyone can explain that. Thanks! :)


回答1:


The clip-path is relative new and could be prone to errors (didn't work for me in Aurora).

For a stable result I would suggest just using canvas' clip() method (you don't need composite for this).

You can provide the points in this way (here percentages):

var path = [50, 33, 75, 10, 80, 80, 60, 75, 40, 60, 20, 10, 40, 20, 50, 33];

Almost as easy as defining in CSS. Then have a function to parse it:

function addClip(context, path) {

    var w = context.canvas.width,
        h = context.canvas.height;

    context.beginPath();
    context.moveTo(path[0] * w / 100, path[1] * h / 100);
    for(var i = 2; i < path.length; i+=2) {
        context.lineTo(path[i] * w / 100, path[i+1] * h / 100);
    }
    context.closePath();
    context.clip();
}

Result:

DEMO HERE

(The clip is set before the drawing operations take place).

Just put your drawing operations in a function which you can call when window is re-sized as well (shown in demo above).

Update

As to anti-alias: there is actually applied anti-alias to the image but because of the red color it can be hard to detect it depending on type of screen and perhaps browser. An enlarged version:




回答2:


I've never worked with -webkit-clip-path:, but just on general principles I'd try, as a workaround, applying the clip path to an element containing the canvas instead of the canvas itself.

 <div class='canvas-wrapper'><canvas></canvas></div>
 .canvas-wrapper {
    display: table;   /* shrinkwrap around canvas */
    -webkit-clip-path: ...;
 }


来源:https://stackoverflow.com/questions/17556088/how-to-clip-canvas-with-css-clip-path

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!