夹子的奇怪行为?

时间:2016-01-12 14:46:41

标签: javascript html5 canvas clip

以下内容会创建一个意外的剪辑路径。是因为 从一个弧的末端移动到下一个弧的开始?圆圈原来是椭圆形,这也是出乎意料的。

var canvas3=document.getElementById("drawing3"); 
var ct=canvas3.getContext("2d"); 

ct.beginPath();
ct.arc(50,80,30,0,Math.PI*2,false);
ct.arc(120,40,60,0,Math.PI*2,true);
ct.arc(180,40,30,0,Math.PI*2,true);
ct.arc(240,40,30,0,Math.PI*2,true);
ct.clip();

ct.fillStyle="yellow";
ct.fillRect(10,10,400,200);
ct.fillStyle="magenta";
ct.font = "40px sans-serif";
ct.fillText("what's this?",30,70);

顺便说一下,剪辑区域是否总是必须以beginPath()?

开头

1 个答案:

答案 0 :(得分:0)

为什么使用椭圆而不是弧

虽然您不包含CSS,但使用CSS调整canvas元素大小时,画布图形会变形。 html5画布的默认大小为300x150,因此使用CSS调整其大小将拉伸或挤压后续绘图,除非CSS完全按照原始2:1的比例调整画布大小。

因此,如果要调整画布大小,请通过直接更改元素的大小来调整大小:

var canvas3=document.getElementById("drawing3"); 
canvas3.width=400;
canvas3.height=300;

为什么beginPath有用(必不可少!)

context.clip始终作用于最后一组路径命令,一组路径命令context.beginPath启动。所以是的,剪辑始终以context.beginPath开头。

为什么beginPath有用(总是使用它!):如果您发出多组路径命令而不使用beginPath启动每个集合,那么每个新集合也将执行所有以前的集合。你的道路只会变成一幅长图,而不是有不同的图画。

修复相互关联的圈子

context.arc是画布路径绘图命令。

路径命令将始终连接(使用一条线)context.beginPathcontext.stroke or context.fill之间出现的所有绘图。

但您可以使用context.moveTo指定“拿起铅笔并将其移至下一个圆心”的路径。这样可以防止您的圈子相互连接。

// pick up the pencil and move it to the next arc's centerpoint
ct.moveTo(x,y);
// and draw the arc around the centerpoint
ct.arc(x,y,r,0,Math.PI*2,false);

enter image description here

这是你的代码重构为在弧之间“拿起铅笔”:

var canvas3=document.getElementById("drawing3"); 
var ct=canvas3.getContext("2d"); 

ct.beginPath();
arcAtXY(50,80,30);
arcAtXY(120,40,60);
arcAtXY(180,40,30);
arcAtXY(240,40,30);
ct.clip();

ct.fillStyle="yellow";
ct.fillRect(10,10,400,200);
ct.fillStyle="magenta";
ct.font = "40px sans-serif";
ct.fillText("what's this?",30,70);

function arcAtXY(x,y,r){
    ct.moveTo(x,y);
    ct.arc(x,y,r,0,Math.PI*2,false);
}
canvas{border:1px solid red;}
<canvas id="drawing3" width=300 height=300></canvas>

与您的设计没有直接关系的其他想法

如果您想要描边圆圈而不是填充它们,您将移动到下一个圆圈的周边而不是其中心点。移动到中心点会导致自动线从中心点绘制到周边。

function arcAtXY(x,y,r){
    ct.moveTo(x+r,y);
    ct.arc(x,y,r,0,Math.PI*2,false);
}