七、画布简介
在这一章中,我们将学习 HTML 画布。HTML 画布有助于您绘制,尤其是 HTML 页面上的图形(例如,圆形、正方形、矩形等)。<canvas></canvas>
标签通常由 JavaScript 控制。Canvas 可以绘制文本,也可以制作动画。让我们看看我们可以使用 HTML 画布做什么。
实现画布
要在您的 HTML 页面上添加画布,您需要在<canvas></canvas>
标签中定义画布的高度和宽度,如下所示:
<html>
<head>
<title>Canvas</title>
</head>
<body>
<canvas id="canvasTest" width="200" height="100" style="border:2px solid #000;">
</canvas>
</body>
</html>
我们已经将画布 ID 定义为canvasTest
,将用来玩画布。我们在画布上使用了内嵌 CSS。2 px 实心边框用于更好地查看画布。
添加 JavaScript
现在,我们将为我们的画布添加几行 JavaScript。我们需要在<script></script>
标签中的<canvas></canvas>
标签之后添加我们的 JavaScript。
画一个长方形
为了测试我们的画布,让我们通过输入下面的代码在画布中绘制一个矩形:
<script type="text/javascript">
var canvas = document.getElementById("canvasTest"); //called our canvas by id
var canvasElement = canvas.getContext("2d"); // made our canvas 2D
canvasElement.fillStyle = "black"; //Filled the canvas black
canvasElement.fillRect(10, 10, 50, 50); //created a rectangle
</script>
在脚本中,我们声明了两个 JavaScript 变量。canvas
变量用于使用画布标识保存画布的内容,我们在<canvas></canvas>
标签中使用了画布标识。canvasElement
变量用于保存画布的上下文。我们将black
指定给fillstyle
,这样我们想要绘制的矩形在填充后会变成黑色。我们使用canvasElement.fillRect(x, y, w, h);
作为矩形的形状。其中x
是矩形距离 x 轴的距离;y
是矩形距离 y 轴的距离;而w
和h
分别是矩形的宽度和高度。
完整的代码如下所示:
<html>
<head>
<title>Canvas</title>
</head>
<body>
<canvas id="canvasTest" width="200" height="100" style="border:2px solid #000;">
</canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvasTest"); //called our canvas by id
var canvasElement = canvas.getContext("2d"); // made our canvas 2D
canvasElement.fillStyle = "black"; //Filled the canvas black
canvasElement.fillRect(10, 10, 50, 50); //created a rectangle
</script>
</body>
</html>
代码的输出如下:
画线
要在画布上绘制一条线,您需要在您的<script></script>
标签中插入以下代码:
<script type="text/javascript">
var c = document.getElementById("canvasTest");
var canvasElement = c.getContext("2d");
canvasElement.moveTo(0,0);
canvasElement.lineTo(100,100);
canvasElement.stroke();
</script>
这里,canvasElement.moveTo(0,0);
用来让我们的线从画布的(0,0)坐标开始。canvasElement.lineTo(100,100);
语句用于使线对角化。canvasElement.stroke();
语句用于使线条可见。我建议您更改canvasElement.lineTo(100,100);
和canvasElement.moveTo(0,0);
中的数字,并查看画布上绘制的线条的变化。
下面是代码的输出:
快速锻炼
- 使用画布和 JavaScript 绘制一条线,该线将平行于画布的 y 轴。
- 画一个高 300 像素宽 200 像素的矩形。在同一画布上画一条线,接触矩形。
画一个圆
要在画布中绘制一个圆,需要在<script></script>
标签中添加以下代码:
<script type="text/javascript">
var c = document.getElementById("canvasTest");
var canvasElement = c.getContext("2d");
canvasElement.beginPath();
canvasElement.arc(95,50,40,0,2*Math.PI);
canvasElement.stroke();
</script>
这里我们用canvasElement.beginPath();
开始画圆,canvasElement.arc(95,50,40,0,2*Math.PI);
为圆的形状,canvasElement.stroke();
设置圆可见。
注
canvasElement.arc(95,50,40,0,2*Math.PI);
语句类似于canvasElement.arc(x, y, r, sA, eA, ac);
,
其中x
是从 x 轴开始的坐标,y
是从 y 轴开始的坐标,r
是圆的半径,sA
是圆的起始角,eA
是圆的结束角,ac
是圆的方向。这里,ac
表示逆时针。
我们的代码的输出将是如下图像:
绘制线性渐变
让我们画一些新的东西。我们将绘制一个矩形并使其颜色逐渐淡化。在您的<script></script>
标签中键入以下代码:
<script type="text/javascript">
var c = document.getElementById("canvasTest");
var canvasElement = c.getContext("2d");
// Create the gradient
var grdient = canvasElement.createLinearGradient(0,0,100,0);
grdient.addColorStop(0,"blue"); // here we added blue as our primary color
grdient.addColorStop(1,"white"); //here we used white as our secondary color.
// Fill with gradient
canvasElement.fillStyle = grdient;
canvasElement.fillRect(10,10,150,80);
</script>
我们添加了canvasElement.createLinearGradient(0,0,100,0);
来创建渐变或渐变。我们添加了grdient.addColorStop(0,"blue");
和grdient.addColorStop(1,"white");
来给矩形上色。
代码的输出如下图所示:
快速锻炼
-
Draw the following smiley face using HTML canvas. (Hint: you will have to draw three full circles and a half circle. The trick is that you can draw the figure by playing with the code of circle for the canvas.):
-
用颜色渐变画一个圆。
我们做个钟吧!
我们要画一个模拟时钟,让它像真正的时钟一样工作。在 HTML 文档的正文部分,键入以下代码:
<canvas id="myclock" height="500" width="500"></canvas>
In your <script></script> tags, take the following variables:
Var canvas; // the clock canvas
var canvasElement; // canvas's elements
// clock settings
var cX = 0;
var cY = 0;
var radius = 150;
这里,cX
和cY
是我们时钟的中心坐标。我们把 150 像素作为时钟的半径。您可以增加或减少它。
然后,我们需要初始化变量。在定义了前面的变量之后,创建一个init();
函数。
该函数应该类似于以下内容:
function init() {
canvas = document.getElementById("myclock");
//Called the element to work on.
canvasElement = canvas.getContext("2d");
//Made the context 2d.
cX = canvas.width / 2;
// we divided by two to get the middle point of X-axis
cY = canvas.height / 2;
// we divided by two to get the middle point of Y-axis
initTime(); //called the initTime() function.
drawClock(); //Called the drawClock() function to draw the graphics.
setInterval("animateClock()", 1000); // Made the animation for each second. Here 1000 is equal to 1 second.
}
让我们初始化时钟的秒针、分针和时针:
function initTime() {
date = new Date();
hours = date.getHours() % 12; // Divided by 12 to make our clock 12 hours.
minutes = date.getMinutes();
seconds = date.getSeconds();
}
这里,date.getHours()
、date.getMinutes()
、date.getSeconds()
会返回你电脑的时间,保存在我们的变量里。
让成为另一个激活我们的时钟的功能:
function animateClock() {
//This function will help our 'second' hand to move after an interval.
clearCanvas(); // This will clear the canvas
refreshTime(); // This will refresh time after 1 second.
drawClock(); // This will draw the clock.
}
我们现在写clearCanvas()
、refreshTime()
和drawClock()
:
function clearCanvas() {
canvasElement.clearRect(0, 0, canvas.width, canvas.height);
}
这里,canvasElement.clearRect(0, 0, canvas.width, canvas.height);
会在一定的时间间隔后重置我们的画布。
我们的refreshTime()
功能应该如下图所示:
function refreshTime() {
seconds += 1;
if (Math.floor((seconds / 60)) != 0) { //we divide seconds by 60 until second is equal to zero.
minutes += 1; // If 60 second is passed we increment minute by 1\.
seconds %= 60;
}
if (Math.floor((minutes / 60)) != 0) {
hours += 1; //We increment hour by 1 after 60 minutes.
minutes %= 60;
}
}
我们在refreshTime()
函数中增加了seconds
变量。因此,每当调用这个函数时,我们的变量将增加1
。然后,我们为我们的hours
和minutes
做了两个条件运算。
现在,让我们画出时钟:
function drawClock() {
drawClockBackground(); //This draws clock background.
drawSecondsHand(); //This draws clock's second hand.
drawMinutesHand(); //This draws clock's minute hand.
drawHoursHand(); //This draws clock's hour hand.
}
我们将编写drawClockBackground()
、drawSecondsHand()
、drawMinutesHand()
和drawHoursHand()
功能:
function drawClockBackground() {
//this function will draw the background of our clock. We are declaring few variables for mathematical purposes.
var correction = 1/300;
var shift_unit = 1/170;
var shift_factor = 1/30;
var angle_initial_position = 2;
var angle_current_position_begin = 0;
var angle_current_position_end = 0;
var repeat = 60;
var lineWidth = 10;
for (var i=0; i < repeat; i+=1) {
//These lines are written for making our clock error free with the angle of the hands (hands' positions)
angle_current_position_begin = angle_initial_position - (i * shift_factor) - correction;
angle_current_position_end = angle_current_position_begin + shift_unit;
if (i % 5 === 0)
lineWidth = 20;
else
lineWidth = 10;
drawArcAtPosition(cX, cY, radius, angle_current_position_begin*Math.PI, angle_current_position_end*Math.PI, false, lineWidth);
}
drawLittleCircle(cX, cY);
}
我们在这个函数中做了一些数学上的事情,并在我们的时钟中心写了一个小圆的drawLittleCircle(cX, cY)
函数。
该函数应该类似于以下内容:
function drawLittleCircle(cX, cY) {
drawArcAtPosition(cX, cY, 4, 0*Math.PI, 2*Math.PI, false, 4);
}
写drawSecondsHand()
功能。该函数将绘制秒针,如下所示:
function drawSecondsHand() {
/* Simple mathematics to find the co ordinate of the second hand;
You may know this: x = rcos(theta), y = rsin(theta). We used these here.
We divided the values n=by 30 because after 5 seconds the second hand moves 30 degree.
*/
endX = cX + radius*Math.sin(seconds*Math.PI / 30);
endY = cY - radius*Math.cos(seconds*Math.PI / 30);
drawHand(cX, cY, endX, endY);
}
我们的drawMinutesHand()
功能应该如下图所示。该功能将绘制我们时钟的分针,如下所示:
function drawMinutesHand() {
var rotationUnit = minutes + seconds / 60;
var rotationFactor = Math.PI / 30;
var rotation = rotationUnit*rotationFactor;
var handLength = 0.8*radius;
endX = cX + handLength*Math.sin(rotation);
endY = cY - handLength*Math.cos(rotation);
drawHand(cX, cY, endX, endY);
}
现在,让我们看看我们的drawHoursHand();
功能。该功能将绘制时针:
function drawHoursHand() {
var rotationUnit = 5 * hours + minutes / 12;
var rotationFactor = Math.PI / 30;
var rotation = rotationUnit*rotationFactor;
var handLength = 0.4*radius;
endX = cX + handLength*Math.sin(rotation);
endY = cY - handLength*Math.cos(rotation);
drawHand(cX, cY, endX, endY);
}
我们在前面的函数中使用了drawHand();
函数。让我们编写函数,如下所示:
function drawHand(beginX, beginY, endX, endY) {
canvasElement.beginPath();
canvasElement.moveTo(beginX, beginY);
canvasElement.lineTo(endX, endY);
canvasElement.stroke();
canvasElement.closePath();
}
现在,我们将为我们的时钟编写最后一个函数,如下面的代码片段所示:
function drawArcAtPosition(cX, cY, radius, start_angle, end_angle, counterclockwise, lineWidth) {
canvasElement.beginPath();
canvasElement.arc(cX, cY, radius, start_angle, end_angle, counterclockwise);
canvasElement.lineWidth = lineWidth;
canvasElement.strokeStyle = "black";
canvasElement.stroke();
canvasElement.closePath();
}
我们时钟的完整代码应该类似于下面的代码:
<html>
<head>
<script type="text/javascript">
var canvas;
var canvasElement;
// clock settings
var cX = 0;
var cY = 0;
var radius = 150;
// time settings
var date;
var hours;
var minutes;
var seconds;
function init() {
canvas = document.getElementById("myclock");
canvasElement = canvas.getContext("2d");
cX = canvas.width / 2;
cY = canvas.height / 2;
initTime();
drawClock();
setInterval("animateClock()", 1000);
}
// get your system time
function initTime() {
date = new Date();
hours = date.getHours() % 12;
minutes = date.getMinutes();
seconds = date.getSeconds();
}
// animate the clock
function animateClock() {
clearCanvas();
refreshTime();
drawClock();
}
// clear the canvas
function clearCanvas() {
canvasElement.clearRect(0, 0, canvas.width, canvas.height);
}
// refresh time after 1 second
function refreshTime() {
seconds += 1;
if (Math.floor((seconds / 60)) != 0) { minutes += 1; seconds %= 60; }
if (Math.floor((minutes / 60)) != 0) { hours += 1; minutes %= 60; }
}
// draw or redraw Clock after time refresh function is called
function drawClock() {
drawClockBackground();
drawSecondsHand();
drawMinutesHand();
drawHoursHand();
}
function drawHand(beginX, beginY, endX, endY) {
canvasElement.beginPath();
canvasElement.moveTo(beginX, beginY);
canvasElement.lineTo(endX, endY);
canvasElement.stroke();
canvasElement.closePath();
}
// draw Hand for seconds
function drawSecondsHand() {
endX = cX + radius*Math.sin(seconds*Math.PI / 30);
endY = cY - radius*Math.cos(seconds*Math.PI / 30);
drawHand(cX, cY, endX, endY);
}
// draw Hand for minutes
function drawMinutesHand() {
var rotationUnit = minutes + seconds / 60;
var rotationFactor = Math.PI / 30;
var rotation = rotationUnit*rotationFactor;
var handLength = 0.8*radius;
endX = cX + handLength*Math.sin(rotation);
endY = cY - handLength*Math.cos(rotation);
drawHand(cX, cY, endX, endY);
}
// draw Hand for hours
function drawHoursHand() {
var rotationUnit = 5 * hours + minutes / 12;
var rotationFactor = Math.PI / 30;
var rotation = rotationUnit*rotationFactor;
var handLength = 0.4*radius;
endX = cX + handLength*Math.sin(rotation);
endY = cY - handLength*Math.cos(rotation);
drawHand(cX, cY, endX, endY);
}
function drawClockBackground() {
var correction = 1/300;
var shift_unit = 1/170;
var shift_factor = 1/30;
var angle_initial_position = 2;
var angle_current_position_begin = 0;
var angle_current_position_end = 0;
var repeat = 60;
var lineWidth = 10;
for (var i=0; i < repeat; i+=1) {
angle_current_position_begin = angle_initial_position - (i * shift_factor) - correction;
angle_current_position_end = angle_current_position_begin + shift_unit;
if (i % 5 == 0) lineWidth = 20;
else lineWidth = 10;
drawArcAtPosition(cX, cY, radius, angle_current_position_begin*Math.PI, angle_current_position_end*Math.PI, false, lineWidth);
}
drawLittleCircle(cX, cY);
}
function drawArcAtPosition(cX, cY, radius, start_angle, end_angle, counterclockwise, lineWidth) {
canvasElement.beginPath();
canvasElement.arc(cX, cY, radius, start_angle, end_angle, counterclockwise);
canvasElement.lineWidth = lineWidth;
canvasElement.strokeStyle = "black";
canvasElement.stroke();
canvasElement.closePath();
}
function drawLittleCircle(cX, cY) {
drawArcAtPosition(cX, cY, 4, 0*Math.PI, 2*Math.PI, false, 4);
}
</script>
</head>
<body onload="init()">
<canvas id="myclock" height="500" width="500"></canvas>
</body>
</html>
如果你可以看到你的代码输出如下图,那么恭喜你!您使用画布成功创建了您的 HTML 时钟:
总结
在本章中,我们学习了 HTML 画布的基础知识。我希望您现在可以使用 HTML 画布绘制任何东西。你可能玩过网络游戏;其中大部分的组件都是使用 HTML 画布绘制的。因此,如果你想开发自己的网络应用或游戏,你需要学习画布。您可以使用 JavaScript 轻松地编写代码来绘制形状并制作动画。
在下一章中,我们将使用 HTML 画布开发一款名为鼠人的游戏。在开始第八章建造鼠人之前!,希望你通过这一章学到了很多关于 HTML 画布的知识。如果你有,让我们现在开发我们的游戏。
版权属于:月萌API www.moonapi.com,转载请注明出处