视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
canvas游戏开发学习之三:绘制复杂形状
2020-11-27 15:13:14 责编:小采
文档


贝塞尔和二次方曲线Bezier and quadratic curves

接下来要介绍的路径是贝塞尔曲线,它可以是二次和三次方的形式,一般用于绘制复杂而有规律的形状。

quadraticCurveTo(cp1x, cp1y, x, y) // BROKEN in Firefox 1.5 (see work around below)
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

上面两行代码的区别见右图。它们都有一个起点一个终点(图中的蓝点),但二次方贝塞尔曲线只有一个(红色)控制点点)而三次方贝塞尔曲线有两个。参数 x和y是终点坐标,cp1x和cp1y 是第一个控制点的坐标,cp2x和cp2y是第二个的。

使用二次方和三次方的贝塞尔曲线是相当有挑战的,因为不像在矢量绘图软件 Adobe Illustrator 里那样有即时的视觉反馈。因为用它来画复杂图形是比较麻烦的。但如果你有时间,并且最重要是有耐心,再复杂的图形都可以绘制出来的。下面我们来画一个简单 而又规律的图形。这些例子都比较简单。我们绘制的都是完整的图形。

// Quadratric curves example
ctx.beginPath();
ctx.moveTo(75,25);
ctx.quadraticCurveTo(25,25,25,62.5);
ctx.quadraticCurveTo(25,100,50,100);
ctx.quadraticCurveTo(50,120,30,125);
ctx.quadraticCurveTo(60,120,65,100);
ctx.quadraticCurveTo(125,100,125,62.5);
ctx.quadraticCurveTo(125,25,75,25);
ctx.stroke();

通过计算,可以由二次曲线的单个控制点得出相应三次方曲线的两个控制点,因此二次方转三次方是可能的,但是反之不然。仅当三次方程中的三次项为零是才可能转换为二次的贝塞尔曲线。通常地可以用多条二次方曲线通过细分算法来近似模拟三次方贝塞尔曲线。

// Bezier curves example
ctx.beginPath();
ctx.moveTo(75,40);
ctx.bezierCurveTo(75,37,70,25,50,25);
ctx.bezierCurveTo(20,25,20,62.5,20,62.5);
ctx.bezierCurveTo(20,80,40,102,75,120);
ctx.bezierCurveTo(110,102,130,80,130,62.5);
ctx.bezierCurveTo(130,62.5,130,25,100,25);
ctx.bezierCurveTo(85,25,75,37,75,40);
ctx.fill();

矩形路径 Rectangles

除了上面提到的三个方法可以直接绘制矩形之外,我们还有一个rect方法是用于绘制矩形路径的。

rect(x, y, width, height)

它接受四个参数,x和y 是其左上角坐标,width和height 是其宽和高。当它被调用时,moveTo方法会自动被调用,参数为(0,0),于是起始坐标又恢复成初始原点了。

综合样例

在整个例子里,最值得注意的是roundedRect函数的使用和fillStyle属性的设置。自定义函数对于封装复杂图形的绘制是非常有用的。在这个例子里使用自定义函数就省掉了大约一半的代码。在接下来的例子里会深入探讨fillStyle属性的使用。这里是用它来改变填充颜色,从默认的黑色,到白色,然后再回到黑色。

function draw() {
 var ctx = document.getElementById('canvas').getContext('2d');
 roundedRect(ctx,12,12,150,150,15);
 roundedRect(ctx,19,19,150,150,9);
 roundedRect(ctx,53,53,49,33,10);
 roundedRect(ctx,53,119,49,16,6);
 roundedRect(ctx,135,53,49,33,10);
 roundedRect(ctx,135,119,25,49,10);

 ctx.beginPath();
 ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false); //chiensexu 本来是true呵呵,反了
 ctx.lineTo(31,37);
 ctx.fill();
 for(i=0;i<8;i++){
 ctx.fillRect(51+i*16,35,4,4);
 }
 for(i=0;i<6;i++){
 ctx.fillRect(115,51+i*16,4,4);
 }
 for(i=0;i<8;i++){
 ctx.fillRect(51+i*16,99,4,4);
 }
 ctx.beginPath();
 ctx.moveTo(83,116);
 ctx.lineTo(83,102);
 ctx.bezierCurveTo(83,94,,88,97,88);
 ctx.bezierCurveTo(105,88,111,94,111,102);
 ctx.lineTo(111,116);
 ctx.lineTo(106.333,111.333);
 ctx.lineTo(101.666,116);
 ctx.lineTo(97,111.333);
 ctx.lineTo(92.333,116);
 ctx.lineTo(87.666,111.333);
 ctx.lineTo(83,116);
 ctx.fill();
 ctx.fillStyle = "white";
 ctx.beginPath();
 ctx.moveTo(91,96);
 ctx.bezierCurveTo(88,96,87,99,87,101);
 ctx.bezierCurveTo(87,103,88,106,91,106);
 ctx.bezierCurveTo(94,106,95,103,95,101);
 ctx.bezierCurveTo(95,99,94,96,91,96);
 ctx.moveTo(103,96);
 ctx.bezierCurveTo(100,96,99,99,99,101);
 ctx.bezierCurveTo(99,103,100,106,103,106);
 ctx.bezierCurveTo(106,106,107,103,107,101);
 ctx.bezierCurveTo(107,99,106,96,103,96);
 ctx.fill();
 ctx.fillStyle = "black";
 ctx.beginPath();
 ctx.arc(101,102,2,0,Math.PI*2,true);
 ctx.fill();
 ctx.beginPath();
 ctx.arc(,102,2,0,Math.PI*2,true);
 ctx.fill();
}
function roundedRect(ctx,x,y,width,height,radius){
 ctx.beginPath();
 ctx.moveTo(x,y+radius);
 ctx.lineTo(x,y+height-radius);
 ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
 ctx.lineTo(x+width-radius,y+height);
 ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
 ctx.lineTo(x+width,y+radius);
 ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
 ctx.lineTo(x+radius,y);
 ctx.quadraticCurveTo(x,y,x,y+radius);
 ctx.stroke();
}

下载本文
显示全文
专题