canvas画图
一,基本用法
1,使用前给canvas设定高度和宽度,出现在标签中的内容在浏览器不支持canvas时使用
<canvas id="drawing" width="200",height="200">A drawing of something</canvas>
2,getContext("2d");取得绘图上下文的引用
var drawing = document.getElementById("drawing"); if(drawing.getContext){ var context = drawing.getContext("2d"); }
3,使用toDataURL()方法,可以导出canvas元素上绘制的图像,接收一个MIME类型格式
var drawing = document.getElementById("drawing"); if(drawing.getContext){ var context = drawing.getContext("2d"); var imgURL = drawing.toDataURL("image/png"); var image = document.createElement("img"); image.src=imgURL; document.body.appendChild(image); }
二,2D上下文
1,填充和描边
填充是用指定的样式(颜色,渐变或图像)填充图形
描边只在图形的边缘画线,
使用fillStyle,strokeStyle两个属性
2,绘制矩形
fillRect(),strokeRect(),clearRect(),接收四个参数,矩形的x坐标,y坐标,矩形宽度和矩形高度
var drawing = document.getElementById("drawing"); if(drawing.getContext){ var context = drawing.getContext("2d"); context.fillStyle = "#0000ff"; context.fillRect(10,10,40,50); context.fillStyle = "rgba(0,0,255,0.5)"; context.fillRect(30,30,50,50); context.strokeStyle = "red"; context.StrokeRect(30,30,80,80); }
lineWidth属性指定线条的宽度,
lineCap属性指定线条末端的形状,平头(butt),圆头(round),方头(square)
lineJoin属性指定线条相交的方式,圆交(round),斜交(bevel),斜接(miter)
clearRect()用于清除一个矩形,把上下文的某一矩形表透明
3,绘制路径
beginPath(),开始路径,closePath(),闭合路径(将终点和起点闭合)
arc(x,y,radius,startAngle,endAngle,counterclockwise)
arcTo(x1,y1,x2,y2,radius):从上一点开始到(x2,y2)的一条弧线,给定的半径穿过(x1,y1)
bezierCurveTo(c1x,c1y,c2x,c2y,x,y):从上一点开始到(x,y)的弧线,(x1,y1)(x2,y2)为控制点
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)绘制矩形,
路径完成,使用filleStyle属性设置填充样式,使用fill()方法实现填充
使用strokeStyle属性设置描边样式,使用stroke()方法,对路径描边
使用clip(),在路径上创建一个剪切区域
var drawing = document.getElementById("drawing"); if(drawing.getContext){ var context = doawing.getContext; 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)方法,用于判断路径被闭合之前,(x,y)是否位于路径上
if(context.isPointInPath(100,100)){alert("Yes");}
4,绘制文本
fillText(),strokeText(),接收四个参数,绘制的文本字符串,x坐标,y坐标,可选的最大像素宽度
font属性:表示文本样式,大小,字体
textAlign属性:文本对齐方式,有start,end,left,right,和center
textBaseline属性:文本的基线,top,hanging,middle,alphabetic,ideographic,bottom
使用fillStyle属性绘制文本,使用fillText()方法实现
measureText(),接收一个参数,要绘制的文本,返回一个对象,仅有一个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
translate(x,y):将坐标原点移动到(x,y),
transform(m1_1,m1_2,m2_1,m2_2,dx,dy):直接修改变化矩阵,方式乘以如下矩阵
m1_1 m1_2 dx
m2_1 m2_2 dy
0 0 1
setTransform(m1_1,m1_2,m2_1,m2_2):将变换矩阵重置为默认状态,然后调用transform()
save(),方法保存某组属性与变换,后面可能还会用到,只保存上下文的设置和变换,不会保存内容
restore(),在保存设置的栈结构中向前返回一级
连续设置save(),可以把更多的设置保存在栈结构中,restore(),可以一级一级的返回
6,绘制图像
drawImage(要绘制的图像,源图像的x坐标,源图像的y坐标,源图像的宽度,源图像的高度,目标图像的x坐标,目标图像的y坐标,目标图像的宽度,目标 图像的高度);
image为从html<img>元素获取
操作结果通过toDataURL()方法获取
7,阴影
shadowColor属性:用css样式表示阴影颜色,默认为黑色
shadowOffsetX属性:形状或路径x轴方向的阴影偏移量
shadowOffsetY属性:形状或路径y轴方向的引用偏移量
shadowBlur属性:模糊的像素数
8,渐变
渐变有canvasGradient实例表示
线性渐变,createLinearGradient(起点x坐标,起点y坐标,终点x坐标,终点y坐标)
使用addColorStop(色标位置,CSS颜色值)方法来指定色标
var gradient = context.createLinearGradient(30,30,70,70);
gradient.addColor(0,"white");
gradient.addColor(1,"black");
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);
}
径向渐变,createRadialGradient(x1,y1,radius1,x2,y2,radius2)
一般设置同心圆情况较多,此时只要考虑两个圆设置不同的半径就好
9,模式
createPattern(HTML<img>元素,表示如何重复图像的字符串)
第二个参数可以为 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);
只表示在画布中的从(10,10)到(150,150)区域显示重复的图片
第一个参数也可以是video元素,或者另一个canvas元素
10,使用图像数据
getImageData(要取得其数据的画面区域的x和y坐标,该区域的像素宽度和高度),
返回一个imageData的实例,每个imageData对象有三个属性,width,height,data
data属性是一个数组,保存着图像中每个像素的数据,data数组中,每个像素用四个元素来保存,表示红,绿,蓝,透明度
第一个像素的数据就保存在数组的第0到第3个元素中
var data = imageData.data,red=data[0],green=data[1],blue=data[2],alpha=fata[3];
一个简单的灰阶过滤器
var drawing = document.getElementById("drawing"); if(drawing.getContext){ var context = drawing.getContext; var image = document.images[0]; var imageData,data,i,len,average,re,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=i+4){ red = data[i]; green = data[i+1]; blue = data[i+2]; alpha = data[i+3]; 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) }
putImageData()方法是把图像数据绘制到画布上
11,合成
globalAlpha属性:介于0-1的值,指定所有绘制的透明度,全局透明度,设置后要设置为默认透明度为0
globalCompositionOperation属性:表示后绘制的图像怎样与先绘制的图形结合,属性值如下
source-over:后绘制的图像位于先绘制的图形上面
source-in:后绘制的图形和先绘制的图形重叠部分可见,两者其余部分完全透明
source-out:后绘制的图形和先绘制的图形不重叠部分可见,先绘制的图形完全透明
source-atop:后绘制的图形和先绘制的图形重叠部分可见,先绘制的图形不受影响
destination-over:后绘制的图形位于先绘制的图形下方,只有之前透明像素下的部分可见
destination-in:后绘制的图形位于先绘制的图形下方,两者不重叠部分完全透明
destination-out:后绘制的图形擦除与先绘制的图形重叠部分
destination-atop:后绘制的图形位于先绘制的图形下方,不重叠不部分,先绘制的图形会变透明
lighter:后绘制的图形与先绘制的图形重叠部分的值相加,该部分变亮
copy:后绘制的图形完全替代与之重叠的先绘制的图形
xor:后绘制的图形与先绘制的图形重叠部分执行异或操作
三,WebGL
1,类型化数组
类型化数组的核心是一个名为ArrayBuffer的类型,每个ArrayBuffer对象表示的只是内存中指定的字节数,不会指定这些字节用于保存什么类型的数据
var buffer = new ArrayBuffer(20);
var bytes = buffer.byteLength;
1)视图
使用ArrayBuffer的一种特别的方式就是来创建数组缓冲器视图,创建视图DataView实例的时候传人ArrayBuffer,可选的字节偏移量,可选的要选择的字节数
var buffer = new ArrayBuffer(20);
var view = new DataView(buffer,9,15);
实例化后,byteOffset保存字节偏移量,byteLength保存字节长度
读取和写入DataView的时候,要根据实际操作的数据类型,选择相应的getter和setter方法
有符号8位整数 getInt8(byteOffset) setInt8(byteOffset,value)
无符号8位整数 getUint8(byteOffset) setUint8(byteOffset,value)
有符号16位整数 getInt16(byteOffset) setInt16(byreOffset,value)
无符号16位整数 getUint16(byteOffset) setUint16(byteOffset,value)
有符号32位整数 getInt32(byteOffset) setInt32(byteOffset,value)
无符号32位整数 getUitn32(byteOffset) setUint32(byteOffset,value)
32位浮点数 getFloat32(byteOffset setFloat32(byteOffset,value)
64位浮点数 getFloat64(byteOffset) setFloat64(byteOffset,value)
读写16位或更大数值的方法都有一个可选的littleEndian属性,是一个布尔值,表示是否采用最小端字节序
var buffer = new ArrayBuffer(20);
var view = new DataView(buffer);
view.setUint16(0,25); 以无符号16位写入25在0位置
var value = view.getInt8(0); 以有符号8为读出0位置的值
2)类型化视图
类型化视图继承了DataView,
Int8Array,Int16Array,Int32Array,表示8,16,32位二补整数
Uint8Array,Uint16Array,Uint32Array,表示8,16,32位无符号整数
Float32Array,Float64Array,表示32,64为IEEE浮点值
var int8s = new Int8Array(buffer,9,10)
同一个缓冲区保存不同类型的数值
var int8s = new Int8Array(buffer,0,10);
var int16s = new Int16Array(butter,11,10);
每个视图构造函数都有一个名为BYTES_PER_ELEMENT属性,保存类型化数组的每个元素需要多少字节
创建类型化视图可以不用先创建ArrayBuffer对象,只要传人希望数组保存的元素数,相应的构造函数就会自动创建包含足够字节数的ArrayBuffer对象
var int8s = new Int8Array(10);
var int8s = new Int8Array([10,20,30,20,20]);保存5个8位整数
通过length属性确定数组中包含的元素个数
subarray()方法,接收两个参数,开始元素的索引和可选的结束元素的索引,返回类型与调用该方法的视图类型相同
2,WebGL上下文
var drawing = document.getElementById("drawing"); if(drawing.getContext){ var gl = drawing.getContext("experimental-webgl"); if(gl){} }
getContext()接收第二个参数,可以为webGL上下文设置一些选项,参数本身是一个对象,包含属性如下
alpha:值为true,表示为上下文创建一个Alpha通道缓冲区,默认值为true
depth:值为true,表示可以使用16位深缓冲区,默认为true
stencil:值为true,表示可以使用8位模板缓冲区,默认为true
antialias:值为true,表示将使用默认机制执行抗锯齿操作,默认值为true
premultipliedAlpha:值为true,表示绘图缓冲区有预乘Alpha值,默认为true
preserveDrawingBuffer:值为true,表示在绘图完成后,保留绘图缓冲区,默认为false
var gl = drawing.getContext("experimental-webgl",{alpha:false}); if(drawing.getContext){ try{ gl = drawing.getContext("experimental-webgls"); }catch(ex){} if(gl){}else{} }
1)常量
gl.开头,比如gl.COLOR_BUFFER_BIT
2)方法命名
通过方法名后缀判断接收的参数的类型和数量,f表示浮点数,i表示整数,v表示接收数组参数
如gl.uniform3iv()
3)准备绘图
实际操作上下文前,要使用某种实色清除canvas
clearColor(),方法来指定要使用的颜色值,接收4个参数,红,绿,蓝,透明度,参数0-1,表示分量的强度
clear(),方法,清理缓冲区
4)视图与坐标
开始绘图之前,要先定义webGL的视口,调用viewport()方法,参数为视口相对于canvas元素的x坐标,y坐标,宽度和高度
gl.viewport(0,0,drawing.width,drawing.height);
视口坐标原点在canvas元素的左下角
视口内部的坐标系原点在中心位置
5)缓冲区
创建缓冲区,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);
gl.bufferData(),的最后一个参数用于指定使用缓冲区的方式,取值范围如下
gl.STATIC_DRAW:数据只加载一次,在多次绘图中使用
gl.STREAM_DRAW:数据只加载一次,在几次绘图中使用
gl.DYNAMIC_DRAW:数据动态改变,在多次绘图中使用
6)错误
手工调用gl.getError(),返回一个错误类型的常量
gl.NO_ERROR:没有错误
gl.INVALID_ENUM:应该传人webGL常量,但传错了参数
gl.INVALID_VALUE:在需要无符号的地放传入了负值
gl.INVALID_OPERATION:在当前状态下不能完成操作
gl.OUT_OF_MENORY:没有足够的内存完成操作
gl.CONTEXT_LOST_WEBGL:外部文件干扰,丢失了当前webGL上下文
var errorCode = gl.getError(); while(errorCode){ console.log("Error occurred:" + errorCode); errorCode = gl.getError(); }
7)着色器
定点着色器:将3D顶点转换为需要渲染的2D点
片段着色器:准确计算要绘制的每个像素的颜色
8)编写着色器
9)编写着色器程序
10)为着色器传人值
11)调试着色器和程序
12)绘图
13)文理
14)读取像素
3,支持