canvas画图

跟風遠走 提交于 2020-02-04 07:52:51

一,基本用法
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,支持

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!