H5 鼠标点击粒子扩散效果

🧐别人的博客中有这样的效果,于是自己就尝试实现了一下。
效果如图
在这里插入图片描述
源码如下

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./assets/global.css">

    <style>
        .blastParticle {
            position: absolute;
            transform: translate(-50%, -50%);
            pointer-events: none;
        }


        body {
            overflow: hidden;
        }



        .hint-text {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 100vw;
            height: 100vh;
            user-select: none;
        }
    </style>
</head>

<body>
    <div class="hint-text">
        点击鼠标左键,查看粒子效果
    </div>


    <script type="module">
        import { Randoms } from "https://gcore.jsdelivr.net/npm/@3r/tool/lib/randoms.js";
        import { Animation } from "https://gcore.jsdelivr.net/npm/@3r/tool/lib/animation.js";
        import { Maths } from "https://gcore.jsdelivr.net/npm/@3r/tool/lib/maths.js";


        /**
         * 爆炸粒子效果
         */
        function blastParticle(params = {}) {
            
            let { left = 0, top = 0, width = 200, height = 200, count = 20, rr = [10, 20], duration = 1 } = params

            // 通过recovery拾取回收canvas 减少dom产生量
            let canvas = document.querySelector('canvas.blastParticle.recovery') || document.createElement("canvas")
            canvas.classList.remove('recovery')

            let ctx = canvas.getContext('2d')
            canvas.width = width;
            canvas.height = height;

            canvas.classList.add('blastParticle')
            canvas.style.left = left + 'px'
            canvas.style.top = top + 'px'


            let cx = width / 2
            let cy = height / 2

            class Particle {
                constructor({ x, y, r, tx, ty, ts, color, duration }) {
                    this.x = x;
                    this.y = y;
                    this.r = r;
                    this.tx = tx;
                    this.ty = ty;
                    this.ts = ts;
                    this.color = color

                    this.timestemp = +new Date()

                    this.update = () => {
                        if ((+new Date() - this.timestemp) > 1000 * duration) return;

                        let timeProportion = (+new Date() - this.timestemp) / (1000 * duration)
                        let proportion = Animation.easeOut(timeProportion)

                        this.x = x + tx * proportion
                        this.y = y + ty * proportion
                        this.r = r * (1 - timeProportion)

                        ctx.fillStyle = color
                        ctx.beginPath()
                        ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2)
                        ctx.closePath();
                        ctx.fill()
                    }
                }
            }



            // 记录开始时间 用于停止渲染标记
            let startTimestemp = +new Date()

            function renderer(particles) {
                ctx.clearRect(0, 0, width, height)
                for (const p of particles) {
                    p.update()
                }

                if (+new Date() - startTimestemp < duration * 1000) {
                    console.log("渲染中");
                    requestAnimationFrame(() => { renderer(particles) })
                }
                else {
                    console.log('渲染结束');
                    canvas.classList.add('recovery');
                }
            }

            // 粒子列表
            let particleList = []
            for (let i = 0; i < count; i++) {
                // 随机方向
                let tx = 2 * Math.random() - 1
                let ty = 2 * Math.random() - 1
                // 乘以半径
                tx *= cx;
                ty *= cy;
                let particle = new Particle({ x: cx, y: cy, r: Randoms.getRandomInt(...rr), tx, ty, ts: 0, duration, color: Randoms.getRandomColor() })
                particleList.push(particle)
            }
            // 执行渲染
            renderer(particleList)
            document.body.appendChild(canvas)
        }

        document.addEventListener("click", (ev) => {
            blastParticle({ left: ev.x, top: ev.y, duration: .5 })
        })
    </script>
</body>

</html>

在线预览
https://linyisonger.github.io/H5.Examples/
源码仓库
https://github.com/linyisonger/H5.Examples.git

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-05-10 15:14:13       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-10 15:14:13       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-10 15:14:13       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-10 15:14:13       20 阅读

热门阅读

  1. 生物经济:生物技术的未来

    2024-05-10 15:14:13       10 阅读
  2. 十二届蓝桥杯Python组3月中/高级试题 第五题

    2024-05-10 15:14:13       11 阅读
  3. MySQL变量的浮点数问题处理

    2024-05-10 15:14:13       11 阅读
  4. Boolean test介绍

    2024-05-10 15:14:13       9 阅读
  5. oracle数据归档方案

    2024-05-10 15:14:13       10 阅读
  6. ==与===的区别

    2024-05-10 15:14:13       11 阅读
  7. leetcode 并查集

    2024-05-10 15:14:13       11 阅读
  8. stable diffusion教程

    2024-05-10 15:14:13       9 阅读