JavaScript第十五章 使用 Canvas 绘图

1 基本用法

要使用<canvas>元素,必须先设置其 width 和 height 属性,指定可以绘图的区域大小。出现在 开始和结束标签中的内容是后备信息,如果浏览器不支持<canvas>元素,就会显示这些信息。下面就 是<canvas>元素的例子。

<canvas id="drawing" width=" 200" height="200">A drawing of something.</canvas>

与其他元素一样,<canvas>元素对应的 DOM元素对象也有 width 和 height 属性,可以随意修 改。而且,也能通过 CSS为该元素添加样式,如果不添加任何样式或者不绘制任何图形,在页面中是看 不到该元素的。

要在这块画布(canvas)上绘图,需要取得绘图上下文。而取得绘图上下文对象的引用,需要调用 getContext()方法并传入上下文的名字。传入"2d",就可以取得 2D上下文对象。

在使用<canvas>元素之前,首先要检测 getContext()方法是否存在,这一步非常重要。有些浏 览器会为 HTML规范之外的元素创建默认的 HTML元素对象。在这种情况下,即使 drawing 变量中 保存着一个有效的元素引用,也检测不到 getContext()方法。

使用 toDataURL()方法,可以导出在<canvas>元素上绘制的图像。这个方法接受一个参数,即图 像的 MIME类型格式,而且适合用于创建图像的任何上下文。

2 2D上下文

使用 2D绘图上下文提供的方法,可以绘制简单的 2D图形,比如矩形、弧线和路径。2D上下文的 坐标开始于<canvas>元素的左上角,原点坐标是(0,0)。所有坐标值都基于这个原点计算,x值越大表示 越靠右,y值越大表示越靠下。默认情况下,width 和 height 表示水平和垂直两个方向上可用的像素 数目

2.1 填充和描边

2D 上下文的两种基本绘图操作是填充和描边。填充,就是用指定的样式(颜色、渐变或图像)填 充图形;描边,就是只在图形的边缘画线。大多数 2D上下文操作都会细分为填充和描边两个操作,而操作的结果取决于两个属性:fillStyle 和 strokeStyle。

这两个属性的值可以是字符串、渐变对象或模式对象,而且它们的默认值都是"#000000"。如果为 它们指定表示颜色的字符串值,可以使用 CSS 中指定颜色值的任何格式,包括颜色名、十六进制码、 rgb、rgba、hsl 或 hsla

2.2 绘制矩形

矩形是唯一一种可以直接在 2D 上下文中绘制的形状。与矩形有关的方法包括 fillRect()、 strokeRect()和 clearRect()。这三个方法都能接收 4个参数:矩形的 x坐标、矩形的 y坐标、矩形 宽度和矩形高度。这些参数的单位都是像素。

2.3 绘制路径

2D 绘制上下文支持很多在画布上绘制路径的方法。通过路径可以创造出复 杂的形状和线条。要绘制路径,首先必须调用 beginPath()方法,表示要开始 绘制新路径。然后,再通过调用下列方法来实际地绘制路径。

  • arc(x, y, radius, startAngle, endAngle, counterclockwise):以(x,y)为圆心绘 制一条弧线,弧线半径为 radius,起始和结束角度(用弧度表示)分别为 startAngle 和 endAngle。后一个参数表示 startAngle 和 endAngle 是否按逆时针方向计算,值为 false 表示按顺时针方向计算。
  • arcTo(x1, y1, x2, y2, radius):从上一点开始绘制一条弧线,到(x2,y2)为止,并且以 给定的半径 radius 穿过(x1,y1)。
  • bezierCurveTo(c1x, c1y, c2x, c2y, x, y):从上一点开始绘制一条曲线,到(x,y)为 止,并且以(c1x,c1y)和(c2x,c2y)为控制点。
  • lineTo(x, y):从上一点开始绘制一条直线,到(x,y)为止。
  • moveTo(x, y):将绘图游标移动到(x,y),不画线。
  • quadraticCurveTo(cx, cy, x, y):从上一点开始绘制一条二次曲线,到(x,y)为止,并 且以(cx,cy)作为控制点。
  • rect(x, y, width, height):从点(x,y)开始绘制一个矩形,宽度和高度分别由 width 和 height 指定。这个方法绘制的是矩形路径,而不是 strokeRect()和 fillRect()所绘制的独 立的形状。

创建了路径后,接下来有几种可能的选择。如果想绘制一条连接到路径起点的线条,可以调用 closePath()。如果路径已经完成,你想用 fillStyle 填充它,可以调用 fill()方法。另外,还可 以调用 stroke()方法对路径描边,描边使用的是 strokeStyle。后还可以调用 clip(),这个方法 可以在路径上创建一个剪切区域。

2.4 绘制文本

文本与图形总是如影随形。为此,2D 绘图上下文也提供了绘制文本的方法。绘制文本主要有两个 方法:fillText()和 strokeText()。这两个方法都可以接收 4 个参数:要绘制的文本字符串、x 坐 标、y坐标和可选的大像素宽度。而且,这两个方法都以下列 3个属性为基础。

  • font:表示文本样式、大小及字体,用 CSS中指定字体的格式来指定,例如"10px Arial"。
  • textAlign:表示文本对齐方式。可能的值有"start"、"end"、"left"、"right"和"center"。 建议使用"start"和"end",不要使用"left"和"right",因为前两者的意思更稳妥,能同时 适合从左到右和从右到左显示(阅读)的语言。
  • textBaseline:表示文本的基线。可能的值有"top"、"hanging"、"middle"、"alphabetic"、 "ideographic"和"bottom"。

这几个属性都有默认值,因此没有必要每次使用它们都重新设置一遍值。fillText()方法使用 fillStyle 属性绘制文本,而 strokeText()方法使用 strokeStyle 属性为文本描边。相对来说,还 是使用 fillText()的时候更多,因为该方法模仿了在网页中正常显示文本

2.5 变换

通过上下文的变换,可以把处理后的图像绘制到画布上。2D绘制上下文支持各种基本的绘制变换。 创建绘制上下文时,会以默认值初始化变换矩阵,在默认的变换矩阵下,所有处理都按描述直接绘制。 为绘制上下文应用变换,会导致使用不同的变换矩阵应用处理,从而产生不同的结果。 可以通过如下方法来修改变换矩阵。

  • rotate(angle):围绕原点旋转图像 angle 弧度。
  • scale(scaleX, scaleY):缩放图像,在 x方向乘以 scaleX,在 y方向乘以 scaleY。scaleX 和 scaleY 的默认值都是 1.0。
  • translate(x, y):将坐标原点移动到(x,y)。执行这个变换之后,坐标(0,0)会变成之前由(x,y) 表示的点。
  • transform(m1_1, m1_2, m2_1, m2_2, dx, dy):直接修改变换矩阵
  • setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):将变换矩阵重置为默认状态,然后 再调用 transform()

2.6 绘制图像

2D绘图上下文内置了对图像的支持。如果你想把一幅图像绘制到画布上,可以使用 drawImage() 方法。根据期望的终结果不同,调用这个方法时,可以使用三种不同的参数组合。简单的调用方式 是传入一个 HTML <img>元素,以及绘制该图像的起点的 x和 y坐标。

2.7 阴影

2D上下文会根据以下几个属性的值,自动为形状或路径绘制出阴影。

  • shadowColor:用 CSS颜色格式表示的阴影颜色,默认为黑色。
  • shadowOffsetX:形状或路径 x轴方向的阴影偏移量,默认为 0。
  • shadowOffsetY:形状或路径 y轴方向的阴影偏移量,默认为 0。
  • shadowBlur:模糊的像素数,默认 0,即不模糊

2.8 渐变

渐变由 CanvasGradient 实例表示,很容易通过 2D上下文来创建和修改。要创建一个新的线性渐 变,可以调用 createLinearGradient()方法。这个方法接收 4个参数:起点的 x坐标、起点的 y坐 标、终点的 x 坐标、终点的 y 坐标。调用这个方法后,它就会创建一个指定大小的渐变,并返回 CanvasGradient 对象的实例。

创建了渐变对象后,下一步就是使用 addColorStop()方法来指定色标。这个方法接收两个参数: 色标位置和 CSS颜色值。色标位置是一个 0(开始的颜色)到 1(结束的颜色)之间的数字。

2.9 模式

模式其实就是重复的图像,可以用来填充或描边图形。要创建一个新模式,可以调用 createPattern()方法并传入两个参数:一个 HTML <img>元素和一个表示如何重复图像的字符串。 其中,第二个参数的值与 CSS的 background-repeat 属性值相同,包括"repeat"、"repeat-x"、 "repeat-y"和"no-repeat"

2.10 使用图像数据

2D上下文的一个明显的长处就是,可以通过 getImageData()取得原始图像数据。这个方法接收 4个参数:要取得其数据的画面区域的 x和 y坐标以及该区域的像素宽度和高度。

2.11 合成

还有两个会应用到 2D 上下文中所有绘制操作的属性:globalAlpha 和 globalComposition- Operation。其中,globalAlpha 是一个介于 0和 1之间的值(包括 0和 1),用于指定所有绘制的透 明度。默认值为 0。如果所有后续操作都要基于相同的透明度,就可以先把 globalAlpha 设置为适当 值,然后绘制,后再把它设置回默认值 0。

第二个属性 globalCompositionOperation 表示后绘制的图形怎样与先绘制的图形结合。这个 属性的值是字符串,可能的值如下

  • source-over(默认值):后绘制的图形位于先绘制的图形上方。
  • source-in:后绘制的图形与先绘制的图形重叠的部分可见,两者其他部分完全透明。
  • source-out:后绘制的图形与先绘制的图形不重叠的部分可见,先绘制的图形完全透明。
  • source-atop:后绘制的图形与先绘制的图形重叠的部分可见,先绘制图形不受影响。
  • destination-over:后绘制的图形位于先绘制的图形下方,只有之前透明像素下的部分才可见。
  • destination-in:后绘制的图形位于先绘制的图形下方,两者不重叠的部分完全透明。
  • destination-out:后绘制的图形擦除与先绘制的图形重叠的部分。
  • destination-atop:后绘制的图形位于先绘制的图形下方,在两者不重叠的地方,先绘制的图形会变透明。
  • ighter:后绘制的图形与先绘制的图形重叠部分的值相加,使该部分变亮。
  • copy:后绘制的图形完全替代与之重叠的先绘制图形。
  • xor:后绘制的图形与先绘制的图形重叠的部分执行“异或”操作。

3 WebGL

WebGL是针对 Canvas的 3D上下文。与其他 Web 技术不同,WebGL并不是 W3C制定的标准,而 是由 Khronos Group制定的。其官方网站是这样介绍的:“Khronos Group是一个非盈利的由会员资助的 协会,专注于为并行计算以及各种平台和设备上的图形及动态媒体制定无版税的开放标准。 ” Khronos Group也设计了其他图形处理 API,比如 OpenGL ES 2.0。浏览器中使用的 WebGL就是基于 OpenGL ES 2.0制定的。 OpenGL等 3D图形语言是非常复杂的,本书不可能介绍其中每一个概念。熟悉 OpenGL ES 2.0的读 者可能会觉得 WebGL更好理解一些,因为好多概念是相通的。

3.1 类型化数组

WebGL涉及的复杂计算需要提前知道数值的精度,而标准的 JavaScript数值无法满足需要。为此,WebGL引入了一个概念,叫类型化数组(typed arrays)。类型化数组也是数组,只不过其元素被设置为 特定类型的值。 类型化数组的核心就是一个名为 ArrayBuffer 的类型。每个 ArrayBuffer 对象表示的只是内存 中指定的字节数,但不会指定这些字节用于保存什么类型的数据。通过 ArrayBuffer 所能做的,就是 为了将来使用而分配一定数量的字节。

3.2 WebGL上下文

目前,在支持的浏览器中,WebGL 的名字叫"experimental-webgl",这是因为 WebGL 规范仍 然未制定完成。制定完成后,这个上下文的名字就会变成简单的"webgl"。如果浏览器不支持 WebGL, 那么取得该上下文时会返回 null。在使用 WebGL上下文时,务必先检测一下返回值。

通过给 getContext()传递第二个参数,可以为 WebGL上下文设置一些选项。这个参数本身是一 个对象,可以包含下列属性。

  • alpha:值为 true,表示为上下文创建一个 Alpha通道缓冲区;默认值为 true。
  • depth:值为 true,表示可以使用 16位深缓冲区;默认值为 true。
  • stencil:值为 true,表示可以使用 8位模板缓冲区;默认值为 false。
  • antialias:值为 true,表示将使用默认机制执行抗锯齿操作;默认值为 true。
  • premultipliedAlpha:值为 true,表示绘图缓冲区有预乘 Alpha值;默认值为 true。
  • preserveDrawingBuffer:值为 true,表示在绘图完成后保留绘图缓冲区;默认值为 false。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容