文档章节

HTML5 Canvas初体验之绘图基础

 恐空控
发布于 2013/08/04 19:33
字数 4993
阅读 521
收藏 8
相信到目前你应该已经对Canvas这一神奇的HTML5新元素有了一定的了解。在本文中,我们将深入了解画布的功能及特点,学习如何在HTML中利用Canvas绘制图形以及其它类型对象。

【E800编译】相信到目前你应该已经对Canvas这一神奇的HTML5新元素有了一定的了解。在本文中,我们将深入了解画布的功能及特点,学习如何在HTML中利用Canvas绘制图形以及其它类型对象。理解如何改变图形形状和对象是如何绘制在画布上,以及如何将其擦除。最后,实例演示如何建立与浏览器窗口的大小相同的画布,以及一些开发游戏必不可缺的技巧等等。

熟悉canvas元素

如同视频和音频元素,canvas元素绝对没有使用外部插件。你唯一需要的只是2D渲染上下文API,即使你不了解2D渲染上下文API也不用担心。

使用canvas元素很简单,我们从下面的代码开始:

<canvaswidth="500" height="500">

<!--Insert fallback content here -->

</canvas>

它的作用是创建一个新的空白画布元素,目前还不能够看到什么,因为你没有做任何2D渲染上下文。

创建canvas元素时要特别注意宽度和高度属性,显然这些属性定义canvas元素的大小,进而定义了2D渲染上下文的大小。在没有定义的情况下,将被设置默认的宽度和高度分别为300150。稍后在本章,我们将着眼于创建一个动态改变大小并填满整个浏览器窗口的画布。

注:canvas元素的位置在你的HTML文档中定义。与其他HTML元素一样,它可以按CSS所需到处移动。

浏览器支持

目前大多数浏览器都支持canvas元素和其大部分功能,但对于Internet Explorer,至少任何早于Internet Explorer 9的版本无法提供支持。一种方式是提醒旧版IE用户升级,另一种选择是使用谷歌开发的一些ExplorerCanvas脚本。这种方法的优点是,你只需要在页面中潜入一个脚本,那么canvas元素在旧版IE中也能正常显示。

ExplorerCanvas脚本可在ExplorerCanvaswebsite下载,并按照说明安装。

2D渲染上下文

canvas元素的目的是充当2D渲染上下文的封装,为您提供所有必要的方法调用以及绘制和操作的功能点。以下这一点非常重要:绘图是在2D渲染上下文中进行,而不是在canvas元素中。你可以通过canvas元素访问并显示2D渲染上下文。

坐标系统

2D渲染上下文是一标准的基于屏幕的绘图平台。与其他2D平台同样,使用同一个平面直角坐标系左上角的原点(0,0)。向右移动会增加x的值,向下移动则增加y值。所以绘图前必须要先了解坐标系统是如何工作的。

2D渲染上下文中直角坐标系

通常一个坐标系统中的单个单元相当于在屏幕上的1个像素,所以位置(2430)位于向右24像素,向下30像素。也有一些场合坐标系统的单位可能等于2个像素,如高清显示器,不过一般的经验法则是:1坐标单位等于1个屏幕像素。

访问2D渲染系统

不用多说,下面让我们创建一个基本的带空白画布元素的HTML页:

<!DOCTYPE html>

<html>

       <head>

                <title>Learning thebasics of canvas</title>

               <metacharset="utf-8">

                <scripttype="text/javascript" src="http://ajax.googleapis.com

/ajax/libs/jquery/1/jquery.min.js"></script>

                <scripttype="text/javascript">

                       $(document).ready(function() {

                        });

                </script>

       </head>

       <body>

                <canvasid="myCanvas" width="500" height="500">

                        <!-- Insert fallbackcontent here -->

                </canvas>

       </body>

</html>

如果现在就运行它,将看不到任何东西。在真正开始绘图之前,我们先访问2D渲染上下文。将以下代码写入jQuery声明语句中:

var canvas = $("#myCanvas");

var context =canvas.get(0).getContext("2d");

我们在这里所要做的只是给canvas元素分配一个变量,然后通过调用getContext方法为2D渲染上下文分配另一个变量的。这里需要注意的是,我们使用了jQuery,我们需要调用get方法来获取canvas元素的DOM,这样我们就可以获取canvasgetContext方法。记住一点, get方法与画布本身无关。

现在我们就有了一个包含2D渲染上下文的变量,在声明上下文变量后添加以下代码:

context.fillRect(40, 40, 100, 100);

此时刷新页面,你会发现已经出现了一个黑色的正方形!

图形是黑色的,这是在画布上绘制时的默认颜色。在稍后章节中,我们会学习如何使用默认之外的颜色进行图形绘制。

绘制基本形状与线条

正如你所看到的,绘制一个正方形是非常简单的,它只需一行代码,fillRect()方法如下:

context.fillRect(40, 40, 100, 100);

你会发现所调用的方法为fillRect()而不是fillSquare()。而我们都知道正方形实际是具有相同长度的边的矩形。

创建一个矩形需要四个参数,前两个是矩形起点(左上角)的坐标值(XY),最后两个为矩形的宽度和高度。fillRect()方法可以形象化改写成如下形式:

context.fillRect(x, y, width, height);

为清晰起见,改变矩形的宽度值为200,保存该文件并刷新页面。

当然,这是一个矩形。在不同的位置绘制矩形只是改变起点的坐标(xy)。例如在(200300)该点处:

在不同位置绘制一个矩形

注意:如果你绘图时原点超出了canvas元素尺寸范围,它将不会出现在屏幕上,而只有原点或者图形的某些部分处于画布元素范围内时才是可见的。

fillRect()strokeRect()是对双胞胎,fillRect方法绘制一个矩形并填充一种颜色(本例以黑色为例),strokeRect方法绘制一个矩形并描边,也就是说矩形的轮廓有线条描边。当然你也可以在fillRect实例中改用strokeRect方法。

绘制一个描边的矩形

现在出现的是一个中空的矩形轮廓。

直线

直线与以上形状略有不同,他们实际上为路径。创建一个简单的路径,你必须首先在2D渲染上下文中调用beginPath方法,接着调用moveTo方法,设置我们即将绘制路径的起点坐标(XY)。最后调用closePath开始路径绘制,其参数(XY)指定了路径终点。示例代码如下:

context.beginPath(); // Start the path

context.moveTo(40, 40); // Set the pathorigin

context.lineTo(340, 40); // Set the pathdestination

context.closePath(); // Close the path

context.stroke(); // Outline the path

路径效果如图:

通过改变lineTo方法的参数(XY)可以实现直线的倾斜:

context.lineTo(340, 340);

在画布上创建一个圈的方式远区别于创建一个矩形。圆是一个相当复杂的形状,甚至在Canvas中没有单独的方法调用来绘制。不过Canvas中提供了绘制圆弧的方法,而我们所要做的就是将弧的两端拼接。下面我们来看看如何在Canvas中绘制一个圆:

context.beginPath(); // Start the path

context.arc(230, 90, 50, 0, Math.PI*2,false); // Draw a circle

context.closePath(); // Close the path

context.fill(); // Fill the path

第一个与最后两行分别是开启和关闭路径(弧)并填充。

其中共有六个参数,(XY)指定了圆弧原点的坐标(本例中圆的圆心),弧的半径,起始角度,终止角度以及一个布尔值(布尔值为true则逆时针绘制圆弧,反之顺时针)。Arc()方法中具体参数如下:

context.arc(x, y, radius, startAngle,endAngle, anticlockwise);

圆的绘制图示如下:

这里需要注意的是,角度的单位都为弧度,360度(一个完整的圆)为2π(圆周率乘以2)弧度。可以利用下面的公式完成弧度转换:

var degrees = 1; // 1 degree

var radians = degrees * (Math.PI / 180); //0.0175 radians

度和弧度之间的转换

注意:在JavaScript中可以通过调用数学函数Math对象获取PI值,除此之外数学函数的作用也十分广泛,如我们后面即将提到的随机数生成。

运最后行这个实例,实际效果如下:

如果只是绘制一个半圆,很简单,只需将角度改为π,代码如下:

context.arc(230, 90, 50, 0, Math.PI,false); // Draw a semi-circle

如果一切顺利,应该有一个可爱的半圈,在您的浏览器。

Arc()中的第六个参数是可选的,不过在Firefox浏览器下,如果它被省略了则会抛出一个错误,所以在绘图时最好保留以明确定义绘制的方向。

样式

下面我们看看在本章开头提及的定义图形颜色的问题:

context.fillStyle = "rgb(255, 0,0)";

context.fillRect(40, 40, 100, 100);

通过设置2D渲染上下文中的FillStyle属性,能够实现改变图形和路径的填充色。在前面的实例中,分配了一个RGB(红,绿,蓝)颜色值,当然你也可以使用任何有效的十六进制代码形式的CSS颜色值(如#FF0000或“red”)。在本例中颜色设置为全红(红色,没有绿色与蓝色),实际效果将会如下:

这样会有一个缺点,问题在于设置了FillStyle属性后就意味着你之后的一切图形绘制都会按该颜色方案执行。当你只是想改变其中一个对象的颜色,需在完成绘制后将FillStyle属性设置为黑色(或另外某颜色),如下列代码所示:

context.fillStyle = "rgb(255, 0,0)";

context.fillRect(40, 40, 100, 100); // Redsquare

context.fillRect(180, 40, 100, 100); // Redsquare

context.fillStyle = "rgb(0, 0,0)";

context.fillRect(320, 40, 100, 100); //Black square

在浏览器中的效果为:

同样你也可以通过使用strokeStyle属性勾勒图形和路径,例如,下面用stroke代替本例中的fill

context.strokeStyle = "rgb(255, 0,0)";

context.strokeRect(40, 40, 100, 100); //Red square

context.strokeRect(180, 40, 100, 100); //Red square

context.strokeStyle = "rgb(0, 0,0)";

context.strokeRect(320, 40, 100, 100); //Black square

注:当然也可以同时使用fillStylestrokeStyle属性,就绘制出填充与轮廓颜色截然不同的图形。

context.strokeStyle = "rgb(255, 0,0)";

context.beginPath();

context.moveTo(40, 180);

context.lineTo(420, 180); // Red line

context.closePath();

context.stroke();

context.strokeStyle = "rgb(0, 0,0)";

context.beginPath();

context.moveTo(40, 220);

context.lineTo(420, 220); // Black line

context.closePath();

context.stroke();

调整线宽

想要在画布上改变线宽,就要用到2D渲染上下文中的lineWidth属性。lineWidth属性默认值为1,你可以将它设置为所需的任意值。例如,我们改变红色与黑色线条的宽度:

context.lineWidth = 5; // Make lines thick

context.strokeStyle = "rgb(255, 0,0)";

context.beginPath();

context.moveTo(40, 180);

context.lineTo(420, 180); // Red line

context.closePath();

context.stroke();

context.lineWidth = 20; // Make lines eventhicker

context.strokeStyle = "rgb(0, 0,0)";

context.beginPath();

context.moveTo(40, 220);

context.lineTo(420, 220); // Black line

context.closePath();

context.stroke();

运行结果显示为稍厚的红线与过厚的黑线:

lineWidth属性在图形上同样适用:

context.lineWidth = 5; // Make lines thick

context.strokeStyle = "rgb(255, 0,0)";

context.strokeRect(40, 40, 100, 100); //Red square

context.strokeRect(180, 40, 100, 100); //Red square

context.lineWidth = 20; // Make lines eventhicker

context.strokeStyle = "rgb(0, 0,0)";

context.strokeRect(320, 40, 100, 100); //Black square

绘制文本

Canvas不仅仅是用来绘制图形和图像,也可以用它来显示文本。尽管在很多情况下这并不是一个较好的选择,尤其是相比使用更为传统的HTML元素(如AP元素)而言。

画布上的文字是作为一个图像绘制出来,准确来讲它并不是文字,也就意味着它无法像普通HTML文档中的文本那样被光标选中。如果你之前使用Microsoft画图,那么你就会明白:一旦文本已经绘制,就不能再次编辑,除非删除重绘。在画布上绘制文本的好处是,你可以使用各种精彩功能在画布上绘制。这里需要强调的是,不应在画布上创建文本,你应该使用正常的HTML元素创建文本,然后通过CSS定位到画布的顶层。这里的关键区别在于,HTML处理文本(内容),而Canvas直接针对像素和图形的处理。

以下代码演示了如何绘制文本:

var text = "Hello, World!";

context.fillText(text, 40, 40);

2D渲染上下文中fillText方法共有四个参数(一个可选,我们暂时忽略);首先是要绘制的文本字符串,第二和第三参数是文本原点(左下角)的坐标值(XY)。

这里没有演示实例效果,因为它太小以致于很难看到,这是因为画布上的文本字体的默认设置为10px sans-serif(绝对微小)。可按下列代码所示更改字体属性:

var text = "Hello, World!";

context.font = "30px serif"; //Change the size and font

context.fillText(text, 40, 40);

CSS中的字体属性类似,字体属性为一个字符串值。在前面的例子中,给出的字体属性是像素尺寸,以及所要使用的字体名称。实例中已将它设置为serif,效果如下:

如果需要你甚至可以设置为斜体:

var text = "Hello, World!";

context.font = "italic 30pxserif";

context.fillText(text, 40, 40);

在这里唯一要做的只是将italic添入字体属性字符串中。除此之外还可以作很多设置,诸如行的高度以及其它备用字体等等,这里就不一一描述。

注:不难发现画布的基础功能使用极其简单方便,因为2D渲染上下文API中使用的方法与属性都是以易于理解的方式命名,这些都能够轻松掌握。

进行下一步之前,我们先来了解下如何勾勒文本,这是非常有用的:

var text = "Hello, World!";

context.font = "italic 60pxserif";

context.strokeText(text, 40, 100);

其中调用的strokeText()方法的参数与fillText()完全相同,为了能更清晰的显示,调整了上例中字体的大小及位置:

画布擦除

当你在绘图过程中出了错或要擦拭重绘时,可以有两种选择:调用clearRect()方法,或者宽度/高度技巧。我们首先看看2D渲染上下文中clearRect()方法。

例如刚刚在画布上绘制一个正方形和一个圆:

context.fillRect(40, 40, 100, 100);

context.beginPath();

context.arc(230, 90, 50, 0, Math.PI*2,false);

context.closePath();

context.fill();

现在需要做的就是调用clearRect()方法,指定擦除区域的原点坐标(X,Y),以及其宽度和高度。如果画布500像素宽,500像素高,那么调用方式可以如下:

context.clearRect(0, 0, 500, 500);

此时再运行,将显示为空白。当不清楚画布的大小时,还可以调用clearRect(),参数可以由jQuery宽度与高度的方法获取:

context.clearRect(0, 0, canvas.width(),canvas.height());

完整代码如下:

var canvas = $("#myCanvas");

var context = canvas.get(0).getContext("2d");

context.fillRect(40, 40, 100, 100);

context.beginPath();

context.arc(230, 90, 50, 0, Math.PI*2,false);

context.closePath();

context.fill();

context.clearRect(0, 0, canvas.width(),canvas.height());

注:canvas元素实际上提供了宽度和高度属性,所以选择哪种方式完全取决于你,使用jQuery方式,或纯JavaScript方式获取画布的尺寸。

其实可以不必清除整个画布,完全可以很容易地清除某一特定区域。例如,在本例中仅删除正方形,就可按下列方式调用clearRect()

context.clearRect(40, 40, 100, 100);

这样就可以单独留下一个圆。

这种方式可以指定clearRect()中的参数以清除一个特定的区域。在本例中,我们将擦除区域的起点(左上角)设定在正方形的左上角(40,40),并将擦除区域的宽度与高度设置为正方形的宽高度(100)。其结果是只有正方形被清除。同样你也可以通过改变clearRect()参数将圆形擦除:

context.clearRect(180, 40, 100, 100);

这样保留下来的就会只是一个正方形。

需注意的是,一个弧形的圆心是它的中心,所以要得到clearRect方法正确的起点,我们需要首先获取弧的圆心,且XY的值需分别减去半径。

context.fillRect(40, 40, 100, 100);

context.beginPath();

context.arc(230, 90, 50, 0, Math.PI*2,false);

context.closePath();

context.fill();

context.clearRect(230, 90, 50, 50);

以上代码会截去圆形的一部分:

有时这种方式可以用于快速方便地绘制复杂图形,先绘制出基本形状再加以裁剪。

宽度/高度技巧

如果你想擦除画布上的一切从头开始,那么可以考虑宽度/高度的技巧。这可以用来重置画布至默认设置并刷新状态。这种方法确实有一些缺点,先举个例子:

context.fillStyle = "rgb(255, 0,0)";

context.fillRect(40, 40, 100, 100);

context.beginPath();

context.arc(230, 90, 50, 0, Math.PI*2,false);

context.closePath();

context.fill();

先在画布上绘制一个红色的正方形和圆形,然后添加画布复位:

canvas.attr("width",canvas.width());

canvas.attr("height",canvas.height());

这只是一个jQuery技巧应用,您需要改变的是canvas元素的宽度与高度属性,并且可以通过jQueryattr()方法做到这一点。我们需传递参数名(宽度和高度),以及所要设置的参数值(与之前的的宽度和高度相同)。正常情况下你会看到一个空白的画布。

添加以下代码行:

context.fillRect(40, 40, 100, 100);

宽度/高度技巧的缺点是,在画布上所有一切都会复位,包括样式和颜色等。

Canvas填充浏览器窗口

到目前为止canvas元素一直在500像素这一固定的宽度和高度上,但那么如何才能让它填满整个浏览器窗口呢?对于一个普通的HTML元素来说,你只需正常将其宽度和高度属性设置为100%即可。不过画布元素并不支持该方法,这里我们来看另一种方式。

最简单的方式做就是将canvas元素的宽度和高度精确设置为浏览器窗口的宽度和高度。我们可以通过window浏览器对象和jQuery技巧获取宽度和高度:

var canvas = $("#myCanvas");

var context = canvas.get(0).getContext("2d");

canvas.attr("width",$(window).get(0).innerWidth);

canvas.attr("height",$(window).get(0).innerHeight);

context.fillRect(0, 0, canvas.width(),canvas.height());

使用$(window).get(0).innerHeight代替$(window).height()是因为后者无法返回所有浏览器窗口的完整高度值。这种方法实际效果并不完美,浏览器窗口中canvas元素和滚动条的四周仍存在白色区域:

为了解决这个问题,我们需要用到CSS。在文本编辑器中创建一个canvas.css,并保存在HTML文档的同一目录下,将下列代码加入CSS文件中并保存:

* { margin: 0; padding: 0; }

html, body { height: 100%; width: 100%; }

canvas { display: block; }

要使用HTML文档中这一CSS,需要添加以下代码行至jQuery script元素前的head元素内:

<link href="canvas.css"rel="stylesheet" type="text/css">

其效果是canvas元素完美地填充了整个浏览器窗口。

当然,这并没有结束。你会发现不管怎么调整浏览器窗口大小,画布都会保持着之前的尺寸:

这就需要在浏览器窗口大小改变的同时来调整画板的大小。

$(window).resize(resizeCanvas);

function resizeCanvas() {

       canvas.attr("width", $(window).get(0).innerWidth);

       canvas.attr("height", $(window).get(0).innerHeight);

       context.fillRect(0, 0, canvas.width(), canvas.height());

};

resizeCanvas();

此时你会发现画布实现完美调整,并且不会出现滚动条。

总结

本章中涵盖了各种有趣的东西,特别是在你从未使用过的Canvas之前。现在你已经学会如何使用canvas元素进行基本形状和路径的绘制,改变图形和路径的颜色,以及如何绘制文本,擦除画布,如何使画布填充浏览器窗口等等。

本文转载自:http://www.e800.com.cn/articles/2012/0315/504978.shtml

共有 人打赏支持
粉丝 10
博文 22
码字总数 7160
作品 0
成都
Web开发中的矢量绘图(vml,svg)处理和应用

前言 1991 年物理学家 Tim Berners-Lee 首次在因特网上发布了 HTML 的第一版描述规范文档。经过了 20 多年的发展,HTML 语言成为如今编程最为广泛的语言和互联网上采用最广的文档格式。虽然 ...

kevin_pang
2014/02/25
0
0
精选9个值得学习的 HTML5 效果【附源码】

这里精选了一组很酷的 HTML5 效果。HTML5 是现 Web 开发领域的热点, 拥有很多让人期待已久的新特性,特别是在移动端,Web 开发人员可以借助 HTML5 强大功能轻松制作各种交互性强、效果丰富的...

赵小宾
2014/11/27
0
0
HTML5视频教程之canvas合成海报所遇问题及解决方案

本篇文章扣丁学堂HTML5培训小编大家分享HTML5开发方面的问题:canvas合成海报所遇问题及解决方案,HTML5不论是现在还是今后的发展相信很多人都是很看好的,下面和小编一起来了解一下HTML5开发...

扣丁学堂
08/29
0
0
使用 HTML5 canvas 绘制的图形

HTML5 是一个新兴标准,它正在以越来越快的速度替代久经考验的 HTML4。HTML5 是一个 W3C “工作草案” — 意味着它仍然处于开发阶段 — 它包含丰富的元素和属性,它们都支持现行的 HTML 4.0...

coko
2013/08/15
0
0
2011年国外十大最佳HTML5网站

面向全球电子商务知识库网站eBizMBA挑选出2011年国外十大最佳HTML5网站,这些网站都是经过eBizMBA网站编辑根据视觉艺术、声效、易用性和创新性等多方面考究评选出来的。 1 The Wilderness D...

国外网站大全
2012/04/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Dubbo分析之Transport层

前言 上一篇文章Dubbo分析之Serialize层,介绍了最底层的序列化/反序列化层,本文继续分析Serialize层的上一层transport网络传输层,此层使用了现有的一些通讯开源框架(ex:netty,mina,grizzl...

ksfzhaohui
26分钟前
1
0
通告!Android 9 Pie未适配应用公示

8月7日,谷歌正式发布Android 9 Pie,至今已两月有余。近日,华为终端开放实验室对国内主流应用在Android 9 Pie的兼容性进行测试,结果显示:目前TOP3000应用兼容率已经超过95%,但仍有少量应...

安卓绿色联盟
28分钟前
1
0
Linux下多网卡绑定模式详解

在我们日常Linux使用中,一般对于生产网都会使用双网卡或多网卡接入,这样既能添加网络带宽,同时又能做相应的冗余,可谓好处多多。而一般我们都会使用Linux操作系统下自带的网卡绑定模式。这...

openthings
30分钟前
2
0
SylixOS中AARCH64跳转表实现原理

1. 跳转表存在的意义 1.1 内核模块反汇编 如下的程序清单,为一个内核模块的源码。 #define __SYLIXOS_KERNEL#include <SylixOS.h>#include <module.h> /* * SylixOS call module_i......

zhywxyy
31分钟前
2
0
聊一聊 Spring 中的线程安全性

本文摘自ImportNew公众号,摘录做学习资料,向大家推荐该公众号 Spring与线程安全 Spring作为一个IOC/DI容器,帮助我们管理了许许多多的“bean”。但其实,Spring并没有保证这些对象的线程安...

木子SMZ
32分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部