「JavaScript深入」Canvas 全面指南

Canvas 是 HTML5 引入的一个用于绘制图形的元素,通过 JavaScript 可以动态地在网页上绘制和操作图像、图形、动画等。Canvas 提供了一块可编程的位图区域,开发者可以通过绘图上下文对其进行绘制


1. Canvas 基础概念

什么是 Canvas?

HTML5 提供了 canvas元素,这是一个空白的矩形区域,可以使用 JavaScript 在上面绘制图形、图像和文本

<canvas id="myCanvas" width="500" height="300"></canvas>

获取 Canvas 绘图上下文

要在 Canvas 上绘图,首先需要获取绘图上下文(context)。Canvas 支持不同的绘图上下文类型:

  • 2D 上下文 (CanvasRenderingContext2D):用于绘制 2D 图形,支持路径绘制、填充、描边、文本绘制、图像处理等。
  • WebGL (WebGLRenderingContext):用于 3D 图形渲染,基于 OpenGL ES。

示例:获取 2D 上下文

<canvas id="myCanvas" width="500" height="300"></canvas>
<script>
  const canvas = document.getElementById("myCanvas");
  const ctx = canvas.getContext("2d"); // 获取 2D 绘图上下文
</script>

2. 基本绘图操作

绘制矩形

ctx.fillStyle = "red"; // 设置填充颜色
ctx.fillRect(50, 50, 100, 100); // 绘制填充矩形

ctx.strokeStyle = "blue"; // 设置描边颜色
ctx.strokeRect(200, 50, 100, 100); // 绘制描边矩形

👇 效果
在这里插入图片描述

绘制路径(线段)

ctx.beginPath(); // 开始路径
ctx.moveTo(50, 200); // 起点
ctx.lineTo(150, 250); // 第一条线
ctx.lineTo(250, 200); // 第二条线
ctx.closePath(); // 关闭路径
ctx.stroke();  // 绘制路径

👇 效果
在这里插入图片描述

绘制圆形

ctx.beginPath();
ctx.arc(150, 150, 50, 0, Math.PI * 2);  // 绘制一个圆弧路径
ctx.fill(); // 填充路径

ctx.arc(150, 150, 50, 0, Math.PI * 2)

  • 绘制一个圆弧路径。
  • 150, 150:圆心的坐标(x, y)。
  • 50:圆的半径。
  • 0:起始角度(弧度制),0表示从3点钟方向开始。
  • Math.PI * 2:结束角度,Math.PI * 2表示完整的360度,即一个完整的圆。

👇 效果
在这里插入图片描述


3. 图像与文本绘制

绘制图片

Canvas 可以绘制图片,通过 drawImage 方法将图片绘制到 Canvas 上

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.src = 'http://gips1.baidu.com/it/u=1658389554,617110073&fm=3028&app=3028&f=JPEG&fmt=auto'; // 替换为实际图像 URL
img.onload = () => {
  // 绘制原始大小
  ctx.drawImage(img, 0, 0);
  
  // 绘制缩放后的图片
  ctx.drawImage(img, 50, 50, 128, 96);  // (image, x, y, width, height)
};

👇 效果

在这里插入图片描述

绘制文本

通过 fillTextstrokeText 方法,可以在 Canvas 上绘制文本。

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

// 设置字体
ctx.font = "30px Arial";
ctx.fillStyle = '#FF0000';
ctx.fillText("Hello, Canvas!", 50, 50);
ctx.strokeText("Outlined Text", 50, 100);

👇 效果
在这里插入图片描述


4. Canvas 动画

基础动画实现

Canvas 动画通常通过 requestAnimationFrame 进行帧更新。

requestAnimationFrame 周期内,通过清除先前的 Canvas 内容并绘制新内容,可以实现流畅的动画效果

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
let posX = 0;
const posY = 150;

function animate() {
  // 清除画布
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // 绘制移动的方块
  ctx.fillStyle = '#FF5733';
  ctx.fillRect(posX, posY, 50, 50);
  // 更新位置
  posX  += 2;
  // 重置位置
  if (posX > canvas.width) posX = -50; 
  // 循环调用
  requestAnimationFrame(animate);
}
animate();  // 启动动画

5. Canvas 性能优化

在使用 Canvas 进行绘图和动画时,性能优化尤为重要,尤其是在处理复杂图形和高频率动画时

1. 减少重绘次数

尽量只更新变化部分,避免整屏重绘。

使用 requestAnimationFrame 来协调动画更新,避免不必要的渲染。

function draw() {
  // 仅在需要时重绘
  if (needsRedraw) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // 执行绘图操作
    needsRedraw = false;
  }
  requestAnimationFrame(draw);
}

2. 使用离屏 Canvas

利用离屏 Canvas 进行预绘,然后将结果绘制到主 Canvas 上,减少主线程的计算压力,提升渲染效率

// 创建离屏 Canvas
const offscreenCanvas = document.createElement("canvas");
const offCtx = offscreenCanvas.getContext("2d");

// 在离屏 Canvas 上绘制
offCtx.fillStyle = 'red';
offCtx.fillRect(0, 0, 100, 100);

// 将离屏 Canvas 的内容绘制到主 Canvas
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
ctx.drawImage(offscreenCanvas, 50, 50);

3. 使用多个层 Canvas

将复杂的静态背景和动态元素分层绘制,可以减少需要频繁更新的绘图区域,提升整体渲染效率

<div style="position: relative;">
  <!-- 静态背景 Canvas -->
  <canvas id="bgCanvas" width="600" height="400" style="position: absolute; z-index: 0;"></canvas>
  <!-- 动态元素 Canvas -->
  <canvas id="fgCanvas" width="600" height="400" style="position: absolute; z-index: 1;"></canvas>
</div>

<script>
  const bgCanvas = document.getElementById('bgCanvas');
  const bgCtx = bgCanvas.getContext('2d');

  // 绘制静态背景
  bgCtx.fillStyle = '#EEEEEE';
  bgCtx.fillRect(0, 0, bgCanvas.width, bgCanvas.height);

  const fgCanvas = document.getElementById('fgCanvas');
  const fgCtx = fgCanvas.getContext('2d');
  let posX = 0;
  const posY = 200;

  function animate() {
    fgCtx.clearRect(0, 0, fgCanvas.width, fgCanvas.height);
    fgCtx.fillStyle = '#FF0000';
    fgCtx.fillRect(posX, posY, 50, 50);
    posX += 2;
    if (posX > fgCanvas.width) posX = -50;
    requestAnimationFrame(animate);
  }

  animate();
</script>

6. Canvas VS SVG

SVG(Scalable Vector Graphics)是一种用来描述二维矢量图形的XML格式。它是一种基于文本的图像格式,支持交互和动画,广泛用于网页设计和开发中。在选择 Canvas 或 SVG 技术进行项目开发时,需要考虑到它们各自的特性、适用场景和项目需求

  • Canvas 是基于像素的技术,适用于生成即时图形,在处理大量对象(如游戏中的图形)时,Canvas 通常表现得更好,因为它直接操作位图。但每次绘制都是对整个 Canvas 的再绘制,无法直接对单个元素进行操作
  • SVG 是矢量图形技术,缩放时不会失去清晰度,适合高保真度的图像展示,每个元素都是独立可操作的 DOM 元素,可以添加事件、样式和脚本,但对于复杂图形,DOM 节点数可能较大
特性CanvasSVG
绘制方式基于像素的位图绘制基于矢量的图形绘制
适用场景高性能实时渲染、大量动态图形、游戏等需要可缩放、交互性高的静态图形、复杂的布局与样式
DOM 结构单一 <canvas>,绘图内容不在 DOM 中每个元素都是 DOM 节点,易于操作和样式化
性能适合大量图形和高频率更新,性能较高动态元素较多时性能可能下降,特别是复杂的 SVG 图形
可访问性需要额外处理,默认不可访问元素可被屏幕阅读器等辅助技术识别,具备更好的可访问性
可缩放性失真适用于缩放
动画与交互需要手动实现动画和交互逻辑支持 CSS 动画、SVG 动画和事件处理

如何选择?

  • 动态动画(游戏、数据可视化)➡ Canvas
  • 可缩放的矢量图(图标、交互 UI)➡ SVG

本文提供了 Canvas 的核心知识点、基础绘图、动画处理及优化技巧。希望对你有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

八了个戒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值