如何使用 CSS 剪辑路径剪辑画布?

Posted

技术标签:

【中文标题】如何使用 CSS 剪辑路径剪辑画布?【英文标题】:How to clip canvas with CSS clip-path? 【发布时间】:2013-07-09 18:58:47 【问题描述】:

我知道我可以通过使用getContext('2d') 创建路径并设置globalCompositeOperation 来剪辑画布。

我注意到,有时我可以在其他浏览器(我使用的是 Chrome)上使用 -webkit-clip-pathclip-path 剪辑画布,但有时我无法:

使用此 html

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

和 CSS:

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

产生这个:

这似乎是正确的。

但是,我注意到,如果我改变画布的高度,它就无法剪辑:

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

产生:

我的假设 ,它在浮点上裁剪(百分比在像素之间而不是像素上裁剪)有问题,但是从百分比更改为像素坐标不会裁剪。

*这里分别是他们的jsfiddle页面的链接:

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

有谁知道为什么一个有效而另一个无效?

是否有一种稳定 的方式来使用 CSS 剪辑画布元素,或者我是否需要使用画布上下文方法?

我问的原因是我想尽可能少用js。我有一串坐标,可以很容易地放入 css;而要使用 ctx.beginPath()...ctx.moveTo()...ctx.lineTo()...ctx.lineTo()... 方法,我需要对这些点执行 for 循环。

另外,我很好奇为什么第一个示例有效,如果有人可以解释的话。谢谢! :)

【问题讨论】:

【参考方案1】:

剪辑路径相对较新,可能容易出错(在 Aurora 中对我不起作用)。

为了获得稳定的结果,我建议只使用画布的clip() 方法(您不需要为此合成)。

您可以通过这种方式提供分数(此处为百分比):

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

几乎就像在 CSS 中定义一样简单。然后有一个函数来解析它:

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

结果:

DEMO HERE

(剪辑是在绘制操作发生之前设置的)。

只需将您的绘图操作放在一个函数中,您也可以在调整窗口大小时调用该函数(如上面的演示所示)。

更新

至于抗锯齿:实际上对图像应用了抗锯齿,但由于红色,很难检测到它,具体取决于屏幕类型,也许浏览器。放大版:

【讨论】:

谢谢肯。这是一个很好的工作示例。我实际上打算避免使用clip() 方法,以便我可以获得具有抗锯齿的多边形(更平滑的边缘,就像 CSS 会给出的那样):jsfiddle.net/bozdoz/TB9rX 知道为什么我的第一个示例有效但其他示例没有? @bozdoz 我只能推测,但这似乎是一个错误。如果在应用剪辑后调整元素大小,则剪辑似乎丢失了。您可以通过使用 JS 重新应用 css-class 来进行测试:document.getElementById('canvas').className = 'canvas';(当然您需要更改 CSS 以便规则为 class)。 @bozdoz 关于抗锯齿:试试这条线:context.translate(0.5, 0.5); 更新小提琴:jsfiddle.net/AbdiasSoftware/CmaUy/2(答案中的图像确实有抗锯齿,但红色可能很难根据屏幕类型查看)。 我认为它因浏览器而异:***.com/questions/9536257/…【参考方案2】:

我从未使用过-webkit-clip-path:,但作为一种解决方法,我会尝试将剪辑路径应用于包含画布而不是画布本身的元素。

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

【讨论】:

以上是关于如何使用 CSS 剪辑路径剪辑画布?的主要内容,如果未能解决你的问题,请参考以下文章

使用 CSS 剪辑路径时如何圆角

javascript - 如何使用 drawImage/putImageData 进行剪辑

css 剪辑路径形状不适用于 ie 或者我如何使用 css 创建它

如何创建中间有孔的画布 html5 剪辑区域?

如何在 HTML5 画布中剪辑多个形状的 INSIDE union?

如何在 html 5 画布中删除区域的剪辑