2.11 融会贯通:绘制喷气式飞机
优质
小牛编辑
124浏览
2023-12-01
本节,我们将使用直线、曲线、图形、颜色、线性渐变、径向渐变,绘制一个矢量式的喷气式飞机,来把HTML5的画布API推到极限。
绘制步骤
按照以下步骤,绘制一个矢量式的喷气式飞机:
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宽的线填充飞机的细节部分。
先绘制离观众最远的部分是一个良好实践,因为在画布上,后绘制的每一个图形都会覆盖先绘制的图形。看看前面的代码,你会看到,右翼最先被绘制,再是机身,再是左翼。这是因为右翼离观众最远,而左翼离观众最近。
当这些线条绘制完成,我们就可以使用纯色来填充该飞机,用线性渐变填充机身,用径向渐变填充驾驶舱,以便给飞机增加立体感。最后,为机头增加醒目的红色渐变,让它准备起飞并激发我们的想象力。