了解下canvas?

栏目: Html5 · 发布时间: 5年前

内容简介:Canvas API 提供了通过 JavaScript 绘制图形的能力 。它广泛用于动画、游戏图形、数据可视化、照片处理和实时视频处理领域。本文将会简单介绍下 canvas 。文章的大部分内容来源于 MDN 的这就是一个 canvas 标签,看起来和普通的 html 标签没什么不同,重要的通过 canvas 标签我们可以获取其canvas 翻译过来是画布的意思,所以接下来我们会对照画布来介绍 canvas 的API。

Canvas API 提供了通过 JavaScript 绘制图形的能力 。它广泛用于动画、游戏图形、数据可视化、照片处理和实时视频处理领域。本文将会简单介绍下 canvas 。文章的大部分内容来源于 MDN 的 canvas 教程 ,想深入了解 canvas 的可以去看一下。

初识 canvas

// 栗子 1
<canvas id="tutorial" width="150" height="150"></canvas>

这就是一个 canvas 标签,看起来和普通的 html 标签没什么不同,重要的通过 canvas 标签我们可以获取其 渲染上下文 ,canvas 的所有API都通过这个渲染上下文暴露出来,以下讲解的 API 也都基于此上下文。

canvas 翻译过来是画布的意思,所以接下来我们会对照画布来介绍 canvas 的API。

var canvas = document.getElementById('tutorial');  
var ctx = canvas.getContext('2d');

绘制图形

了解下canvas?

canvas 坐标系统中,元素的左上角为坐标原点,向右下延伸坐标轴,所有图形相对于原点绘制,默认 1 网格单位对应 1 像素,比如栗子1 中的 canvas 元素就形成一个 150X150 的坐标系。 上图中的矩形坐标即为 (x, y)。

和 svg 不同,canvas 只提供了一种基本图形:矩形,不过借助路径我们可以绘制想要的任意图形。

绘制矩形

canvas 提供了三种矩形 API,我们可以通过渲染上下文获取到它们。所有 API 接受四个参数: x, y, width, height。

function draw() {  
  var canvas = document.getElementById('canvas');
  if (canvas.getContext) {
    var ctx = canvas.getContext('2d');

    ctx.fillRect(25, 25, 100, 100);
    ctx.clearRect(45, 45, 60, 60);
    ctx.strokeRect(50, 50, 50, 50);
  }
}

fillRect 和 strokeRect 分别会 “填充” 和 “描边“ 一片矩形区域。调用它们会立即绘制到画布上。

clearRect 会像橡皮擦一样清除特定的矩形区域。

结果如图:

了解下canvas?

绘制路径

路径由一系列的点组成,通过路径的组合我们可以绘制需要的任何图形。绘制一条路径步骤如下:

  1. 通过 beginPath   创建路径,并创建一个路径缓存区,当前坐标为起点。
  2. 然后通过  绘制命令  绘制路径,将绘制的 直线、弧线等存入缓存区,从而组合成图形。
  3. 最后 closePath  会在当前坐标和起点连起一条直线(可选), 最后可以 填充 或 描边 路径。

这个绘制步骤和画画差不多,落笔、描边到填充和真实世界的心智模型是相同的。其中的重头戏就是步骤2的绘制命令:

lineTo arc [bezierCurveTo()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/bezierCurveTo) 等命令分别绘制直线、弧线和贝塞尔曲线路径。而 moveTo 命令接受 x、y 两个参数,调用其会将画笔移动到指定的 x,y 坐标。

比如这里有个稍微复杂的栗子, 绘制一个吃豆人

路径复用

在吃豆人的栗子里,我们反复调用 roundedRect 函数来生成圆角矩形, canvas 提供了路径复用的方法,这就是 Path2D ,通过 Path2d 我们可以创建路径对象,调用绘制命令、甚至合并两个路径对象。以吃豆人中的圆角矩形函数为栗,使用Path2D 后的代码:

// A utility function to draw a rectangle with rounded corners.
function roundedRect(ctx, x, y, width, height, radius) {  
  const path = new Path2D();
  path.moveTo(x, y + radius);
  path.lineTo(x, y + height - radius);
  path.arcTo(x, y + height, x + radius, y + height, radius);
  path.lineTo(x + width - radius, y + height);
  path.arcTo(x + width, y + height, x + width, y + height-radius, radius);
  path.lineTo(x + width, y + radius);
  path.arcTo(x + width, y, x + width - radius, y, radius);
  path.lineTo(x + radius, y);
  path.arcTo(x, y, x, y + radius, radius);

  ctx.stroke(path);
}

加点样式?

canvas 通过状态机来保持 画笔 和 画布的状态,我们可以通过 API 来改变画笔的状态来绘制不同样式的图形。比如通过 fillStyle 和 strokeStyle 改变填充和描边的样式,通过 lineWidth 改变画笔的尺寸等。通过 createLinearGradient [createPattern(image, type)](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createPattern) 来绘制渐变色和图片背景,这里不再赘述。

文本绘制

去看原文吧

坐标轴变换

去看原文吧

加点动画?

canvas 动画的限制在于:图形绘制结束后无法再更改图形的状态(尺寸、颜色、坐标等)。这和我们熟悉的 html 元素不一样,dom 元素在渲染后还可以进行做位移、缩放等动画。由于以上原因,在 canvas 中做动画需要遵循以下步骤:

  1. 使用 clearRect 等方法清除画布
  2. 保存 canvas 的初始状态
  3. 绘制当前动画帧,这一步你可能会修改 canvas 状态
  4. 恢复 canvas 初始状态。

这里有一个 时钟动画的栗子 ,我们将不同的图形封装为对象,绘制图形时只需要调用对象的 draw 方法,这样统一了编程模型。

class Hour {  
    constructor(ctx) {
        this.ctx = ctx;
    }
    draw() {
        this.ctx.lineWidth = 14;
        this.ctx.beginPath();
        this.ctx.moveTo(-20, 0);
        this.ctx.lineTo(80, 0);
        this.ctx.stroke();
    }
}

绘制的每一帧我们会不断更新画布的状态,为了不污染下一帧的画布状态,我们需要不断调用 saverestore 来保存和回退画布状态。

这一章简单介绍了 canvas的基本知识,下篇文章会涉及 canvas 内的事件处理、碰撞检测等内容,并利用这些实现一些炫酷的效果,敬请期待。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

HTML Dog

HTML Dog

Patrick Griffiths / New Riders Press / 2006-11-22 / USD 49.99

For readers who want to design Web pages that load quickly, are easy to update, accessible to all, work on all browsers and can be quickly adapted to different media, this comprehensive guide represen......一起来看看 《HTML Dog》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

URL 编码/解码
URL 编码/解码

URL 编码/解码