canvas 使折线变顺滑

50 阅读1分钟

将折线变顺滑,其实一共就两步:获取点的集合-使用贝塞尔曲线将点连起来

  1. 获取点的集合

    使折线变顺滑,首先要确定这条折线上的点,拿到这条线上点的集合,再把它们转化为可以用贝塞尔曲线来连接起来的点的集合,如下函数:
// 使曲线顺滑
    makeSmoothCurveLine(points) {
      const arr = [];
      points.forEach((point, i) => {
        if (i !== 0) {
          const [A, B] = this.getCtrlPoint(i - 1, points);
          arr.push([A.x, A.y, B.x, B.y, point.x, point.y]);
        }
      });
      return arr;
    }
    /**
     * 获取 模拟贝塞尔曲线关键控制点
     */
    getCtrlPoint(i, points, a = 0.168, b = 0.168) {
      let x0;
      let y0;
      let x1;
      let y1;

      if (points[i].x === points[i + 1].x || points[i].y === points[i + 1].y) {
        a = 0;
        b = 0;
      }

      if (i < 1) {
        x0 = points[0].x + (points[1].x - points[0].x) * a;
        y0 = points[0].y + (points[1].y - points[0].y) * a;
      } else {
        x0 = points[i].x + (points[i + 1].x - points[i - 1].x) * a;
        y0 = points[i].y + (points[i + 1].y - points[i - 1].y) * a;
      }

      if (i > points.length - 3) {
        const last = points.length - 1;
        x1 = points[last].x - (points[last].x - points[last - 1].x) * b;
        y1 = points[last].y - (points[last].y - points[last - 1].y) * b;
      } else {
        x1 = points[i + 1].x - (points[i + 2].x - points[i].x) * b;
        y1 = points[i + 1].y - (points[i + 2].y - points[i].y) * b;
      }

      return [
        {
          x: x0,
          y: y0
        },
        {
          x: x1,
          y: y1
        }
      ];
    }
  1. 在canvas中使用贝塞尔曲线函数将这些点连接起来

 // 绘制线条
    drawCurve() {
      const canvas = document.querySelector('#creative-bar-chart-line');
      if (!canvas) {
        return;
      }
      canvas.width = this.boxWidth;
      canvas.height = this.boxHeight;
      this.ctx = canvas.getContext('2d');
      this.ctx.beginPath();
      this.ctx.moveTo(this.pointsAll[0].x, this.pointsAll[0].y);
      this.pointsAll.forEach(item => {
        this.ctx.bezierCurveTo(...item);
      });
      this.ctx.lineWidth = this.chartData.lineStyle.width;
      this.ctx.strokeStyle = this.chartData.lineStyle.color;
      this.ctx.stroke();
    }

到此就完成啦,不清楚其中奥妙的同学可以去了解下贝塞尔曲线~