关于canvas:Canvas-入门指南

5次阅读

共计 4681 个字符,预计需要花费 12 分钟才能阅读完成。

mdn 文档

canvas 能够用于动画、游戏画面、数据可视化、图片编辑以及实时视频解决等内容。

canvas api 次要聚焦于 2D 图形。

WebGL api 次要聚焦于硬件加速的 2D 和 3D 图形。

先来看一个根底事例:

<canvas id="canvas">
    Your browser not support canvas, please update browser.
</canvas>

<script>
  function draw() {
    // 获取 canvas 元素
    const canvas = document.getElementById('canvas');
    // 创立画板
    const context = canvas.getContext('2d');

    // 填充形态
    context.fillRect(10, 10, 55, 50);
    // 填充色彩
    context.fillStyle = 'black';
  }
  
  draw();
</script>

这时,浏览器会呈现一个彩色的方块:

绘制图形

首先学习如何绘制矩形。

绘制矩形

canvas 提供了 3 种办法来绘制矩形:

  1. fillRect(x, y, width, height): 绘制了一个填充的矩形;
  2. strokeRect(x, y, width, height): 绘制了一个矩形的边框;
  3. clearRect(x, y, width, height): 分明指定矩形区域,让分明局部齐全通明;
  4. rect(x, y, width, height): 矩形门路

应用以上三个办法构建一个空心矩形:

function draw() {const canvas = document.getElementById('canvas');
    const context = canvas.getContext('2d');

    context.fillRect(25, 25, 100, 100);
    context.clearRect(50, 50, 50, 50);
}

draw();

如图下所示:

绘制门路

绘图的根本元素是门路。

门路:通过不同色彩和宽度的线段或曲线相连造成的不同形态的点的汇合

一下是所须要的函数:

  1. beginPath(): 新建一条门路,生成之后,图形绘制命令被指向到门路上生成门路;
  2. closePath(): 闭合门路之后图形绘制命令又从新指向到上下文中;
  3. stroke(): 通过线条来绘制图形轮廓;
  4. fill(): 通过填充门路的内容区域生成实心的图形了;

用以上的办法来构建一个矩形:

function draw() {const canvas = document.getElementById('canvas');
    const context = canvas.getContext('2d');

    context.beginPath();
    context.moveTo(100, 100);
    context.lineTo(100, 0);
    context.lineTo(0, 0);
    context.lineTo(0, 100);
    context.fill();}

draw();

生成门路:

  1. beginPath(): 实质上,门路是由很多子门路形成,这些子门路都是在一个列表中,所有的子门路来形成图形。每次调用这个办法,列表都会清空,而后就能够从新绘制新的图形了;
  2. moveTo(): 设置门路之后,指定起始地位;
  3. lineTo(): 调用函数 绘制门路;
  4. closePath(): 闭合门路(非必须),在调用 fill() 函数时,所有没有闭合的形态都会主动闭合。

挪动笔

moveTo(): 从画布上的一个点挪动到另外一个点。

绘制直线

应用 lineTo(x, y) 办法:从以后地位到 (x, y) 的领导地位的线段。

绘制圆弧

  1. arc(x, y, radius, startAngle, endAngle, anticlockwise): 画一个以 (x, y) 为圆心的以 radius 为半径的圆弧 / 园。从 startAngle 开始,到 endAngle 完结,依照 anticlockwise 给定的方向。
  2. arcTo(x1, y1, x2, y2, radius): 依据给定的控制点和半径画一段圆弧,再以直线链接两个控制点。

arc() 函数中,示意角度的单位是弧度,不是角度。

角度转弧度的公式为:弧度 = 角度 * (π/ 180)

应用以上办法,画一个实心圆:

function draw() {const canvas = document.getElementById('canvas');
    const context = canvas.getContext('2d');

    context.beginPath();
    context.moveTo(50, 50);

    context.arc(50, 50, 25, 0, 2 * Math.PI, true);
    context.fill();}

draw();

如图下所示:

Path2D

为了简化代码以及进步性能,咱们能够应用 Path2D 用来缓存或者记录绘画命令。

来试验一下,来画一个内切圆:

function draw() {const canvas = document.getElementById('canvas');
    const context = canvas.getContext('2d');

    const rectangle = new Path2D();
    rectangle.rect(0, 0, 100, 100);

    const circle = new Path2D();
    circle.moveTo(50, 50);
    circle.arc(50, 50, 50, 2 * Math.PI, false);

    context.stroke(rectangle);
    context.stroke(circle);
}

draw();

SVG Path

能够应用 svg path data 来初始化 canvas 下面的门路

到当初为止,咱们能够应用一系列门路来将咱们所须要的图形,绘画在画布下面了。大体上的步骤如下:

  1. 创立画布
  2. 开始门路
  3. 设置初始点
  4. 绘画门路
  5. 闭合门路

示例

接下来,就通过下面学习到的常识来画一个简略的柱状图:

轴线

生成轴线:

// 坐标轴生成
createAxle(type = 'x') {const {point, axleLength} = this.defaults;

  const axle = new Path2D();
  axle.moveTo(...point);

  if (type === 'x') {axle.lineTo(point[0] + axleLength, point[1]);
  } else {axle.lineTo(point[0], point[1] - axleLength);
  }

  this.context.stroke(axle);
}

刻度

生成刻度:

// 生成刻度
createScale(type = 'x') {const {point, count, axleLength, scaleLength} = this.defaults;
  const ruleWidth = parseInt(axleLength / count, 10);

  const scale = new Path2D();

  for (let i = 0; i <= axleLength; i += ruleWidth) {if (type === 'x') {scale.moveTo(point[0] + i, point[1]);
      scale.lineTo(point[0] + i, point[1] + scaleLength);
    } else {scale.moveTo(point[0], point[1] - i);
      scale.lineTo(point[0] - scaleLength, point[1] - i);
    }
  }

  this.context.stroke(scale);
}

画出柱状图

最初一步,咱们就要画出柱状图的要害,柱子了。

// 画柱状图
createRect() {const {point, axleLength, count} = this.defaults;
  const rectLength = parseInt(axleLength / count, 10);

  const rect = new Path2D();
  for (let i = 0; i <= count; i += 1) {
    rect.rect(point[0] + (rectLength * i),
      point[1],
      rectLength,
      -rectLength * i
    );
  }

  this.context.fill(rect);
}

残缺代码

class LineChart {constructor(config) {const canvas = document.getElementById('canvas');
        this.context = canvas.getContext('2d');

        this.defaults = {point: [50, 120],
            axleLength: 100,
            count: 5,
            scaleLength: 5
        };

        Object.assign(this.defaults, config);
    }

    // 坐标轴生成
    createAxle(type = 'x') {const {point, axleLength} = this.defaults;

        const axle = new Path2D();
        axle.moveTo(...point);

        if (type === 'x') {axle.lineTo(point[0] + axleLength, point[1]);
        } else {axle.lineTo(point[0], point[1] - axleLength);
        }

        this.context.stroke(axle);
    }

    // 坐标标尺
    createScale(type = 'x') {const {point, count, axleLength, scaleLength} = this.defaults;
        const ruleWidth = parseInt(axleLength / count, 10);

        const scale = new Path2D();

        for (let i = 0; i <= axleLength; i += ruleWidth) {if (type === 'x') {scale.moveTo(point[0] + i, point[1]);
                scale.lineTo(point[0] + i, point[1] + scaleLength);
            } else {scale.moveTo(point[0], point[1] - i);
                scale.lineTo(point[0] - scaleLength, point[1] - i);
            }
        }

        this.context.stroke(scale);
    }

    // 画柱状图
    createRect() {const {point, axleLength, count} = this.defaults;
        const rectLength = parseInt(axleLength / count, 10);

        const rect = new Path2D();
        for (let i = 0; i <= count; i += 1) {
            rect.rect(point[0] + (rectLength * i),
                point[1],
                rectLength,
                -rectLength * i
            );
        }

        this.context.fill(rect);
    }

    draw() {this.createAxle('x');
        this.createAxle('y');

        this.createScale('x');
        this.createScale('y');

        this.createRect();}
}

const lineChart = new LineChart();

lineChart.draw();

后果如下所示:

剩下的工作还有一些,之后在更新吧!

  • [] 丑化这个柱状图啊,当初这个太黑了
  • [] 标上刻度
  • [] 依据数据来对柱子进行调节
正文完
 0