首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >globalCompositeOperation和同心、空心、移动的形状

globalCompositeOperation和同心、空心、移动的形状
EN

Stack Overflow用户
提问于 2014-04-09 19:29:22
回答 1查看 387关注 0票数 0

我正在努力实现以下目标:

在画布上画了许多同心圆(或环)。每个圆圈都有一个“洞”,所以后面画的较小的圆圈是部分可见的。每个帧(我们使用window.requestAnimationFrame渲染),每个圆圈/形状/环的半径略有增加。

在图像这里中描述了一个有两个环的场景。

守则:

代码语言:javascript
运行
复制
function draw() {
    drawBgr();
    for (var i = 0, len = rings.length; i < len; i++) {
        rings[i].draw();
    }
}

function drawBgr() {
    context.globalCompositeOperation = "source-over";
    context.clearRect(0, 0, WIDTH, HEIGHT);
    context.rect(0, 0, WIDTH, HEIGHT);
    context.fillStyle = '#FFFFFF';
    context.fill();
}

function squareRing(ring) { //called by rings[i].draw();
    context.globalCompositeOperation = "source-over";

    context.fillRect(ring.centerX - ring.radius / 2, ring.centerY - ring.radius / 2, ring.radius, ring.radius);
    context.globalCompositeOperation = "source-out";

    context.beginPath();
    context.arc(CENTER_X, CENTER_Y, ring.radius, 0, 2 * Math.PI, false);
    //context.lineWidth = RING_MAX_LINE_WIDTH * (ring.radius / MAX_SIDE);
    context.fillStyle = '#000000';
    context.fill();
    context.globalCompositeOperation = "source-over";

}
  1. 这里到底有什么问题?我在画圆圈之前给clearRect打电话。看看“我得到了什么”的形象。这是在多个框架上绘制单个环的结果。我不应该得到任何不同的东西,就像一个中间有一个空心正方形的黑色圆圈。(请注意,每个帧的半径都在增加。)
  2. 我确实意识到切换globalCompositeOperation可能不足以达到我想要的效果。我如何在画布上绘制的对象中画一个“洞”,而不删除我试图修改的对象下面的“孔”中的所有内容?

是我用来引用globalCompositeOperation值的教程。

我正在使用Firefox 28.0。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-10 10:48:38

我不会尝试使用globalCompositeOperation,因为我发现在几次迭代之后很难知道会发生什么,如果画布以前没有被清除,就更难了。

我更喜欢剪裁,这让我想到了:

http://jsbin.com/guzubeze/1/edit?js,output

那么,要在抽签中建立一个“洞”,如何使用裁剪?

->>定义一个正切子路径,在这个区域内,切断一个负部分,此时使用顺时针方向的子路径:

裁剪必须只使用一条路径,因此不能使用rect():它每次都会开始一个路径,并且不允许选择时钟(:-),因此您必须定义这两个函数,这两个函数只需创建所需的子路径:

代码语言:javascript
运行
复制
// clockwise sub-path of a rect
function rectPath(x,y,w,h) {
  ctx.moveTo(x,y);
  ctx.lineTo(x+w,y);
  ctx.lineTo(x+w,y+h);
  ctx.lineTo(x,y+h);
}

// counter-clockwise sub-path of a rect
function revRectPath(x,y,w,h) {
  ctx.moveTo(x,y);
  ctx.lineTo(x,y+h);
  ctx.lineTo(x+w,y+h);
  ctx.lineTo(x+w,y);  
}

然后您可以编写绘图代码:

代码语言:javascript
运行
复制
function drawShape(cx, cy, d, scale, rotation) {
  ctx.save();
  ctx.translate(cx,cy);
  scale = scale || 1;
  if (scale !=1) ctx.scale(scale, scale);
  rotation = rotation || 0;
  if (rotation) ctx.rotate(rotation);
  // clip with rectangular hole
  ctx.beginPath();
  var r=d/2; 
  rectPath(-r,-r, d, d);
  revRectPath(-0.25*r,-0.8*r, 0.5*r, 1.6*r);
  ctx.closePath();
  ctx.clip();
  ctx.beginPath();
  // we're clipped !
  ctx.arc(0,0, r, 0, 2*Math.PI);
  ctx.closePath();
  ctx.fill();
  ctx.restore();
}

编辑:

为了记录在案,有一个更简单的方法来绘制所要求的方案:只需画一个圆圈,然后逆时针画一个内直角。你所填写的将是圆圈内位于rect之外的部分,这就是你想要的:

代码语言:javascript
运行
复制
function drawTheThing(x,y,r) {
   ctx.beginPath();
   ctx.arc(x ,y, r, 0, 2*Math.PI);
   revRectPath(x-0.25*r, y-0.8*r, 0.5*r, 1.6*r);
   ctx.fill();
   ctx.closePath();
}

(我不发图片:这是一样的)。

根据你的需要,如果你改变了抽签,或者你想引入某种一般性,使用第一个或第二个。如果以后不更改方案,则第二个解决方案更简单一些,=>更好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22972222

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档