当前位置: 首页 > 文档资料 > HTML5 Canvas 实战 >

2.11 融会贯通:绘制喷气式飞机

优质
小牛编辑
124浏览
2023-12-01

本节,我们将使用直线、曲线、图形、颜色、线性渐变、径向渐变,绘制一个矢量式的喷气式飞机,来把HTML5的画布API推到极限。

绘制喷气式飞机
图2-12 绘制喷气式飞机

绘制步骤

按照以下步骤,绘制一个矢量式的喷气式飞机:

1. 定义2D画布上下文,并设置直线交汇点样式:

window.onload  = function(){
  var canvas  = document.getElementById("myCanvas");
  var context = canvas.getContext("2d");
  var grd;
  context.lineJoin  = "round";

2. 绘制右侧尾翼:

  //右侧尾翼轮廓
  context.beginPath();
  context.moveTo(248,  60);  // 13 
  context.lineTo(262,  45);  // 12 
  context.lineTo(285,  56);  // 11 
  context.lineTo(284,  59);  // 10
  context.lineTo(276,  91);  // 9 
  context.closePath();
  context.fillStyle  = "#495AFE"; 
  context.fill();
  context.lineWidth  =  4; 
  context.stroke();
  //右侧尾翼细节
  context.beginPath();
  context.moveTo(281,  54);  //  10 
  context.lineTo(273,  84);  //  9 
  context.closePath();
  context.lineWidth  =  2; 
  context.stroke();

3. 绘制右翼:

  //右翼轮廓
  context.beginPath();
  context.moveTo(425,  159);
  context.lineTo(449,  91);   //  4 
  context.lineTo(447,  83);   //  5 
  context.lineTo(408,  67);   //  6 
  context.lineTo(343,  132);  //  7 
  context.fillStyle  = "#495AFE"; 
  context.fill();
  context.lineWidth  =  4; 
  context.stroke();
  //右翼细节
  context.beginPath();
  context.moveTo(420,  158);
  context.lineTo(447,  83);  //  4 
  context.lineWidth  =  2; 
  context.stroke();
  context.beginPath();
  context.moveTo(439,  102);
  context.lineTo(395,  81); 
  context.lineWidth  =  2; 
  context.stroke();

4. 绘制机身和机尾的顶部:

  //机身轮廓
  context.beginPath();
  context.moveTo(541,  300);  //  1
  context.quadraticCurveTo(529,  252,  490,  228);  //  2 
  context.quadraticCurveTo(487,  160,  303,  123);  //  3
  //机尾轮廓
  context.lineTo(213,  20);  //  14 
  context.lineTo(207,  22);  //  15
  context.bezierCurveTo(208,  164,  255,  207,  412,  271);  //  27 
  context.lineTo(427,  271);  //  28
  context.quadraticCurveTo(470,  296,  541,  300);  //  1 
  context.closePath();
  grd  = context.createLinearGradient(304,  246,  345,  155); 
  grd.addColorStop(0, "#000E91");  //深蓝色
  grd.addColorStop(1, "#495AFE");  //浅蓝色
  context.fillStyle  = grd;
  context.fill();
  context.lineWidth  =  4; 
  context.stroke();
  //机尾细节
  context.beginPath();
  context.moveTo(297,  124);
  context.lineTo(207,  22); 
  context.lineWidth  =  2; 
  context.stroke();

5. 绘制左侧尾翼:

  //左侧尾翼轮廓
  context.beginPath();
  context.moveTo(303,  121);  //  8 
  context.lineTo(297,  125);  //  8 
  context.lineTo(255,  104); 
  context.lineWidth  =  2; 
  context.stroke();
  context.beginPath();
  context.moveTo(212,  80);
  context.lineTo(140,  85);   //  18
  context.lineTo(138,  91);   //  19 
  context.lineTo(156,  105);  //  20 
  context.lineTo(254,  104);
  context.lineTo(254,  100); 
  context.lineWidth  =  4;
  context.fillStyle  = "#495AFE"; 
  context.fill();
  context.stroke();
  //左侧尾翼细节
  context.beginPath();
  context.moveTo(140,  86);   //  18 
  context.lineTo(156,  100);  //  20 
  context.lineTo(254,  100);
  context.lineTo(209,  77); 
  context.lineWidth  =  2; 
  context.stroke();

6. 绘制左翼:

  //左翼轮廓
  context.beginPath();
  context.moveTo(262,  166);  //  22 
  context.lineTo(98,  208);   //  23
  context.lineTo(96,  215);   //  24 
  context.lineTo(136,  245);  //  25 
  context.lineTo(339,  218);
  context.lineTo(339,  215);
  context.closePath();
  context.fillStyle  = "#495AFE"; 
  context.fill();
  context.lineWidth  =  4; 
  context.stroke();
  //左翼细节
  context.beginPath();
  context.moveTo(98,  210);
  context.lineTo(136,  240);  //  25 
  context.lineTo(339,  213); 
  context.lineWidth  =  2; 
  context.stroke();
  context.beginPath();
  context.moveTo(165,  235);
  context.lineTo(123,  203); 
  context.lineWidth  =  2; 
  context.stroke();

7. 绘制侧面细节:

  // 侧面细节
  context.beginPath();
  context.moveTo(427,  271);
  context.lineTo(423,  221);
  context.quadraticCurveTo(372,  175,  310,  155); 
  context.lineWidth  =  4;
  context.stroke();

8. 绘制机头细节:

  //机头细节
  context.beginPath();
  context.moveTo(475,  288);
  context.quadraticCurveTo(476,  256,  509,  243);
  context.quadraticCurveTo(533,  268,  541,  300);  //  1
  context.quadraticCurveTo(501,  300,  475,  288);
  grd  = context.createLinearGradient(491,  301,  530,  263);
  grd.addColorStop(0, "#9D0000");  // dark red
  grd.addColorStop(1, "#FF0000");  // light red 
  context.fillStyle  = grd;
  context.fill();
  context.lineWidth  =  4; 
  context.stroke();
  context.beginPath();
  context.moveTo(480,  293);
  context.quadraticCurveTo(480,  256,  513,  246); 
  context.lineWidth  =  2;
  context.stroke();

9. 绘制驾驶舱:

  //驾驶舱细节
  context.beginPath();
  context.moveTo(442,  169);
  context.quadraticCurveTo(419,  176,  415,  200); 
  context.quadraticCurveTo(483,  250,  490,  228); 
  context.quadraticCurveTo(480,  186,  439,  170); 
  context.lineWidth  =  4;
  context.stroke();
  grd  = context.createRadialGradient(473,  200,  20,  473,  200,  70); 
  grd.addColorStop(0, "#E1E7FF");  // 深灰色 
  grd.addColorStop(1, "#737784");  // 浅灰色 
  context.fillStyle  = grd;
  context.fill();
  context.beginPath();
  context.moveTo(448,  173);
  context.quadraticCurveTo(425,  176,  420,  204); 
  context.lineWidth  =  2;
  context.stroke();
  context.beginPath();
  context.moveTo(470,  186);
  context.quadraticCurveTo(445,  190,  440,  220); 
  context.lineWidth  =  2;
  context.stroke();

10. 绘制进气口:

  //进气口轮廓
  context.beginPath();
  context.moveTo(420,  265);
  context.lineTo(416,  223);
  context.bezierCurveTo(384,  224,  399,  270,  420,  265); 
  context.closePath();
  context.fillStyle  = "#001975"; 
  context.fill();
  context.lineWidth  =  4; 
  context.stroke();
  context.beginPath();
  context.moveTo(420,  265);
  context.lineTo(402,  253); 
  context.lineWidth  =  2; 
  context.stroke();
  context.beginPath();
  context.moveTo(404,  203);
  context.bezierCurveTo(364,  204,  379,  265,  394,  263); 
  context.lineWidth  =  2;
  context.stroke();
};

11. 在HTML文档的body部分嵌入canvas标签:

<canvas id="myCanvas" width="650" height="350" style="border:1px solid black;">
</canvas>

工作原理

本节,我们组合使用了直线、二次曲线、贝塞尔曲线、路径、图形、纯色填充、线性渐变、径向渐变。虽然HTML5的画布还不是十分成熟,但它确实提供了绘制伟大的绘画作品,包括矢量式的喷气式飞机,所需要的一切。

要在HTML5的画布中绘制喷气式飞机,可以从Adobe Photoshop或其它图像编辑器入手,先在图像编辑器中绘制出一个喷气式飞机,要求绘制区域跟画布尺寸完全相等,本例的画布尺寸为650 x 350像素。然后,通过鼠标光标,找到构成飞机形状的关键点,其方法是把鼠标光标放到每条线的终点,并记录这些点的x, y坐标。有了这些坐标点,我们用4px宽的线绘制飞机的主要轮廓,回头再用2px宽的线填充飞机的细节部分。

先绘制离观众最远的部分是一个良好实践,因为在画布上,后绘制的每一个图形都会覆盖先绘制的图形。看看前面的代码,你会看到,右翼最先被绘制,再是机身,再是左翼。这是因为右翼离观众最远,而左翼离观众最近。

当这些线条绘制完成,我们就可以使用纯色来填充该飞机,用线性渐变填充机身,用径向渐变填充驾驶舱,以便给飞机增加立体感。最后,为机头增加醒目的红色渐变,让它准备起飞并激发我们的想象力。