JavaScript高级程序设计学习记录-canvas

880 阅读6分钟

<canvas> 标签是HTML5最受欢迎的新特性,会占据一块页面区域,使用JavaScript可以动态的绘制图片。<canvas> 自身提供一些API包括支持基础绘图能力的2D上下文和被称为WebGL的3D上下文。

1. 使用requestAnimationFrame

这个api的作用是告诉浏览器要执行动画,浏览器会以最优方式确定重绘的时序。

1.1 早定定时动画

在早期或不支持requestAnimationFrame()的浏览器里,我们可以使用setInterVal来循环实现。因为显示器的刷新率一般是60Hz,这意味着每秒需要重绘60次,所以实现平滑动画最佳重绘间隔为1000 / 60。但如果同时云顶多个动画就需要加以限流,一面重绘间隔过快动画过早运行完成。

setIntervalsetTimeout是不能保证事件精度的。如果添加到队列后,主线程还被其他任务占用的话,任务不会马上执行。

1.2 requestAnimationFrame

requestAnimationFrame接收一个参数,也就是要调用的函数。要实现动画循环可以把多个requestAnimationFrame调用串联起来。

传给requestAnimationFrame的函数可以接收以参数,这个参数表示下次重绘的事件。

requestAnimationFrame()会返回一个请求ID,可以通过cancelAnimationFrame()来取消任务。

function updateProgress() {
  let div = document.querySelector('.status')
  div.style.width = (parseInt(div.style.width, 10) + 5) + '%'
  if(div.style.left != '100%') {
    requestAnimationFrame(updateProgress)
  }
}

requestAnimationFrame(updateProgress)

2. 基本的画布功能

创建canvas标签必须要设置width和height属性。标签之间的内容是后背属性,当canvas不显示时显示。

getContext()可以获取canvas上下文的引用,平面图形需要传入参数"2d"。

toDataURL()用来导出canvas的图像,他接收一个参数:图片的类型,默认png格式。

let canvas = document.querySelector('#canvas')

let context = canvas.getContext('2d')

let imgURI = canvas.toDataURL('image/png')

2.1 2D绘图上下文

1. 填充和描边

填充是以指定样式自动填充图形,描边置位图形边界着色。他俩的显示效果取决于两个属性:fillStylestrokeStyle

let canvas = document.querySelector('#canvas')

let context = canvas.getContext('23')

context.strokeStyle = 'red'
constex.fillStyle = '#0000ff'

2. 绘制矩形

矩形是唯一一个可以直接在2D绘图上下文忠绘制的形状,能够绘制的方法有三个: fillRect()strokeRect()clearRect() ,他们都接受四个参数:矩形x坐标矩形y坐标矩形宽度矩形长度 。他们的单位都是像素。

  • fillRect()用于指定颜色在画布上绘制并填充矩形,填充的颜色使用fillStyle。
  • strokeRect() 方式通过strokeStyle属性指定的颜色绘制矩形轮廓,是个空心的矩形。
  • clearRect() 方法可以擦除画布中的某个区域,把他变为透明。
let canvas = document.querySelector('#canvas')
let context = canvas.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)

这段代码的意思是将线条颜色设置为红色,在坐标点(10,10)绘制了一个宽高为50像素的矩形,然后将线条颜色设置为半透明蓝色,在坐标点(30,30)绘制了一个宽高为50像素的矩形。clearRect会在坐标点(40,40)的地方擦除宽高为10像素的矩形,相当于开了个孔。

3. 绘制路径

绘制路径必须先调用begeinPath()方法表示要开始绘制新路径,然后在调用下列方法来绘制路径

  • arc(x, y, radius, startAngle, endAngle, counterclockwise):以坐标(x,y)为圆心,以radius为半径绘制一条弧线,其实角度为startAngle,结束调度为endAngle。counterclockwise表示是否为逆时针绘制,默认顺时针。
  • arcTo(x1, y1, x2, y2, radius) :以给定半径 radius ,经由 (x1,y1) 绘制一条从上一点到 (x2, y2) 的弧线。
  • bezierCurveTo(c1x, c1y, c2x, c2y, x, y):以 (c1x, c1y) 和(c2x, c2y) 为控制点,绘制一条从上一点到 (x, y) 的弧线(三次贝塞尔曲线)。
  • lineTo(x ,y):绘制一条从上一点到(x, y)的直线。
  • moveT(x ,y):不绘制线条,只把绘制光标移动到(x, y)
  • quadraticCurveTo(cx, cy, x, y) :以 (cx, cy) 为控制点,绘制一条从上一点到 (x, y)的弧线(二次贝塞尔曲线)。
  • rect(x, y, width, height):以给定宽度和高度在坐标点 (x, y) 绘制一个矩形。这个方法与 strokeRect() 和 fillRect() 的区别在于,它创建的是一条路径,而不是独立的图形。

创建路径之后,可以使用closePath() 绘制一条返回起点的线。使用clip() 方法可以创建一个新剪切区域。

4. 绘制文本

fillText()strokeText() 可以绘制文本,接收四个参数:要绘制的字符串、x坐标、y坐标和可选的最大像素宽度。

使用以下三个属性可以设定文本的样式:

  • font:字体样式、大小、字体等,比如 '10px Arial'。
  • textAlign:指定文本的对齐方式,可选值为'satrt'、'end'、'left'、'right'和'center'。
  • textBaseLine:指定文本的基线,可选值为'top''hanging'、'middle'、'alphabetic'、'ideographic'、'bottom'。

5. 变化

以下方法可以改变canvas的变化矩阵

  • rotate(angle):围绕原点旋转angle弧度
  • scale(scaleX, scaleY):通过在 x 轴乘以 scaleX 、在 y 轴乘以 scaleY 来缩放图像。 scaleX和 scaleY 的默认值都是 1.0
  • translate(x, y) :把原点移动到 (x, y) 。执行这个操作后,坐标(0, 0)就会变成 (x, y) 。

6. 绘制图像

drawImage方法可以把现有图像绘制到canvas上。

let image = document.querySelector('img')
context.drawImage(image,10,10)

获取第一个img的图像,在画布的坐标点(10,10)出绘制出来,绘制的图像大小与原图像一致,如果要改变大小可传入目标宽度和高度。

context.drawImage(image,10,10,20,30)

7.图像数据

getImageData 方法可以获取原始图像数据,接收四个参数:要取得数据中第一个像素的左上角坐标和要取得的像素宽度及高度。

let imageData = context.getImageData(10, 5, 50, 50)

从坐标点(10,5)处开始获取50像素宽、50像素高的数据,返回一个ImageData的实例对象,包含3个属性:width、height和data,data包含图像的原始像素信息的数组。

2.2 WebGl

webgl是画布的3d上下文。

在完全支持的浏览器中,WebGL 2.0 上下文的名字叫 "webgl2" ,WebGL 1.0 上下文的名字叫"webgl1" 。如果浏览器不支持 WebGL,则尝试访问 WebGL 上下文会返回 null 。在使用上下文之前,应该先检测返回值是否存在:

let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {
  let gl = drawing.getContext("webgl");
  if (gl){
  //  使用 WebGL
  }
}

webgl同样可以调用getContext()方法获取上下文的一些选项,可以直接传入一个option对象。

webgl只能绘制三种形状:点、先和三晓静。其他形状必须通过这三种基本形状在3D空间组合绘制。