悬停多个 Canvas 元素

时间:2021-02-04 13:10:36

标签: javascript canvas html5-canvas

当悬停在画布所在的块上时,应该发生一个动作,但是当我尝试显示三个元素时,为什么,然后它只对一个有效,其余的不起作用,可能是什么原因?如有任何建议,我将不胜感激。

当悬停在画布所在的块上时,应该发生一个动作,但是当我尝试显示三个元素时,为什么,然后它只对一个有效,其余的不起作用,可能是什么原因?如有任何建议,我将不胜感激。

https://jsfiddle.net/biben/qurbe0p7/1/

        let canvas, ctx;
        let render, init;
        let blob;

        class Blob {
          constructor() {
            this.points = [];
          }

          init() {
            for (let i = 0; i < this.numPoints; i++) {
              let point = new Point(this.divisional * (i + 1), this);
              // point.acceleration = -1 + Math.random() * 2;
              this.push(point);
            }
          }

          render() {
            let canvas = this.canvas;
            let ctx = this.ctx;
            let position = this.position;
            let pointsArray = this.points;
            let radius = this.radius;
            let points = this.numPoints;
            let divisional = this.divisional;
            let center = this.center;

            ctx.clearRect(0, 0, canvas.width, canvas.height);

            pointsArray[0].solveWith(pointsArray[points - 1], pointsArray[1]);

            let p0 = pointsArray[points - 1].position;
            let p1 = pointsArray[0].position;
            let _p2 = p1;

            ctx.beginPath();
            ctx.moveTo(center.x, center.y);
            ctx.moveTo((p0.x + p1.x) / 2, (p0.y + p1.y) / 2);

            for (let i = 1; i < points; i++) {
              pointsArray[i].solveWith(
                pointsArray[i - 1],
                pointsArray[i + 1] || pointsArray[0]
              );

              let p2 = pointsArray[i].position;
              var xc = (p1.x + p2.x) / 2;
              var yc = (p1.y + p2.y) / 2;
              ctx.quadraticCurveTo(p1.x, p1.y, xc, yc);
              // ctx.lineTo(p2.x, p2.y);

              ctx.fillStyle = "#000000";
              // ctx.fillRect(p1.x-2.5, p1.y-2.5, 5, 5);

              p1 = p2;
            }

            var xc = (p1.x + _p2.x) / 2;
            var yc = (p1.y + _p2.y) / 2;
            ctx.quadraticCurveTo(p1.x, p1.y, xc, yc);
            // ctx.lineTo(_p2.x, _p2.y);

            // ctx.closePath();
            ctx.fillStyle = this.color;
            ctx.fill();
            ctx.strokeStyle = "#000000";
            // ctx.stroke();

            /*
            ctx.fillStyle = '#000000';
            if(this.mousePos) {
              let angle = Math.atan2(this.mousePos.y, this.mousePos.x) + Math.PI;
              ctx.fillRect(center.x + Math.cos(angle) * this.radius, center.y + Math.sin(angle) * this.radius, 5, 5);
            }
        */
            requestAnimationFrame(this.render.bind(this));
          }

          push(item) {
            if (item instanceof Point) {
              this.points.push(item);
            }
          }

          set color(value) {
            this._color = value;
          }
          get color() {
            return this._color || "rgb(0, 147, 212)";
          }

          set canvas(value) {
            if (
              value instanceof HTMLElement &&
              value.tagName.toLowerCase() === "canvas"
            ) {
              this._canvas = canvas;
              this.ctx = this._canvas.getContext("2d");
            }
          }
          get canvas() {
            return this._canvas;
          }

          set numPoints(value) {
            if (value > 2) {
              this._points = value;
            }
          }
          get numPoints() {
            return this._points || 32;
          }

          set radius(value) {
            if (value > 0) {
              this._radius = value;
            }
          }
          get radius() {
            return this._radius || 200;
          }

          set position(value) {
            if (typeof value == "object" && value.x && value.y) {
              this._position = value;
            }
          }
          get position() {
            return this._position || { x: 0.5, y: 0.5 };
          }

          get divisional() {
            return (Math.PI * 2) / this.numPoints;
          }

          get center() {
            return {
              x: this.canvas.width * this.position.x,
              y: this.canvas.height * this.position.y,
            };
          }

          set running(value) {
            this._running = value === true;
          }
          get running() {
            return this.running !== false;
          }
        }

        class Point {
          constructor(azimuth, parent) {
            this.parent = parent;
            this.azimuth = Math.PI - azimuth;
            this._components = {
              x: Math.cos(this.azimuth),
              y: Math.sin(this.azimuth),
            };

            this.acceleration = -0.3 + Math.random() * 0.6;
          }

          solveWith(leftPoint, rightPoint) {
            this.acceleration =
              (-0.3 * this.radialEffect +
                (leftPoint.radialEffect - this.radialEffect) +
                (rightPoint.radialEffect - this.radialEffect)) *
                this.elasticity -
              this.speed * this.friction;
          }

          set acceleration(value) {
            if (typeof value == "number") {
              this._acceleration = value;
              this.speed += this._acceleration * 2;
            }
          }
          get acceleration() {
            return this._acceleration || 0;
          }

          set speed(value) {
            if (typeof value == "number") {
              this._speed = value;
              this.radialEffect += this._speed * 5;
            }
          }
          get speed() {
            return this._speed || 0;
          }

          set radialEffect(value) {
            if (typeof value == "number") {
              this._radialEffect = value;
            }
          }
          get radialEffect() {
            return this._radialEffect || 0;
          }

          get position() {
            return {
              x:
                this.parent.center.x +
                this.components.x * (this.parent.radius + this.radialEffect),
              y:
                this.parent.center.y +
                this.components.y * (this.parent.radius + this.radialEffect),
            };
          }

          get components() {
            return this._components;
          }

          set elasticity(value) {
            if (typeof value === "number") {
              this._elasticity = value;
            }
          }
          get elasticity() {
            return this._elasticity || 0.001;
          }
          set friction(value) {
            if (typeof value === "number") {
              this._friction = value;
            }
          }
          get friction() {
            return this._friction || 0.0085;
          }
        }

        init = function (cur_blob, target, target_color) {
          canvas = document.createElement("canvas");
          canvas.setAttribute("touch-action", "none");

          elem = document.getElementById(target);
          elem.appendChild(canvas);

          let resize = function () {
            // canvas.width = elem.offsetWidth;
            // canvas.height = elem.offsetHeight;
            // cur_blob.radius = canvas.width / 2.13;
            // console.log(canvas);

            canvas.width = window.innerWidth;
            if (window.innerHeight > 476) {
              canvas.height = window.innerHeight;
            } else {
              canvas.height = 476;
            }

            if (window.innerWidth > 568) {
              cur_blob.radius = 200;
            } else {
              cur_blob.radius = 140;
            }
          };
          window.addEventListener("resize", resize);
          resize();

          let oldMousePoint = { x: 0, y: 0 };
          let hover = false;

          cur_blob.color = target_color;

          let mouseMove = function (e) {
            let pos = cur_blob.center;
            let diff = { x: e.clientX - pos.x, y: e.clientY - pos.y };
            let dist = Math.sqrt(diff.x * diff.x + diff.y * diff.y);
            let angle = null;

            cur_blob.mousePos = { x: pos.x - e.clientX, y: pos.y - e.clientY };

            // console.log(cur_blob.mousePos);

            if (dist < cur_blob.radius && hover === false) {
              let vector = { x: e.clientX - pos.x, y: e.clientY - pos.y };
              angle = Math.atan2(vector.y, vector.x);
              hover = true;
            } else if (dist > cur_blob.radius && hover === true) {
              let vector = { x: e.clientX - pos.x, y: e.clientY - pos.y };
              angle = Math.atan2(vector.y, vector.x);
              hover = false;
              cur_blob.color = null;
            }

            if (typeof angle == "number") {
              let nearestPoint = null;
              let distanceFromPoint = 100;

              cur_blob.points.forEach((point) => {
                if (Math.abs(angle - point.azimuth) < distanceFromPoint) {
                  nearestPoint = point;
                  distanceFromPoint = Math.abs(angle - point.azimuth);
                }
              });

              if (nearestPoint) {
                let strength = {
                  x: oldMousePoint.x - e.clientX,
                  y: oldMousePoint.y - e.clientY,
                };
                strength =
                  Math.sqrt(strength.x * strength.x + strength.y * strength.y) * 10;
                if (strength > 100) strength = 100;
                nearestPoint.acceleration = (strength / 100) * (hover ? -1 : 1);
              }
            }

            oldMousePoint.x = e.clientX;
            oldMousePoint.y = e.clientY;

            cur_blob.color = target_color;
          };

          elem.addEventListener("pointermove", mouseMove);

          cur_blob.canvas = canvas;
          cur_blob.init();
          cur_blob.render();
        };

        blob0 = new Blob();
        blob1 = new Blob();
        blob2 = new Blob();
        init(blob0, "product-card__image-0", "#0093d4");
        init(blob1, "product-card__image-1", "#3ea934");
        init(blob2, "product-card__image-2", "#694aac");
        console.log(blob0);
        console.log(blob1);
        console.log(blob2);

0 个答案:

没有答案