第15章 使用 Canvas 绘图
1. 基本用法
(1) 要使用<canvas>元素,必须先设置其
width
和height
属性,指定可以绘图的区域大小。出现在 开始和结束标签中的内容是后备信息,如果浏览器不支持<canvas>元素,就会显示这些信息。
<canvas id="drawing" width=" 200" height="200">A drawing of something.</canvas>
(2) <canvas>元素对应的 DOM 元素对象也有 width 和 height 属性,可以随意修 改。而且,也能通过 CSS 为该元素添加样式,如果不添加任何样式或者不绘制任何图形,在页面中是看 不到该元素的。
(3)
getContext()方法
:取得绘图上下文对象的引用,传入上下文的名字。传入"2d",就可以取得 2D 上下文对象。
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d");
//更多代码
}
(4)
toDataURL()方法
可以导出在<canvas>元素上绘制的图像。这个方法接受一个参数,即图 像的 MIME 类型格式,而且适合用于创建图像的任何上下文。
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
//取得图像的数据 URI
var imgURI = drawing.toDataURL("image/png");
//显示图像
var image = document.createElement("img");
image.src = imgURI; document.body.appendChild(image);
}
2. 2D 上下文
(1) 填充和描边
填充
,就是用指定的样式(颜色、渐变或图像)填
充图形。fillStyle 属性
描边
,就是只在图形的边缘画线。strokeStyle属性
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d");
context.strokeStyle = "red";
context.fillStyle = "#0000ff";
}
(2) 绘制矩形
与矩形有关的方法包括
fillRect()
、strokeRect()
和clearRect()
。这三个方法都能接收4 个参数
:矩形的 x 坐标
、矩形的 y 坐标
、矩形宽度
和矩形高度
。这些参数的单位都是像素。
*fillRect()方法
在画布上绘制的矩形会填充指定的颜色。填充的颜色通过 fillStyle 属性指定。
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d");
//绘制红色矩形
context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50);
//绘制半透明的蓝色矩形
context.fillStyle = "rgba(0,0,255,0.5)"; context.fillRect(30, 30, 50, 50);
}
* strokeRect()方法
在画布上绘制的矩形会使用指定的颜色描边。描边颜色通过 strokeStyle 属性指定。
描边线条的宽度由 lineWidth 属性控制,该属性的值可以是任意整数。另外, 通过 lineCap 属性可以控制线条末端的形状是平头、圆头还是方头("butt"、 "round"或"square"),通过 lineJoin 属性可以控制线条相交的方式是圆交、斜 交还是斜接("round"、"bevel"或"miter")。
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d");
//绘制红色描边矩形
context.strokeStyle = "#ff0000"; context.strokeRect(10, 10, 50, 50);
//绘制半透明的蓝色描边矩形
context.strokeStyle = "rgba(0,0,255,0.5)"; context.strokeRect(30, 30, 50, 50);
}
*
clearRect()方法
用于清除画布上的矩形区域。本质上,这个方法可以把绘制上下文中的某 一矩形区域变透明。
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d");
//绘制红色矩形
context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50);
//绘制半透明的蓝色矩形
context.fillStyle = "rgba(0,0,255,0.5)"; context.fillRect(30, 30, 50, 50);
//在两个矩形重叠的地方清除一个小矩形
context.clearRect(40, 40, 10, 10);
}
(3) 绘制路径
(1) 要绘制路径,首先必须调用 beginPath()方法
,表示要开始 绘制新路径。
(2) 然后,再通过调用下列方法来实际地绘制路径。
- 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()所绘制的独立的形状。
(4) 创建了路径后,接下来有几种可能的选择。
closePath()
:绘制一条连接到路径起点的线条。fill()
:填充路径,使用fillStyle 填充。stroke()
:对路径描边,描边使用的是 strokeStyle。clip()
:在路径上创建一个剪切区域。
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d");
//开始路径
context.beginPath();
//绘制外圆
context.arc(100, 100, 99, 0, 2 * Math.PI, false);
//绘制内圆
context.moveTo(194, 100);
context.arc(100, 100, 94, 0, 2 * Math.PI, false);
//绘制分针
context.moveTo(100, 100);
context.lineTo(100, 15);
//绘制时针
context.moveTo(100, 100);
context.lineTo(35, 100);
//描边路径
context.stroke();
}
isPointInPath()的方法
,这个方法接收 x 和 y 坐标作为 参数,用于在路径被关闭之前确定画布上的某一点是否位于路径上。
if (context.isPointInPath(100, 100)){
alert("Point (100, 100) is in the path.");
}
(4) 绘制文本
- 绘制文本主要有两个 方法:
fillText()
和strokeText()
。 - 这两个方法都可以接收
4 个参数
:要绘制的文本字符串、x 坐 标、y 坐标和可选的最大像素宽度。 - 这两个方法都以下列
3 个属性
为基础。
(1) font:表示文本样式、大小及字体,用 CSS 中指定字体的格式来指定,例如"10px Arial"。
(2) textAlign:表示文本对齐方式。可能的值有"start"、"end"、"left"、"right"和"center"。
(3) textBaseline:表示文本的基线。可能的值有"top"、"hanging"、"middle"、"alphabetic"、
"ideographic"和"bottom"。
*
textAlign
设置为"start",则 x 坐标表示的是文本左 端的位置(从左到右阅读的语言);设置为"end",则 x 坐标表示的是文本右端的位置。`
//正常
context.font = "bold 14px Arial";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText("12", 100, 20);
//起点对齐
context.textAlign = "start";
context.fi llText("12", 100, 40);
//终点对齐
context.textAlign = "end";
context.fi llText("12", 100, 60);
*
textBaseline 属性
的值可以调整文本的垂直对齐方式:值为"top",y 坐标表示文本顶端;值为 "bottom",y 坐标表示文本底端;值为"hanging"、"alphabetic"和"ideographic",则 y 坐标分 别指向字体的特定基线坐标。
*
measureText()方法
利用 font、textAlign 和 textBaseline 的当前值计算指定文本的大小
。
这个方法接收一个参数
,即要绘制的文本;返回一个 TextMetrics 对象。返回的对象目前只有一个width 属性
,但将来还会增加更多度量属性。
var fontSize = 100;
context.font = fontSize + "px Arial";
while(context.measureText("Hello world!").width > 140){
fontSize--;
context.font = fontSize + "px Arial";
}
context.fillText("Hello world!", 10, 10);
context.fillText("Font size is " + fontSize + "px", 10, 50);
(5) 变换
- 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()。
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d");
//开始路径
context.beginPath();
//绘制外圆
context.arc(100, 100, 99, 0, 2 * Math.PI, false);
//绘制内圆
context.moveTo(194, 100);
context.arc(100, 100, 94, 0, 2 * Math.PI, false);
//变换原点
context.translate(100, 100);
//旋转表针
context.rotate(1);
//绘制分针
context.moveTo(0,0);
context.lineTo(0, -85);
//绘制时针
context.moveTo(0, 0);
context.lineTo(-65, 0);
//描边路径
context.stroke();
}
*
save()方法
调用这个方法后,当时的所有设置都会进入一个栈结构,得以妥善保管。
*restore()方法
,在保存设置的栈结构中向前返回一级, 恢复之前的状态。
context.fillStyle = "#ff0000";
context.save();
context.fillStyle = "#00ff00";
context.translate(100, 100);
context.save();
context.fillStyle = "#0000ff";
context.fillRect(0, 0, 100, 200); //从点(100,100)开始绘制蓝色矩形
context.restore();
context.fillRect(10, 10, 100, 200); //从点(110,110)开始绘制绿色矩形
context.restore();
context.fillRect(0, 0, 100, 200); //从点(0,0)开始绘制红色矩形
(6) 绘制图像
drawImage() 方法
:想把一幅图像绘制到画布上。
调用这个方法的3种参数组合:
- 传入一个 HTML <img>元素,以及绘制该图像的起点的 x 和 y 坐标。
var image = document.images[0];
context.drawImage(image, 10, 10);
- 如果你想改变绘制后图像的大小,可以再多传入两个参数,分别表示
目标宽度
和目标高度
。
context.drawImage(image, 50, 10, 20, 30);
-
选择把图像中的某个区域绘制到上下文中
。drawImage()方法的这种调 用方式总共需要传入 9 个参数:要绘制的图像、源图像的 x 坐标、源图像的 y 坐标、源图像的宽度、源 图像的高度、目标图像的 x 坐标、目标图像的 y 坐标、目标图像的宽度、目标图像的高度。
context.drawImage(image, 0, 10, 50, 50, 0, 100, 40, 60);
(7) 阴影
- shadowColor:用 CSS 颜色格式表示的阴影颜色,默认为黑色。
- shadowOffsetX:形状或路径 x 轴方向的阴影偏移量,默认为 0。
- shadowOffsetY:形状或路径 y 轴方向的阴影偏移量,默认为 0。
- shadowBlur:模糊的像素数,默认 0,即不模糊。
这些属性都可以通过 context 对象来修改。只要在绘制前为它们设置适当的值,就能自动产生阴 影。
var context = drawing.getContext("2d");
//设置阴影
context.shadowOffsetX = 5;
context.shadowOffsetY = 5;
context.shadowBlur = 4;
context.shadowColor = "rgba(0, 0, 0, 0.5)";
//绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//绘制蓝色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
(8) 渐变
createLinearGradient()方法
(线性渐变),这个方法接收 4 个参数:起点的 x 坐标、起点的 y 坐 标、终点的 x 坐标、终点的 y 坐标。调用这个方法后,它就会创建一个指定大小的渐变,并返回 CanvasGradient 对象的实例。addColorStop()方法
来指定色标。这个方法接收两个参数: 色标位置和 CSS 颜色值。色标位置是一个 0(开始的颜色)到 1(结束的颜色)之间的数字。
var gradient = context.createLinearGradient(30, 30, 70, 70);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
gradient 对象表示的是一个从画布上点(30,30)到点(70,70)的渐变。起点的色标是白色,终 点的色标是黑色。然后就可以把 fillStyle 或 strokeStyle 设置为这个对象,从而使用渐变来绘制 形状或描边
//绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//绘制渐变矩形
context.fillStyle = gradient;
context.fillRect(30, 30, 50, 50);
确保渐变 与形状对齐:
function createRectLinearGradient(context, x, y, width, height){
return context.createLinearGradient(x, y, x+width, y+height);
}
var gradient = createRectLinearGradient(context, 30, 30, 50, 50);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
//绘制渐变矩形
context.fi llStyle = gradient; context.fillRect(30, 30, 50, 50);
createRadialGradient()方法
(径向渐变[放射渐变]),接收 6 个参 数,对应着两个圆的圆心和半径。前三个参数指定的是起点圆的原心(x 和 y)及半径,后三个参数指 定的是终点圆的原心(x 和 y)及半径。
var gradient = context.createRadialGradient(55, 55, 10, 55, 55, 30);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
//绘制红色矩形
context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50);
//绘制渐变矩形
context.fillStyle = gradient; context.fillRect(30, 30, 50, 50);
(9) 模式
模式其实就是重复的图像,可以用来填充或描边图形。
要创建一个新模式,可以调用
createPattern()方法
并传入两个参数
:一个 HTML <img>元素和一个表示如何重复图像的字符串。 其中,第二个参数的值与 CSS 的 background-repeat 属性值相同,包括"repeat"、"repeat-x"、 "repeat-y"和"no-repeat"。
var image = document.images[0],
pattern = context.createPattern(image, "repeat");
//绘制矩形
context.fillStyle = pattern; context.fillRect(10, 10, 150, 150);
模式与渐变一样,都是
从画布的原点(0,0)开始的
。将填充样式(fillStyle)设置 为模式对象,只表示在某个特定的区域内显示重复的图像,而不是要从某个位置开始绘制重复的图像。
(10) 使用图像数据
getImageData()
取得原始图像数据。这个方法接收 4 个参数:要取得其数据的画面区域的 x 和 y 坐标以及该区域的像素宽度和高度。
var imageData = context.getImageData(10, 5, 50, 50);
- 这里返回的对象是 ImageData 的实例。每个 ImageData 对象都有三个属性:width、height 和data。
- 其中 data 属性是一个数组,保存着图像中每一个像素的数据。在 data 数组中,每一个像素用4 个元素来保存,分别表示红、绿、蓝和透明度值。因此,第一个像素的数据就保存在数组的第 0 到第3 个元素中。
通过修改图像数据,可以像下面这样创建一个简单的灰阶过滤器:
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d"),
image = document.images[0],
imageData, data,
i, len, average,
red, green, blue, alpha;
//绘制原始图像
context.drawImage(image, 0, 0);
//取得图像数据
imageData = context.getImageData(0, 0, image.width, image.height); data = imageData.data;
for (i=0, len=data.length; i < len; i+=4){
red = data[i];
green = data[i+1];
blue = data[i+2];
alpha = data[i+3];
//求得 rgb 平均值
average = Math.floor((red + green + blue) / 3);
//设置颜色值,透明度不变
data[i] = average;
data[i+1] = average;
data[i+2] = average;
}
//回写图像数据并显示结果
imageData.data = data;
context.putImageData(imageData, 0, 0);
}
(11) 合成
globalAlpha
是一个介于 0 和 1 之间的值(包括 0 和 1),用于指定所有绘制的透 明度。默认值为 0。
//绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//修改全局透明度
context.globalAlpha = 0.5;
//绘制蓝色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
//重置全局透明度
context.globalAlpha = 0;
globalCompositionOperation
表示后绘制的图形怎样与先绘制的图形结合。这个 属性的值是字符串,可能的值如下:
(1) source-over(默认值):后绘制的图形位于先绘制的图形上方。
(2) source-in:后绘制的图形与先绘制的图形重叠的部分可见,两者其他部分完全透明。
(3) source-out:后绘制的图形与先绘制的图形不重叠的部分可见,先绘制的图形完全透明。
(4) source-atop:后绘制的图形与先绘制的图形重叠的部分可见,先绘制图形不受影响。
(5) destination-over:后绘制的图形位于先绘制的图形下方,只有之前透明像素下的部分才可见。
(6) destination-in:后绘制的图形位于先绘制的图形下方,两者不重叠的部分完全透明。
(7) destination-out:后绘制的图形擦除与先绘制的图形重叠的部分。
(8) destination-atop:后绘制的图形位于先绘制的图形下方,在两者不重叠的地方,先绘制的图形会变透明。
(9) lighter:后绘制的图形与先绘制的图形重叠部分的值相加,使该部分变亮。
(10) copy:后绘制的图形完全替代与之重叠的先绘制图形。
(11) xor:后绘制的图形与先绘制的图形重叠的部分执行“异或”操作。
3. WebGL
(1) 类型化数组
- 类型化数组的核心就是一个名为
ArrayBuffer 的类型
。每个 ArrayBuffer 对象表示的只是内存 中指定的字节数,但不会指定这些字节用于保存什么类型的数据。通过 ArrayBuffer 所能做的,就是 为了将来使用而分配一定数量的字节。
var buffer = new ArrayBuffer(20);
- 创建了 ArrayBuffer 对象后,能够通过该对象获得的信息只有它包含的字节数,方法是访问其
byteLength 属性
:
var bytes = buffer.byteLength;
*视图
使用 ArrayBuffer(数组缓冲器类型)的一种特别的方式就是用它来
创建数组缓冲器视图
。其中, 最常见的视图是DataView
,通过它可以选择 ArrayBuffer 中一小段字节。
(1) 在
创建 DataView 实例
的时候传入一个 ArrayBuffer、一个可选的字节偏移量(从该字节开始选择)和一个可选的要选 择的字节数。
//基于整个缓冲器创建一个新视图
var view = new DataView(buffer);
//创建一个开始于字节 9 的新视图
var view = new DataView(buffer, 9);
//创建一个从字节 9 开始到字节 18 的新视图
var view = new DataView(buffer, 9, 10);
(2) DataView 对象会把字节偏移量以及字节长度信息分别保存在
byteOffset
和byteLength
属性中。
alert(view.byteOffset);
alert(view.byteLength);
(3) DataView 支持的数据类型以及相应的读写方法:
var buffer = new ArrayBuffer(20),
view = new DataView(buffer),
value;
view.setUint16(0, 25);
view.setUint16(2, 50); //不能从字节 1 开始,因为 16 位整数要用 2B
value = view.getUint16(0);
var buffer = new ArrayBuffer(20),
view = new DataView(buffer),
value;
view.setUint16(0, 25);
value = view.getInt8(0);
alert(value); //0
*类型化视图
类型化视图
一般也被称为类型化数组,因为它们除了元素必须是某种特定的数据类型外,与常规的 数组无异。
类型化视图也分几种,而且它们都继承了 DataView。
(1) Int8Array:表示 8 位二补整数。
(2) Uint8Array:表示 8 位无符号整数。
(3) Int16Array:表示 16 位二补整数。
(4) Uint16Array:表示 16 位无符号整数。
(5) Int32Array:表示 32 位二补整数。
(6) Uint32Array:表示 32 位无符号整数。
(7) Float32Array:表示 32 位 IEEE 浮点值。
(8) Float64Array:表示 64 位 IEEE 浮点值。
- 由于这些视图都继承自 DataView,因而可以使用相同的构造函数
参数
来实例化。第一个参数是要 使用 ArrayBuffer 对象,第二个参数是作为起点的字节偏移量(默认为 0),第三个参数是要包含的字 节数。三个参数中只有第一个是必需的。
//创建一个新数组,使用整个缓冲器
var int8s = new Int8Array(buffer);
//只使用从字节 9 开始的缓冲器
var int16s = new Int16Array(buffer, 9);
//只使用从字节 9 到字节 18 的缓冲器
var uint16s = new Uint16Array(buffer, 9, 10);
- 每个视图构造函数都有一个名为
BYTES_PER_ELEMENT
的属性,表示类型化数组的每个元素需要多 少字节。
//需要 10 个元素空间
var int8s = new Int8Array(buffer, 0, 10 * Int8Array.BYTES_PER_ELEMENT);
//需要 5 个元素空间
var uint16s = new Uint16Array(buffer, int8s.byteOffset + int8s.byteLength, 5 * Uint16Array.BYTES_PER_ELEMENT);
- 使用类型化视图时,可以通过
方括号语法访问每一个数据成员
,可以通过 length 属性确定数组中有多少元素。
for (var i=0, len=int8s.length; i < len; i++){
console.log("Value at position " + i + " is " + int8s[i]);
}
- 类型化视图还有一个方法,即
subarray()
,使用这个方法可以基于底层数组缓冲器的子集创建一 个新视图。这个方法接收两个参数:开始元素的索引和可选的结束元素的索引。返回的类型与调用该方 法的视图类型相同。
var uint16s = new Uint16Array(10),
sub = uint16s.subarray(2, 5);
(2) WebGL上下文
- 在支持的浏览器中,WebGL 的名字叫
"experimental-webgl"
,如果浏览器不支持 WebGL, 那么取得该上下文时会返回 null。
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素 if (drawing.getContext){
var gl = drawing.getContext("experimental-webgl");
if (gl){
//使用 WebGL }
}
- 通过给 getContext()传递
第二个参数
,可以为 WebGL 上下文设置一些选项。这个参数本身是一 个对象,可以包含下列属性。
(1) alpha:值为 true,表示为上下文创建一个 Alpha 通道缓冲区;默认值为 true。
(2) depth:值为 true,表示可以使用 16 位深缓冲区;默认值为 true。
(3) stencil:值为 true,表示可以使用 8 位模板缓冲区;默认值为 false。
(4) antialias:值为 true,表示将使用默认机制执行抗锯齿操作;默认值为 true。
(5) premultipliedAlpha:值为 true,表示绘图缓冲区有预乘 Alpha 值;默认值为 true。
(6) preserveDrawingBuffer:值为 true,表示在绘图完成后保留绘图缓冲区;默认值为 false。建议确实有必要的情况下再开启这个值,因为可能影响性能。
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
var gl = drawing.getContext("experimental-webgl", { alpha: false});
if (gl){
//使用 WebGL
}
}
*常量
在 WebGL 中,保存在上下文对象中的这些常量都没有 GL_前缀。
*方法命名
- 方法名的后缀会包含参数个数(1 到 4) 和接收的数据类型(f 表示浮点数,i 表示整数)。例如,gl.uniform4f()意味着要接收 4 个浮点数,而 gl.uniform3i()则表示要接收 3 个整数。
- 也有很多方法接收数组参数而非一个个单独的参数。这样的方法其名字中会包含字母 v(即 vector, 矢量)。因此,gl.uniform3iv()可以接收一个包含 3 个值的整数数组。
*准备绘图
在实际操作 WebGL 上下文之前,一般都要使用某种实色清除<canvas>,为绘图做好准备。
clearColor()方法
来指定要使用的颜色值,该方法接收 4 个参数:红、绿、蓝和透明度。 每个参数必须是一个 0 到 1 之间的数值,表示每种分量在最终颜色中的强度。clear()方法
传入的参数gl.COLOR_BUFFER_BIT
告诉 WebGL 使用之前定义的颜色来填充相应区 域。
gl.clearColor(0,0,0,1); //black
gl.clear(gl.COLOR_BUFFER_BIT);
*视口与坐标
开始绘图之前,通常要先定义 WebGL 的视口(viewport)。默认情况下,视口可以使用整个<canvas> 区域。
1.
viewport()方法
改变视口大小,传入 4 个参数:(视口相对于<canvas>元素的) x 坐标、y 坐标、宽度和高度。
视口坐标
的原点(0,0)在<canvas>元素的左下角,x
轴和 y 轴的正方向分别是向右和向上。视口内部的坐标系
与定义视口的坐标系也不一样。在视口内部,坐标原点(0,0)是视口的中心 点,因此视口左下角坐标为(-1,-1),而右上角坐标为(1,1)。
*缓冲区
顶点信息保存在 JavaScript 的类型化数组中,使用之前必须转换到 WebGL 的缓冲区。
gl.createBuffer()
创建缓冲区。gl.bindBuffer()
绑定到 WebGL 上下文。gl.bufferData()
数据填充缓冲区。- gl.bufferData()的最后一个参数用于指定使用缓冲区的方式,取值范围是如下几个常量。
(1) gl.STATIC_DRAW:数据只加载一次,在多次绘图中使用。
(2) gl.STREAM_DRAW:数据只加载一次,在几次绘图中使用。
(3) gl.DYNAMIC_DRAW:数据动态改变,在多次绘图中使用。drawElements()
输出缓冲区的内容,也可以传入 gl.ELEMENT_ARRAY_BUFFER。gl.deleteBuffer()
释放内存。
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.5, 1]), gl.STATIC_DRAW);
gl.deleteBuffer(buffer);
网友评论