数据可视化系列之 Canvas 手册

351 阅读5分钟

pexels-mark-g-1057309-2401539.jpg

在 HTML5 中,<canvas>元素为 Web 开发带来了无限的可能性,它允许开发者使用 JavaScript 在网页上绘制图形、动画和复杂的视觉内容。本教程将从基础概念出发,深入探讨 Canvas 的使用方法,引导你一步步掌握 Canvas 的绘图技巧。

Canvas 简介

什么是 Canvas?

  • Canvas 是一个 HTML 元素,用于通过脚本(通常是 JavaScript)动态创建图形。
  • canvas 是一个二维网格, canvas 的左上角坐标为 (0,0)

Canvas 的特点

  • 动态绘图:可以使用 JavaScript 在 Canvas 上绘制图形。
  • 像素控制:提供了对像素级别的控制。
  • 动画支持:适合创建动画效果。
  • 硬件加速:可以利用 GPU 加速图形渲染。

Canvas 基础

创建 Canvas 元素

在 HTML 中,可以通过以下方式创建 Canvas 元素:

<!DOCTYPE html>
<html>
  <head>
    <title>Canvas Tutorial</title>
  </head>
  <body>
    <canvas id="myCanvas" width="500" height="500" style="border:1px solid #000000;">
      您的浏览器不支持HTML5 Canvas。
    </canvas>
    <script src="canvas.js"></script>
  </body>
</html>

绘制图形

  • 要绘制图形,首先需要获取 Canvas 元素的上下文(context),然后使用该上下文绘制图形。
  • getContext("2d")对象是内建的 HTML5 对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。
// canvas.js
window.onload = function () {
  var canvas = document.getElementById('myCanvas')
  var ctx = canvas.getContext('2d')
}

Canvas 图形绘制

绘制矩形

使用fillRectclearRect方法绘制和清除矩形。

  • 在画布上绘制 100x100 的矩形,从左上角开始 (10,10)。
// canvas.js
ctx.fillStyle = '#FF0000'
ctx.fillRect(10, 10, 100, 100)

ctx.clearRect(20, 20, 80, 80)

绘制圆形

使用arc方法绘制圆形。 使用 stroke() 或者 fill() 来绘制圆

  • 语法:arc(x,y,r,start,stop)
// canvas.js
ctx.beginPath()
ctx.arc(150, 75, 50, 0, 2 * Math.PI)
ctx.fill()

绘制线条

使用moveTolineTostroke方法绘制线条。

  • moveTo(x,y) 定义线条开始坐标
  • lineTo(x,y) 定义线条结束坐标
  • 定义开始坐标(10,10), 和结束坐标 (150,150)。然后使用 stroke() 方法来绘制线条:
// canvas.js
ctx.beginPath()
ctx.moveTo(10, 10)
ctx.lineTo(150, 150)
ctx.stroke()

绘制路径

使用路径方法绘制复杂的图形。

// canvas.js
ctx.beginPath()
ctx.moveTo(20, 20)
ctx.lineTo(100, 20)
ctx.lineTo(100, 100)
ctx.closePath()
ctx.fill()

Canvas 样式和颜色

设置颜色和渐变

  • 使用fillStylestrokeStyle设置填充和描边颜色
  • 使用createLinearGradientcreateRadialGradient创建渐变。
    • createLinearGradient(x,y,x1,y1) - 创建线条渐变
    • createRadialGradient(x,y,r,x1,y1,r1) - 创建一个径向/圆渐变
    • 当我们使用渐变对象,必须使用两种或两种以上的停止颜色
    • addColorStop()方法指定颜色停止,参数使用坐标来描述,可以是 0 至 1.
// canvas.js
var linearGradient = ctx.createLinearGradient(0, 0, 0, 150)
linearGradient.addColorStop(0, '#FF0000')
linearGradient.addColorStop(1, '#0000FF')
ctx.fillStyle = linearGradient
ctx.fillRect(10, 120, 150, 150)

设置线型

使用lineWidthlineCaplineJoin设置线条样式。

// canvas.js
ctx.lineWidth = 5
ctx.lineCap = 'round'
ctx.lineJoin = 'bevel'

Canvas 变换

变换基础

Canvas 支持平移、缩放、旋转等变换操作。

  • save() 保存当前环境的状态。
  • restore() 返回之前保存过的路径状态和属性。
// canvas.js
ctx.save()

ctx.scale(2, 2)
ctx.rotate(Math.PI / 4)
ctx.translate(100, 100)

ctx.restore()

综合变换示例

将多个变换操作应用于绘制图形。

  • scale() 缩放当前绘图至更大或更小。
  • rotate() 旋转当前绘图。
  • translate() 重新映射画布上的 (0,0) 位置。
  • transform() 替换绘图的当前转换矩阵。
// canvas.js
ctx.save()
ctx.translate(150, 150)
ctx.rotate(Math.PI / 4)
ctx.scale(0.5, 0.5)
ctx.fillRect(-50, -50, 100, 100)
ctx.restore()

Canvas 文本

绘制文本

使用fillTextstrokeText方法绘制文本。

  • font - 定义字体
  • fillText(text,x,y) - 在 canvas 上绘制实心的文本
  • strokeText(text,x,y) - 在 canvas 上绘制空心的文本
// canvas.js
ctx.font = '30px Arial'
ctx.fillStyle = '#FF0000'
ctx.fillText('Hello, Canvas', 50, 100)

ctx.strokeStyle = '#000000'
ctx.strokeText('Hello, Canvas', 50, 150)

文本样式

设置文本的对齐、基线等样式。

// canvas.js
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText('Centered Text', 150, 200)

Canvas 图像处理

绘制图像

使用drawImage方法在 Canvas 上绘制图像。

  • drawImage(image,x,y)
// canvas.js
var img = new Image()
img.onload = function () {
  ctx.drawImage(img, 10, 10)
}
img.src = 'path/to/image.png'

图像变换

对图像进行缩放、裁剪等变换操作。剪切图像,并在画布上定位被剪切的部分:

  • context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
// canvas.js
ctx.drawImage(img, 0, 0, img.width / 2, img.height / 2, 10, 10, 100, 100)

创建图像数据

使用createImageDatagetImageData方法操作像素数据。

  • getImageData() 返回 ImageData 对象,该对象为画布上指定的矩形复制像素数据。
  • putImageData() 把图像数据(从指定的 ImageData 对象)放回画布上。
// canvas.js
var imageData = ctx.createImageData(100, 100)
// 操作图像数据...
ctx.putImageData(imageData, 10, 10)

Canvas 动画

动画基础

通过定期更新 Canvas 内容来创建动画。

// canvas.js
var x = 10,
  y = 10

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height)

  ctx.fillStyle = '#0095DD'
  ctx.fillRect(x, y, 50, 50)

  x += 2
  y += 2

  if (x + 50 < canvas.width && y + 50 < canvas.height) {
    requestAnimationFrame(draw)
  }
}

requestAnimationFrame(draw)

复杂动画示例

结合变换和动画,创建更复杂的动画效果。

// canvas.js
var angle = 0

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height)

  ctx.save()
  ctx.translate(canvas.width / 2, canvas.height / 2)
  ctx.rotate(angle)
  ctx.beginPath()
  ctx.moveTo(50, -50)
  ctx.lineTo(-50, -50)
  ctx.closePath()
  ctx.stroke()
  ctx.restore()

  angle += 0.01
  requestAnimationFrame(draw)
}

requestAnimationFrame(draw)

实践案例

Canvas 绘制折线图表

性能优化

  • 层(Layers):使用多个 Canvas 层来优化绘制性能。
  • 缓存(Caching):缓存复杂的图形以避免重复绘制。

Canvas 第三方库

虽然原生 Canvas 提供了强大的功能,但使用第三方库可以简化开发流程,并提供额外的工具和功能。

  • Fabric.js:提供交互式对象和丰富的图形功能。
  • Konva.js:一个 2D Canvas 库,用于创建交互式 2D 图形。
  • EaselJS:专注于游戏开发,提供显示对象和动画支持。

结语

Canvas 作为一个强大的绘图工具,为 Web 前端开发提供了丰富的视觉表现力。从基础图形绘制到复杂的动画制作,Canvas 都能轻松应对。通过本教程的学习,你应该已经对 Canvas 有了深入的了解,并且能够开始在项目中应用 Canvas 技术。随着实践的深入,你将能够发掘 Canvas 更多的潜力,创造出令人惊叹的视觉效果。