Canvas从入门到实战


Canvas从入门到实战

文章插图
 
1、什么是Canvas?
html5 提供Canvas API , 其本质上是一个DOM元素 , 可以看成是浏览器提供一块画布供我们在上面渲染2D或者3D图形 。由于3D绘制上下文(webgl)目前在很多浏览器上兼容性较差 , 所以我们一般用于绘制2D图形 。
2、为什么使用Canvas?
canvas是HTML5引入的标签 , 在此之前我们通常会使用SVG来绘制一些图形 , 那么两者之间有什么区别呢?SVG可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言XML描述的2D图形的语言 , 两者部分区别:
 
  • SVG 图像是使用各种元素创建的 , 这些元素分别应用于矢量图像的结构、绘制与布局;而Canvas本身并不描述图像 , 而是通过JAVAscript完成绘制;
  • 如上所述 , SVG本身是DOM元素 , 每一个描述元素也是DOM元素 , 浏览器在进行渲染时需要进行大量计算以处理每一个元素;而在渲染Canvas的过程中 , 浏览器只需要渲染一张画布 , 其余的是通过JavaScript引擎执行逻辑来绘制;
  • SVG(矢量图)不依赖分辨率 , 放大不会失真;而Canvas(位图)依赖分辨率 , 放大会失真;
 
由于Canvas是通过Javascript来完成绘制的 , 所以可控性很强 , 我们可以比较精确的控制图形渲染的每一帧;从另一方面来说 , 如果在高频率渲染中要处理过多的DOM元素就意味着性能一定不会太好 , 渲染速度会下降很多 。Canvas的高性能能够保障复杂场景中图形的渲染效率 , 所以目前很多领域都会使用Canvas , 例如动画、游戏图形、数据可视化、照片处理和实时视频处理等 。
3、Canvas的基本使用
要使用Canvas , 我们需要先获取Canvas元素的引用继而通过getContext()方法获取图形的绘制上下文 。
const canvas = document.getElementById('canvas')const ctx = canvas.getContext('2d')
获取到图形绘制上下文后 , 我们就能使用CanvasRenderingContext2D接口上的绘图API了 , 接下来我们可以了解一些比较常规的使用 。
3.1、画布属性:
 
  • width、height:画布的宽度以及高度 , 默认大小为300x150;
  • fillStyle:填充图形的样式 , 值可以是color string、CanvasGradient对象;
  • strokeStyle:轮廓图形的样式 , 值可以是color string、CanvasGradient对象;
  • lineWidth:绘制线条的宽度;
  • globalAlpha:画布的透明度 , 0-1的偏移值;
  • globalCompositeOperation:画布中新老图形重叠时的渲染方式 , 默认为source-over , 新图形覆盖老图形;
  •  
ctx.width = 300ctx.height = 300ctx.fillStyle = '#fff'ctx.strokeStyle = 'blue'ctx.lineWidth = 5ctx.globalAlpha = 0.3ctx.globalCompositeOperation = 'destination-out' // 新老图形重叠部分变透明 
3.2、绘制图形:
 
  • .fillRect(x,y,width,height):绘制一个填充的矩形 , 矩形左上角的坐标为(x,y) , 高宽分别为width、height;
  • .strokeRect(x,y,width,height):绘制一个矩形边框 , 矩形左上角的坐标为(x,y) , 高宽分别为width、height;
  • .clearRect(x,y,width,height):清除指定矩形区域 , 让清除部分完全透明;
ctx.fillStyle = 'red'ctx.fillRect(100,100,100,100)ctx.strokeStyle = 'blue'ctx.strokeRect(200,200,100,100)ctx.clearRect(125,125,50,50)ctx.strokeRect(130,130,40,40) 
Canvas从入门到实战

文章插图
 
3.3、绘制路径:
 
  • .beginPath():开始一段路径的绘制;
  • .closePath():从起始点到当前点 , 结束路径的绘制 , 非必需;
  • .fill():根据路径生成填充图形;
  • .stroke():通过路径生成轮廓图形;
  • .moveTo(x,y):声明一段路径的起始点;
  • .l.NETo(x,y):绘制一条从当前坐标到(x,y)的线;
ctx.beginPath()ctx.moveTo(50,50)ctx.lineTo(100,100)ctx.lineTo(100,0)ctx.fill()ctx.beginPath()ctx.moveTo(110,100)ctx.lineTo(150,100)ctx.lineTo(150,200)ctx.lineTo(110,200)ctx.closePath() // 轮廓图形不会根据从当前坐标到起始坐标生成轮廓 , 所以需要闭合路径ctx.stroke()


推荐阅读