heart--canvas

使用canvas在鼠标点击处 绘制图形

by Evermenot

HTML

<canvas></canvas>

CSS

* {
  margin: 0;
  padding: 0;
}

JavaScript

(function(win) {
  let Heart = function(ctx, x, y, size) {
    this.ctx = ctx;
    this.x= x;
    this.y = y;
    this.size = size;
    this.vertices = getVector();

    function getVector() {
      let vertices = [];

      // console.log(this == win) //true
      for(let i = 0; i < 50; i++) {
        let step = i/50 * (Math.PI * 2);
        let vector = {
          x : size * (16 * Math.pow(Math.sin(step), 3)),
          y : size * (13 * Math.cos(step) - 5 * Math.cos(2 * step) - 2 * Math.cos(3 * step) - Math.cos(4 * step))
        }
        vertices.push(vector);
      }

      return vertices;
    };
  }

  Heart.prototype.draw = function() {
    /* 期望效果:
            *     在鼠标点击位置绘制图形
            *
            * 错误做法:                (引以为戒。。。)
            *     使用canvas API中的translate,分别以鼠标点击位置的offsetX、offsetY为画布坐标的水平和竖直方向的偏移量,绘制图形,但实际效果和预期完全不太一样(大哭~~~)
            *
            * 错误原因:
            *     translate是以上个坐标原点为基础,进行平移             (原谅我的无知~~~~~)
            *
            * 解决问题:
            *     在开始绘制前,将当前状态使用save()保存下来,并在每一次绘制结束之后,使用restore()将状态重置,以免影响下次点击
            *
            * 最后吐槽下:
            *     有很多文章在介绍相同效果的绘制,但是真的有自测过吗。。。
            */
    this.ctx.save();
    this.ctx.beginPath();
    this.ctx.translate(this.x, this.y);
    this.ctx.rotate(Math.PI);

    let vertices = this.vertices
    for(let i = 0; i < vertices.length; i++) {
      let vector = vertices[i];
      this.ctx.lineTo(vector.x, vector.y);
    }

    // this.ctx.fillStyle = '#ccc';
    // this.ctx.fill();

    this.ctx.strokeStyle = "#ccc";
    this.ctx.stroke();
    this.ctx.closePath();

    this.ctx.restore();
  };
  win.Heart = Heart;

})(window)

let canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

let ctx = canvas.getContext('2d');
canvas.onclick = function(e) {
  let size = 6;
  let x = e.offsetX;
  let y = e.offsetY;
  let heart = null;
  heart = new Heart(ctx, x, y, size);
  heart.draw();
}