Canvas | 使用直线绘制一个朴实无华、日趋圆滑的等边N边形

281 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

昨天学习了使用 Canvas 绘制直线(文章链接:Canvas学习笔记(一)入门示例 —— 绘制直线)。

今天笔者自己脑动了个场景 —— 使用直线绘制等边多边形,巩固昨天学习的知识。

先来看下效果:

20221028-canvas.gif

声明 Canvas DOM 元素

<canvas id="canvas" width="500" height="500" style="border: 1px dashed #333333"></canvas>

因为要绘制的是等边多边形,所以笔者这里定义的是一个500 * 500的正方形画布。

获取 Canvas 对象 & 上下文环境对象 & Canvas 的宽度和高度

// 1、获取 Canvas 对象
var canvas = document.getElementById("canvas");
// 2、获取上下文环境对象
var ctx = canvas.getContext("2d");
// 获取Canvas的宽度和高度
var width = canvas.width;
var height = canvas.height;

运用昨天学习的知识获取Canvas 对象、上下文环境对象、Canvas 的宽度和高度。Canvas 的宽度和高度在后面会用来清除之前绘制的图形。

定义全局变量

// 圆心
var basePoint = {
  x: 250,
  y: 250,
};
// 半径长度
var radius = 150;
// 多边形的起始边的个数
var num = 3;

全局变量中笔者定义了圆心、半径长度、多边形的起始边的个数。

根据角度生成一个包含坐标位置的点

/**
 * 根据角度生成一个包含坐标位置的点
 */
function createPoint(angle) {
  return {
    x:
      basePoint.x +
      Math.round(radius * Math.cos((angle * Math.PI) / 180)),
    y:
      basePoint.y +
      Math.round(radius * Math.sin((angle * Math.PI) / 180)),
  };
}

使用正弦函数、余弦函数、角度、半径长度计算终点坐标,之后对终点坐标值进行了四舍五入处理。

绘制多边形

function draw() {
  // 清除之前绘制的图形
  ctx.clearRect(0, 0, width, height);

  // 起点
  var startPoint = {
    x: basePoint.x + radius,
    y: basePoint.y,
  };

  ctx.beginPath();
  // 将画笔移动到起点位置
  ctx.moveTo(startPoint.x, startPoint.y);
  // 循环绘制第N条直线
  for (var i = 0; i < num; i++) {
    var point = createPoint((360 / num) * (i + 1));
    ctx.lineTo(point.x, point.y);
  }
  ctx.stroke();
}

绘制多边形步骤:

  1. 清除之前绘制的图形;
  2. 将画笔移动到起点位置;
  3. 开始绘制多边形

以三角形为例。绘制第一条线对应的角度是120度;第二条线对应的角度是240度;第三条线对应的角度是360度。

定时执行绘制方法,依次绘制正三角形、正方形、等边五边形……

var t = setInterval(function () {
  if (num > 30) {
    clearInterval(t);
  }
  draw();
  num = num + 1;
}, 1000);

这里我们最多绘制了等边30边形就停止绘制了。当 n 足够大时,绘制的图形接近于圆形。

完整代码

完整代码笔者已经在码上掘金上发布,如果有兴趣可以自行查看。

好了,一个朴实无华的等边多边行就画好了。

问题

在编写本篇文章的过程中,笔者遇到一个问题:Canvas 使用clearRect()方法无法清除上一次绘制的图形。

查阅资料后笔者找到的解决方案是:在开始绘制图形前先调一下beginPath()方法。