简体   繁体   English

如何在画布上为 Path2D 对象设置动画

[英]How to animate Path2D objects on canvas

On my canvas I have 2 types of circles :在我的画布上,我有两种类型的圆圈:

those I created directly from the context (= decorativeStars):我直接从上下文创建的那些(=decorativeStars):

 drawDecorativeStar = (decorativeStar) => {
        this.ctx.beginPath();
        this.ctx.arc(decorativeStar.x, decorativeStar.y, decorativeStar.radius, 0, 2 * Math.PI);
        this.ctx.fillStyle = "rgba(254, 255, 242," + decorativeStar.alpha + ")";
        this.ctx.fill();
        this.ctx.closePath();

    }

and those created as Path2D because I wanted them to be clickable (=planetPaths):以及创建为 Path2D 的那些,因为我希望它们可点击(=planetPaths):

createPlanetPaths = (planets) => {
        for (var i = 0; i < planets.length; i++) {
            this.planetPaths[i] = {
                ref: new Path2D(),
                x: Math.random() * WIDTH_CANVAS,
                y: Math.random() * HEIGHT_CANVAS,
                radius: this.getPlanetRadius(planets[i]),
                color: planets[i].color,
            }
        }
    }

drawPlanets = (planetPaths) => {

        for (let i = 0; i < planetPaths.length; i++) {
            planetPaths[i].ref.arc(planetPaths[i].x, planetPaths[i].y, planetPaths[i].radius, 0, 2 * Math.PI);
            planetPaths[i].ref.gradient = this.ctx.createLinearGradient((planetPaths[i].x - planetPaths[i].radius), (planetPaths[i].y - planetPaths[i].radius), 1.02 * (planetPaths[i].x + planetPaths[i].radius), 1.02 * (planetPaths[i].y + planetPaths[i].radius));
            planetPaths[i].ref.gradient.addColorStop(0, planetPaths[i].color);
            planetPaths[i].ref.gradient.addColorStop(1, 'red');
            this.ctx.fillStyle = planetPaths[i].ref.gradient;
            this.ctx.fill(planetPaths[i].ref);
        }

    };

Now i'd like to animate these circles, using requestAnimationFrame.现在我想使用 requestAnimationFrame 为这些圆圈设置动画。 My problem is that this.ctx.clearRect(0, 0, WIDTH_CANVAS, HEIGHT_CANVAS);我的问题是this.ctx.clearRect(0, 0, WIDTH_CANVAS, HEIGHT_CANVAS); seem to have no effect on the Path2D objects, while it works for the others.似乎对 Path2D 对象没有影响,而它对其他对象有效。

Is there another way to clear Path2D objects?还有另一种清除 Path2D 对象的方法吗?

EDIT, here my updateCanvas method, to generate the animation:编辑,这里是我的 updateCanvas 方法,以生成动画:

updateCanvas() {

        this.ctx.clearRect(0, 0, WIDTH_CANVAS, HEIGHT_CANVAS);

        for (let i = 0; i < this.planetPaths.length; i++) {
            var planetPath = this.planetPaths[i];
            if (planetPath.x < WIDTH_CANVAS) {
                planetPath.x += 1;
            } else {
                planetPath.x = 0;
            }
        }


        for (let i = 0; i < this.decorativeStars.length; i++) {
            var star = this.decorativeStars[i];
            if (star.decreasing == true) {
                star.alpha -= star.decreasingIncreasingRatio;
                if (star.alpha < 0.10) { star.decreasing = false; }
            }
            else {
                star.alpha += star.decreasingIncreasingRatio;
                if (star.alpha > 0.95) { star.decreasing = true; }
            }
            // star.x+=0.01;
        }

        this.drawDecorativeStars(this.decorativeStars);
        this.drawPlanets(this.planetPaths);

        this.myReq = requestAnimationFrame(this.updateCanvas);

    }

You are using the Path2D object incorrectly.您错误地使用了Path2D对象。

In the drawPlanets function you are adding sub-paths to the path each time you call draw.drawPlanets函数中,您每次调用 draw 时都会向路径添加子路径。

planetPaths[i].ref.arc(planetPaths[i].x, planetPaths[i].y, planetPaths[i].radius, 0, 2 * Math.PI);

Thus every time you draw the path with this.ctx.fill(planetPaths[i].ref);因此每次你用this.ctx.fill(planetPaths[i].ref);绘制路径时this.ctx.fill(planetPaths[i].ref); you draw all the sub paths you have added up to that time.您绘制了当时添加的所有子路径。

Using Path2D使用Path2D

  • You can not clear the Path2D object.您无法清除Path2D对象。
  • You only add the path you want rendered, once.您只需添加一次要渲染的路径。
  • To change the path you need to create a new Path2D or transform the path when you render it.要更改路径,您需要在渲染时创建一个新的Path2D或转换路径。

Fix使固定

Create the path and all unchanging states once (init), then render many times (each frame)创建路径和所有不变状态一次(init),然后渲染多次(每帧)

You code should look more like...你的代码应该看起来更像......

createPlanetPaths = planets => {
    for (const planet of planets) {
        const path = new Path2D();
        const x = Math.random() * WIDTH_CANVAS;
        const y = Math.random() * HEIGHT_CANVAS;
        const radius =  this.getPlanetRadius(planet);

        path.arc(x, y, radius, 0, 2 * Math.PI);

        const gradient = this.ctx.createLinearGradient((px - radius), (y - radius), 1.02 * (x + radius), 1.02 * (y + radius));
        gradient.addColorStop(0, planet.color);
        gradient.addColorStop(1, 'red');

        this.planetPaths[i] = {path, gradient};
    }
}

drawPlanets = planetPaths => {
    for (const planetPath of planetPaths) {
        this.ctx.fillStyle = planetPath.gradient;
        this.ctx.fill(planetPath.path);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM