游戏开发之旅-JavaScript绘制图形

createh54周前 (03-23)技术教程6

本节是第四讲的第二十二小节,上一节课为大家介绍了Ajax技术,包括XmlHttpRequest对象和FetchAPI的基本用法,本节为大家继续介绍JavaScript绘制图形的方法(Canvas API),有关WebGL的实例请参见视频课程的内容。

网络图形

我们来讨论 HTML 的 多媒体和嵌入式 模块,早先的网页只有单调的文字,后来才引入了图像,起初是通过 元素的方式,后来出现了类似于 background-image 的 CSS 属性和 SVG 图像等方式。然而,这还不够好。当你能够使用 CSS 和 JavaScript 让 SVG 矢量图动起来时,位图却依然没有相应的支持。同时 SVG 动画的可用工具也少得可怜。有效地生成动画、游戏画面、3D场景和其他的需求依然没有满足,而这些在诸如 C++ 或者 Java 等低级语言中却司空见惯。当浏览器开始支持 HTML 画布元素 和相关的 Canvas API(由苹果公司在 2004 年前后发明,后来其他的浏览器开始跟进)时,形势开始改善。下面你会看到,canvas 提供了许多有用的工具,特别是当捆绑了由网络平台提供的一些其他的 API 时。它们用来生成 2D 动画、游戏画面和数据分析图,以及其他类型的 app。

2D画布基础

以下是绘制图形的基础代码:

var canvas = document.querySelector('.myCanvas');

var width = canvas.width = window.innerWidth;

var height = canvas.height = window.innerHeight;

var ctx = canvas.getContext('2d');

ctx.fillStyle = 'rgb(0, 0, 0)';

ctx.fillRect(0, 0, width, height);

所有绘画操作都离不开 CanvasRenderingContext2D 对象(这里叫做 ctx)。许多操作都需要提供坐标来指示绘图的确切位置,如下图所示,画布左上角的坐标是(0, 0),横坐标(x)轴向右延伸,纵坐标(y)轴向下延伸。



简单矩形

ctx.fillStyle = 'rgb(255, 0, 0)';

ctx.fillRect(50, 50, 100, 150);

画布上将出现一个红色的矩形。其左边和顶边与画布边缘距离均为 50 像素(由前两个参数指定),宽 100 像素、高 150 像素(由后两个参数指定)。

ctx.fillStyle = 'rgba(255, 0, 255, 0.75)';

ctx.fillRect(25, 100, 175, 50);

通过指定半透明的颜色来绘制半透明的图形,比如使用 rgba()。 a 指定了“α 通道”的值,也就是颜色的透明度。值越高透明度越高,底层的内容就越清晰。

描边(stroke)和线条宽度

ctx.strokeStyle = 'rgb(255, 255, 255)';

ctx.strokeRect(25, 25, 175, 200);

ctx.lineWidth = 5;

目前我们绘制的矩形都是填充颜色的,我们也可以绘制仅包含外部框线(图形设计中称为描边)的矩形。你可以使用 strokeStyle 属性来设置描边颜色,使用 strokeRect 来绘制一个矩形的轮廓。默认的描边宽度是 1 像素,可以通过调整 lineWidth 属性的值来修改。

绘制路径

ctx.fillStyle = 'rgb(255, 0, 0)';

ctx.beginPath();

ctx.moveTo(50, 50);

// 绘制路径

ctx.fill();

可以通过绘制路径来绘制比矩形更复杂的图形。路径中至少要包含钢笔运行精确路径的代码以确定图形的形状。画布提供了许多函数用来绘制直线、圆、贝塞尔曲线等等。

一些通用的方法和属性将贯穿以下全部内容:

beginPath():在钢笔当前所在位置开始绘制一条路径。在新的画布中,钢笔起始位置为 (0, 0)。

moveTo():将钢笔移动至另一个坐标点,不记录、不留痕迹,只将钢笔“跳”至新位置。

fill():通过为当前所绘制路径的区域填充颜色来绘制一个新的填充形状。

stroke():通过为当前绘制路径的区域描边,来绘制一个只有边框的形状。

路径也可和矩形一样使用 lineWidth 和 fillStyle / strokeStyle 等功能。

等边三角形

function degToRad(degrees) {

return degrees * Math.PI / 180;

};

ctx.fillStyle = 'rgb(255, 0, 0)';

ctx.beginPath();

ctx.moveTo(50, 50);

ctx.lineTo(150, 50);

var triHeight = 50 * Math.tan(degToRad(60));

ctx.lineTo(100, 50+triHeight);

ctx.lineTo(50, 50);

ctx.fill();

首先绘制一条直线,终点坐标为 (150, 50)。此时路径沿 x 轴向右行走 100 像素。然后利用三角函数来计算等边三角形的高。这里我们要绘制的三角形是朝下的。等边三角形每个角均为 60°,为计算高的值,我们可以将三角形从正中心分割为两个直角三角形,每个直角三角形的三个角分别为 90°、60°、30°。


通过基本三角函数可得:临边长度乘以角的正切等于对边长度。于是可得三角形的高为 50 * Math.tan(degToRad(60))。由于 Math.tan() 接受数值的单位为弧度,于是我们用刚才的 degToRad() 函数将 60° 换算为弧度。有了三角形的高,我们来绘制另一条线,终点坐标为 (100, 50+triHeight)。

画圆

ctx.fillStyle = 'rgb(0, 0, 255)';

ctx.beginPath();

ctx.arc(150, 106, 50, degToRad(0), degToRad(360), false);

ctx.fill();

arc() 函数有六个参数。前两个指定圆心的位置坐标,第三个是圆的半径,第四、五个是绘制弧的起、止角度(给定 0° 和 360° 便能绘制一个完整的圆),第六个是绘制方向(false 是顺时针,true 是逆时针)。

ctx.fillStyle = 'yellow';

ctx.beginPath();

ctx.arc(200, 106, 50, degToRad(-45), degToRad(45), true);

ctx.lineTo(200, 106);

ctx.fill();

将 arc() 的最后一个参数设置为 true,意味着弧将逆时针绘制,也就意味着即使起、止角度分别设置为 -45°、45°,我们还是得到了区域外的一条 270° 的弧。

文本

ctx.strokeStyle = 'white';

ctx.lineWidth = 1;

ctx.font = '36px arial';

ctx.strokeText('Canvas text', 50, 50);

ctx.fillStyle = 'red';

ctx.font = '48px georgia';

ctx.fillText('Canvas text', 50, 150);

fillText() :绘制有填充色的文本。

strokeText():绘制文本外边框(描边)。

这两个函数有三个基本的参数:需要绘制的文字、文本框(顾名思义,围绕着需要绘制文字的方框)左上顶点的X、Y坐标。

还有一系列帮助控制文本渲染的属性:比如用于指定字体族、字号的 font,它的值和语法与 CSS 的 font 属性一致。

在画布上绘制图片

var image = new Image();

image.src = 'flower.png';

ctx.drawImage(image, 20, 20, 185, 175, 50, 50, 185, 175);

第一个参数为图片引用。参数 2、3 表示裁切部分左上顶点的坐标,参考原点为原图片本身左上角的坐标。原图片在该坐标左、上的部分均不会绘制出来。参数 4、5 表示裁切部分的长、宽。参数 6、7 表示裁切部分左上顶点在画布中的位置坐标,参考原点为画布左上顶点。参数 8、9 表示裁切部分在画布中绘制的长、宽。

创建一个循环

ctx.translate(width/2, height/2);

function degToRad(degrees) {

return degrees * Math.PI / 180;

};

var length = 250;

var moveOffset = 20;

for(var i = 0; i < length; i++) {

ctx.fillStyle = 'rgba(' + (255-length) + ', 0, ' + (255-length) + ', 0.9)';

ctx.beginPath();

ctx.moveTo(moveOffset, moveOffset);

ctx.lineTo(moveOffset+length, moveOffset);

var triHeight = length/2 * Math.tan(degToRad(60));

ctx.lineTo(moveOffset+(length/2), moveOffset+triHeight);

ctx.lineTo(moveOffset, moveOffset);

ctx.fill();

length--;

moveOffset += 0.7;

ctx.rotate(degToRad(5));

}

translate(),可用于移动画布的原点,将 canvas 按原始 x点的水平方向、原始的 y点垂直方向进行平移变换。

在每次迭代中:设置 fillStyle 为略透明的紫色渐变色。渐变由每次迭代时 length 值的改变实现。随着循环的运行, length 值逐渐变小,从而使连续的三角形颜色逐渐变亮。

开始路径。

将钢笔移动至坐标 (moveOffset, moveOffset);该变量定义了每次要绘制新三角形时需要移动的距离。

画一条直线,终点坐标为 (moveOffset+length, moveOffset)。即一条长度为 length 与 X 轴平行的线。

计算三角形的高,方法同上。

向三角形底部顶点方向绘制一条直线,然后向三角形的起始点绘制一条直线。

调用 fill() 为三角形填充颜色。

更新次序变量,准备绘制下一个三角形。length 的值减一,使三角形每次迭代都变小一些;小幅增加 moveOffset 的值,使得下一个三角形略微错位;用一个新函数 rotate() 来旋转整块画布,在绘制下个三角形前画布旋转 5°。

以上内容部分摘自视频课程04网页游戏编程JavaScript-22绘制图形,更多示例请参见网站示例。跟着张员外讲编程,学习更轻松,不花钱还能学习真本领。

相关文章

「Java」绘图入门和机制,绘图方法演示(绘制坦克)

目录1.绘图入门(绘制一个圆)1.第一步//1.先定义一个Mypanel,继承JPanel,画图行就在面板上画。//Mypanel可以理解为一个画板//Graphics可以理解为一个画笔,提供了很多绘...

java Graphics2D 画图

在Java中,当需要画一些特殊的形状时,比如说椭圆、矩形等,可以使用 Graphics2D 来绘图。一些API:g.drawLine(3,3,50,50);//画一条线段 g.drawRect(80...

有趣的EXCEL&amp;vba作图

还记不记得之前有个日本老爷爷用EXCEL绘图,美轮美奂,可谓是心思巧妙。我是没有那样的艺术细胞,不过咱有自己的方式,用代码作图通过vba代码将指定的图片写入excel工作表中,可不是插入图片哦解题思...

还能这么玩?用VsCode画类图、流程图、时序图、...不要太爽

软件设计中,有好几种图需要画,比如流程图、类图、组件图等,我知道大部分人画流程图一般都会用微软的viso绘制,我之前也是这个习惯。viso画图有个不好的地方是需要时刻去调整线条和边框已达到简洁美观,今...

Python绘图Turtle库详解

Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x、纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行...