这个烟花效果,浏览器窗口切换到其他tab页,等一下,再切换回来,烟花效果不正确,怎么改正?

发布于 2022-09-12 01:20:14 字数 6047 浏览 27 评论 0

浏览器打开该页面,切换到其他tab页。等几秒再切换回来。烟花会出现倒退效果。怎么改正?
代码不是我写的,canvas也不熟悉,需要大神亲自指明代码。
image.png

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <style>
body,html {
  overflow: hidden; 
  margin: 0; 
 padding: 0px;
}
        .opaque {
        margin: 0;
        width: 100%;
        background: #020202;
        cursor: crosshair;
    }

    canvas {
        display: block
    }

    h1 {
        position: absolute;
        top: 20%;
        left: 50%;
        transform: translate(-50%, -50%);
        color: #fff;
        font-family: "Source Sans Pro";
        font-size: 5em;
        font-weight: 900;
        -webkit-user-select: none;
        user-select: none;
    }
    </style>
</head>

<body>
    <div class="opaque">
        <canvas id="birthday"></canvas>
    </div>
    <script type="text/javascript">
    // helper functions
    const PI2 = Math.PI * 2
    const random = (min, max) => Math.random() * (max - min + 1) + min | 0
    const timestamp = _ => new Date().getTime()

    // container
    class Birthday {
        constructor() {
            this.resize()

            // create a lovely place to store the firework
            this.fireworks = []
            this.counter = 0

        }

        resize() {
            this.width = canvas.width = window.innerWidth
            let center = this.width / 2 | 0
            this.spawnA = center - center / 4 | 0
            this.spawnB = center + center / 4 | 0

            this.height = canvas.height = window.innerHeight
            this.spawnC = this.height * .1
            this.spawnD = this.height * .5

        }

        onClick(evt) {
            let x = evt.clientX || evt.touches && evt.touches[0].pageX
            let y = evt.clientY || evt.touches && evt.touches[0].pageY

            let count = random(3, 5)
            for (let i = 0; i < count; i++) this.fireworks.push(new Firework(
                random(this.spawnA, this.spawnB),
                this.height,
                x,
                y,
                random(0, 260),
                random(30, 110)))

            this.counter = -1

        }

        update(delta) {
            ctx.globalCompositeOperation = 'hard-light'
            ctx.fillStyle = `rgba(20,20,20,${ 7 * delta })`
            ctx.fillRect(0, 0, this.width, this.height)

            ctx.globalCompositeOperation = 'lighter'
            for (let firework of this.fireworks) firework.update(delta)

            // if enough time passed... create new new firework
            this.counter += delta * 3 // each second
            if (this.counter >= 1) {
                this.fireworks.push(new Firework(
                    random(this.spawnA, this.spawnB),
                    this.height,
                    random(0, this.width),
                    random(this.spawnC, this.spawnD),
                    random(0, 360),
                    random(30, 110)))
                this.counter = 0
            }

            // remove the dead fireworks
            if (this.fireworks.length > 1000) this.fireworks = this.fireworks.filter(firework => !firework.dead)

        }
    }

    class Firework {
        constructor(x, y, targetX, targetY, shade, offsprings) {
            this.dead = false
            this.offsprings = offsprings

            this.x = x
            this.y = y
            this.targetX = targetX
            this.targetY = targetY

            this.shade = shade
            this.history = []
        }
        update(delta) {
            if (this.dead) return

            let xDiff = this.targetX - this.x
            let yDiff = this.targetY - this.y
            if (Math.abs(xDiff) > 3 || Math.abs(yDiff) > 3) { // is still moving
                this.x += xDiff * 2 * delta
                this.y += yDiff * 2 * delta

                this.history.push({
                    x: this.x,
                    y: this.y
                })

                if (this.history.length > 20) this.history.shift()

            } else {
                if (this.offsprings && !this.madeChilds) {

                    let babies = this.offsprings / 2
                    for (let i = 0; i < babies; i++) {
                        let targetX = this.x + this.offsprings * Math.cos(PI2 * i / babies) | 0
                        let targetY = this.y + this.offsprings * Math.sin(PI2 * i / babies) | 0

                        birthday.fireworks.push(new Firework(this.x, this.y, targetX, targetY, this.shade, 0))

                    }

                }
                this.madeChilds = true
                this.history.shift()
            }

            if (this.history.length === 0) this.dead = true
            else if (this.offsprings) {
                for (let i = 0; this.history.length > i; i++) {
                    let point = this.history[i]
                    ctx.beginPath()
                    ctx.fillStyle = 'hsl(' + this.shade + ',100%,' + i + '%)'
                    ctx.arc(point.x, point.y, 1, 0, PI2, false)
                    ctx.fill()
                }
            } else {
                ctx.beginPath()
                ctx.fillStyle = 'hsl(' + this.shade + ',100%,50%)'
                ctx.arc(this.x, this.y, 1, 0, PI2, false)
                ctx.fill()
            }

        }
    }

    let canvas = document.getElementById('birthday')
    let ctx = canvas.getContext('2d')

    let then = timestamp()

    let birthday = new Birthday
    window.onresize = () => birthday.resize()
    document.onclick = evt => birthday.onClick(evt)
    document.ontouchstart = evt => birthday.onClick(evt)

    ;
    (function loop() {
        requestAnimationFrame(loop)

        let now = timestamp()
        let delta = now - then

        then = now
        birthday.update(delta / 1000)


    })()
    </script>
</body>

</html>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

素染倾城色 2022-09-19 01:20:14

定时器异常了吧。document.hidden隐藏的时候动画就停了呗。

监听visibilitychange这个事件是在前后台切换的时候会触发。

メ斷腸人バ 2022-09-19 01:20:14

let lastTime: number = 0;

const animotion = (timestamp: number = 0): void => {

    if (timestamp - lastTime > 50) {

        render();

        lastTime = timestamp;

    }

    window.requestAnimationFrame(animotion);
};

animotion();

附上我以前写的,你可以参考下:
效果:
https://grewer.github.io/JsDe...
code:
https://github.com/Grewer/JsD...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文