马黑黑 发表于 2022-8-11 07:27

梦幻电音

<style>
#papa { left: -214px; width: 1024px; height: 640px; background: #000 url('https://638183.freep.cn/638183/Pic/81/818.png') no-repeat center/cover; box-shadow: 3px 3px 20px #000; position: relative; }
#canv { position: absolute; }
#disc { position: absolute; width: 40px; height: 40px; left: 10px; top: 10px; background: conic-gradient(red,orange,yellow,green,teal,blue,purple); mask: radial-gradient(transparent 4px,red 0); -webkit-mask: radial-gradient(transparent 4px,red 0); border-radius: 50%; cursor: pointer; animation: rot 2s linear infinite; }
#tit { position: absolute; left: 60px; top: 10px;font: bold 22px / 40px sans-serif; color: snow; text-shadow: 2px 2px 4px black; }
@keyframes rot { to { transform: rotate(360deg); } }
</style>

<div id="papa">
        <span id="tit">Electric Dreams</span>
        <canvas id="canv"></canvas>
        <span id="disc"></span>
</div>

<script>
(function() {
        let ctx = canv.getContext('2d');
        let w = canv.width = papa.offsetWidth, h = canv.height = papa.offsetHeight;
        let particles = [], idx = 0, aud = new Audio();
       
        aud.src = 'https://music.163.com/song/media/outer/url?id=1332849399.mp3';
        aud.loop = true;
        aud.autoplay = true;

        disc.style.animationPlayState = aud.paused ? 'paused' : 'running';
        disc.onclick = () => aud.paused ? aud.play() : aud.pause();
        aud.addEventListener('playing',()=> disc.style.animationPlayState = 'running');
        aud.addEventListener('pause',()=> disc.style.animationPlayState = 'paused');

        canv.onclick = function(event) {
                let x = event.offsetX || event.layerX;
                let y = event.offsetY || event.layerY;
                createParticle(x, y);
        }

        function createParticle(x, y) {
                let count = 100;
                let radius = 10;
                let hue = Math.floor(Math.random() * 51) + 100;
                let change = 30;
                for (let j = 0; j < count; j ++) {
                        let p = {};
                        let angle = 360 / count * j;
                        let radian = Math.PI / 180 * angle;
                        p.radius = radius;
                        p.startX = x;
                        p.startY = y;
                        p.radian = radian;
                        p.hue = Math.floor(Math.random() * (change * 2)) + (hue - change);
                        p.lightness = Math.floor(Math.random() * 100);
                        p.alpha = (Math.floor(Math.random() * 101)) / 100;
                        p.speed = (Math.random() * 5) + 0.4;
                        p.radius = p.speed;
                        particles.push(p);
                }
        }

        function drawParticle() {
                ctx.fillStyle = 'transparent';
                ctx.fillRect(0, 0, w, h);
                for (let i = 0; i < particles.length; i++) {
                       let p = particles;
                        let resultX = Math.cos(p.radian) * p.radius;
                        let resultY = Math.sin(p.radian) * p.radius + 0.4;
                        p.startX += resultX;
                        p.startY += resultY;
                        p.radius *= 1 - p.speed / 100;
                        p.alpha -= 0.005;
                        if (p.alpha <= 0) {
                                particles.splice(i, 1);
                                continue;
                        }

                        ctx.beginPath();
                        ctx.arc(p.startX, p.startY, 2, 0, 360, false);
                        ctx.closePath();
                        ctx.fillStyle = "hsla( " + p.hue + " , 100% ," + p.lightness + "% , " + p.alpha + ")";
                        ctx.fill();
                }
        }

        function fade() {
                ctx.globalCompositeOperation = "destination-out";
                ctx.fillStyle = "rgba(0 , 0 , 0, " + 0.1 + ")";
                ctx.fillRect(0, 0, w, h);
                ctx.globalCompositeOperation = "lighter";
        }

        function render() {
                idx ++;
                fade();
                drawParticle();
                if(idx > 50) {
                        createParticle(Math.random() * w, Math.random() * h);
                        idx = 0;
                }
                requestAnimationFrame(render);
        }
        render();
})();
</script>

马黑黑 发表于 2022-8-11 07:29

鼠标点击帖子任意地方……

马黑黑 发表于 2022-8-11 07:29

除了光盘

马黑黑 发表于 2022-8-11 07:33

代码分享:
<style>
#papa { left: -214px; width: 1024px; height: 640px; background: #000 url('https://638183.freep.cn/638183/Pic/81/818.png') no-repeat center/cover; box-shadow: 3px 3px 20px #000; position: relative; }
#canv { position: absolute; }
#disc { position: absolute; width: 40px; height: 40px; left: 10px; top: 10px; background: conic-gradient(red,orange,yellow,green,teal,blue,purple); mask: radial-gradient(transparent 4px,red 0); -webkit-mask: radial-gradient(transparent 4px,red 0); border-radius: 50%; cursor: pointer; animation: rot 2s linear infinite; }
#tit { position: absolute; left: 60px; top: 10px;font: bold 22px / 40px sans-serif; color: snow; text-shadow: 2px 2px 4px black; }
@keyframes rot { to { transform: rotate(360deg); } }
</style>

<div id="papa">
        <span id="tit">Electric Dreams</span>
        <canvas id="canv"></canvas>
        <span id="disc"></span>
</div>

<script>
(function() {
        let ctx = canv.getContext('2d');
        let w = canv.width = papa.offsetWidth, h = canv.height = papa.offsetHeight;
        let particles = [], idx = 0, aud = new Audio();
       
        aud.src = 'https://music.163.com/song/media/outer/url?id=1332849399.mp3';
        aud.loop = true;
        aud.autoplay = true;

        disc.style.animationPlayState = aud.paused ? 'paused' : 'running';
        disc.onclick = () => aud.paused ? aud.play() : aud.pause();
        aud.addEventListener('playing',()=> disc.style.animationPlayState = 'running');
        aud.addEventListener('pause',()=> disc.style.animationPlayState = 'paused');

        canv.onclick = function(event) {
                let x = event.offsetX || event.layerX;
                let y = event.offsetY || event.layerY;
                createParticle(x, y);
        }

        function createParticle(x, y) {
                let count = 100;
                let radius = 10;
                let hue = Math.floor(Math.random() * 51) + 100;
                let change = 30;
                for (let j = 0; j < count; j ++) {
                        let p = {};
                        let angle = 360 / count * j;
                        let radian = Math.PI / 180 * angle;
                        p.radius = radius;
                        p.startX = x;
                        p.startY = y;
                        p.radian = radian;
                        p.hue = Math.floor(Math.random() * (change * 2)) + (hue - change);
                        p.lightness = Math.floor(Math.random() * 100);
                        p.alpha = (Math.floor(Math.random() * 101)) / 100;
                        p.speed = (Math.random() * 5) + 0.4;
                        p.radius = p.speed;
                        particles.push(p);
                }
        }

        function drawParticle() {
                ctx.fillStyle = 'transparent';
                ctx.fillRect(0, 0, w, h);
                for (let i = 0; i < particles.length; i++) {
                       let p = particles;
                        let resultX = Math.cos(p.radian) * p.radius;
                        let resultY = Math.sin(p.radian) * p.radius + 0.4;
                        p.startX += resultX;
                        p.startY += resultY;
                        p.radius *= 1 - p.speed / 100;
                        p.alpha -= 0.005;
                        if (p.alpha <= 0) {
                                particles.splice(i, 1);
                                continue;
                        }

                        ctx.beginPath();
                        ctx.arc(p.startX, p.startY, 2, 0, 360, false);
                        ctx.closePath();
                        ctx.fillStyle = "hsla( " + p.hue + " , 100% ," + p.lightness + "% , " + p.alpha + ")";
                        ctx.fill();
                }
        }

        function fade() {
                ctx.globalCompositeOperation = "destination-out";
                ctx.fillStyle = "rgba(0 , 0 , 0, " + 0.1 + ")";
                ctx.fillRect(0, 0, w, h);
                ctx.globalCompositeOperation = "lighter";
        }

        function render() {
                idx ++;
                fade();
                drawParticle();
                if(idx > 50) {
                        createParticle(Math.random() * w, Math.random() * h);
                        idx = 0;
                }
                requestAnimationFrame(render);
        }
        render();
})();
</script>

马黑黑 发表于 2022-8-11 07:51

本帖最后由 马黑黑 于 2022-8-11 12:07 编辑

本帖使用表达式函数的方式封装所有JS代码,可解开,将:

开头的 (和 末尾的 )() 去掉。

表达式函数又称立即执行函数,举个简单例子:

(function() {
    alert('Hi~');
})();

开头的括号告诉浏览器,我是个立即执行函数;末尾的反括号告诉浏览器,立即执行函数到此结束。最后一对括号告诉浏览器,立即执行前面括号里的表达式函数。

立即执行函数有诸多应用场景,它的作用也很多,这里不提。

马黑黑 发表于 2022-8-11 07:54

本帖烟花效果参考了大佬们的开源作品,里面的算法颇有玩味。例如,烟花的散开(draw函数内)、拖尾效果(fade函数)等等。

马黑黑 发表于 2022-8-11 07:58

本帖渲染烟花的颜色使用了 hsl 值,hsl颜色体系的知识可参阅 https://www.w3school.com.cn/css/css_colors_hsl.asp

背景渲染(拖尾)使用的颜色体系的rgba

加林森 发表于 2022-8-11 07:59

好厉害,点击就开花了。{:4_199:}

马黑黑 发表于 2022-8-11 08:03

本帖封装的函数简单说明:

createParticle(x, y)函数:在xy坐标点创建圆环例子

drawParticle()函数:绘制动态例子

fade()函数:烟花拖尾效果

render()函数:渲画布

还有画布单击事件,canv.onclick,用于手动播放一朵烟花。

上海朝阳 发表于 2022-8-11 08:41

太美啦,梦幻世界呀。

加林森 发表于 2022-8-11 08:48

马黑黑 发表于 2022-8-11 07:58
本帖渲染烟花的颜色使用了 hsl 值,hsl颜色体系的知识可参阅 https://www.w3school.com.cn/css/css_colors_ ...

去学习。谢谢啦!

马黑黑 发表于 2022-8-11 12:06

上海朝阳 发表于 2022-8-11 08:41
太美啦,梦幻世界呀。

感谢支持

马黑黑 发表于 2022-8-11 12:07

加林森 发表于 2022-8-11 08:48
去学习。谢谢啦!

那个没有前面给你的容易,它是更全面、深刻的

加林森 发表于 2022-8-11 12:16

马黑黑 发表于 2022-8-11 12:07
那个没有前面给你的容易,它是更全面、深刻的

没关系的,慢慢学习吧,总会学点有用的吧。

马黑黑 发表于 2022-8-11 12:38

加林森 发表于 2022-8-11 12:16
没关系的,慢慢学习吧,总会学点有用的吧。

它的知识体系是全面的,学完它就是高手

加林森 发表于 2022-8-11 12:50

马黑黑 发表于 2022-8-11 12:38
它的知识体系是全面的,学完它就是高手

我不求高手,就系统学习一下可以吧。

马黑黑 发表于 2022-8-11 12:51

加林森 发表于 2022-8-11 12:50
我不求高手,就系统学习一下可以吧。

挺好挺好

红影 发表于 2022-8-11 14:20

马黑黑 发表于 2022-8-11 07:58
本帖渲染烟花的颜色使用了 hsl 值,hsl颜色体系的知识可参阅 https://www.w3school.com.cn/css/css_colors_ ...

一直不知道这个颜色有什么用,这个帖子里就遇到了呢{:4_173:}

红影 发表于 2022-8-11 14:22

这个代码绘制的烟花,比平日里找的动图还漂亮,黑黑太厉害了{:4_199:}

红影 发表于 2022-8-11 14:24

画布的存在,使得对图形的操作更方便,绽放在鼠标指向的烟花非常有趣。
页: [1] 2 3 4
查看完整版本: 梦幻电音