超出范围时的 JavaScript 画布裁剪形状

Posted

技术标签:

【中文标题】超出范围时的 JavaScript 画布裁剪形状【英文标题】:JavaScript canvas clipping shape when out of bounds 【发布时间】:2016-01-24 10:39:51 【问题描述】:

我所要求的可能非常简单,但我在获得预期结果时遇到了很多麻烦。

我想要一个形状(在本例中是正方形,但应与其他形状如圆形等一起使用)在离开另一个形状的边界时自行切断。

基本上,顶部图像是我想要的,底部是我目前拥有的: http://imgur.com/a/oQkzG

我听说这可以通过 globalCompositeOperation 来完成,但我正在寻找任何能够提供所需结果的解决方案。

这是当前代码,如果你不能使用 JSFiddle:

// Fill the background
ctx.fillStyle = '#0A2E36';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Fill the parent rect
ctx.fillStyle = '#CCA43B';
ctx.fillRect(100, 100, 150, 150);

// Fill the child rect
ctx.fillStyle = 'red';
ctx.fillRect(200, 200, 70, 70);

// And fill a rect that should not be affected
ctx.fillStyle = 'green';
ctx.fillRect(80, 80, 50, 50);

JSFiddle Link

【问题讨论】:

问题是我无法弄清楚将它们放在哪里或使用哪些,即使在阅读了该指南之后我也无法获得预期的效果。 ctx.globalCompositeOperation='source-over' ctx.fillStyle='yellow'; ctx.fillRect(10,10,50,50); ctx.fillStyle='green' ctx.fillRect(0,0,20,20) ctx.globalCompositeOperation='source-atop'; ctx.fillStyle='red' ctx.fillRect(40,40,20,20) 【参考方案1】:

由于您需要对象之间的某种关系(场景图),您现在应该构建它。 从您的问题来看,似乎任何子元素都应该被其父元素裁剪。 (是的,复合操作可以派上用场,但只有在清除背景上绘制 2 个图形时才会派上用场,否则事情会很快变得复杂,并且您可能必须使用背面画布,因此这里的剪切更简单。)

我在处理 rect 大小写的最基本的类下面做了,你会发现它不是很难构建。

“场景”由背景矩形组成,它有两个孩子,黄色和绿色。黄色的 Rect 有一个红色的孩子。

var canvas = document.getElementById('cv');
var ctx = canvas.getContext('2d');

function Rect(fill, x, y, w, h) 
    var childs = [];
    this.draw = function () 
        ctx.save();
        ctx.beginPath();
        ctx.fillStyle = fill;
        ctx.rect(x, y, w, h);
        ctx.fill();
        ctx.clip();
        for (var i = 0; i < childs.length; i++) 
            childs[i].draw();
        
        ctx.restore();
    
    this.addChild = function (child) 
        childs.push(child);
    
    this.setPos = function (nx, ny) 
        x = nx;
        y = ny;
    


// background
var bgRect = new Rect('#0A2E36', 0, 0, canvas.width, canvas.height);
// One parent rect
var parentRect = new Rect('#CCA43B', 100, 100, 150, 150);
// child rect
var childRect = new Rect('red', 200, 200, 70, 70);
parentRect.addChild(childRect);
//  Another top level rect
var otherRect = new Rect('green', 80, 80, 50, 50);

bgRect.addChild(parentRect);
bgRect.addChild(otherRect);

function drawScene() 
    bgRect.draw();
    drawTitle();


drawScene();

window.addEventListener('mousemove', function (e) 
    var rect = canvas.getBoundingClientRect();
    var x = (e.clientX - rect.left);
    var y = (e.clientY - rect.top);
    childRect.setPos(x, y);
    drawScene();
);

function drawTitle() 
    ctx.fillStyle = '#DDF';
    ctx.font = '14px Futura';
    ctx.fillText('Move the mouse around.', 20, 24);
&lt;canvas id='cv' width=440 height=440&gt;&lt;/canvas&gt;

【讨论】:

你是对的,这样对 OP 代码的未来会更好。不过需要注意的是,当更多浏览器支持它时,应该使用Path2D() 接口来简化它。

以上是关于超出范围时的 JavaScript 画布裁剪形状的主要内容,如果未能解决你的问题,请参考以下文章

Flutter实现圆形头像的几种方法

如何在 HTML5 画布中剪辑 INSIDE 形状?

javascript将画布裁剪为内容

javascript将图像裁剪到画布

Javascript/jQuery:从画布中删除形状/路径

使用 javascript 从 HTML5 画布镜像形状