马黑黑 发表于 2022-11-14 08:40

涅槃重生左侧效果解释

请访问 《涅槃重生》 查看效果,谢谢!

帖子左侧的效果,是帖子“动”的组成部分,它的实现思路是:布排N多个元素,通过 transform 的 rotate 和 translate 配合令各元素旋转、移位以达到一定规律的排列,再随机令元素中的某一个着色(着色功能由 audio 播放进度驱动)。

实现步骤:

一、CSS

① 要有一个父框,父框关键代码如下

#papa {
        width: 1200px;
        height: 800px;
        display: grid;
        place-items: center;
        position: relative;
}


grid布局并令子元素绝对居中,这样在设定子元素的物理位置是省事:它们绝对居中,仅调整水平方向或垂直方向的位置,只需加一个 left 或 top 即可。相对定位,必须,这样才能约束绝对定位的子元素。

② 制定子元素基本样式

#papa > span {
        position: absolute;
        left: 300px;
        width: 40px;
        height: 40px;
        border-radius: 8px;
        border: 1px solid red;
}


我们用 span 标签做特效的载体,作为 papa 的直系子元素,即第一代子元素。绝对定位,必须设置;left 定义了元素的初始位置,top不设置,自动垂直居中;宽高都是 40px;边框圆角为 8px,边框样式是 1px、实线、红色。

二、HTML代码:仅父框

<div id="papa"></div>

三、JS实现最终效果

① 生成N多子元素并细化细节

(function() {
        let total = 100, rr = 700;
        Array.from({length: total}).forEach((item, key) => {
                        item = document.createElement('span');
                        let num = rr * key / total;
                        if (num > rr / 2) num -= rr;
                        item.className = 'circle';
                        item.style.cssText += `
                                border-color: #${Math.random().toString(16).substr(-6)};
                                transform: rotate(${(360/total) * key}deg) translateY(${num}px);
                        `;
                        papa.appendChild(item);
                });
})();


这是一个自执行函数,简单解释一下——

变量 total 是子元素数量,rr 是子元素分布的直径;

通过遍历 total 个元素,将其作为 span 标签追加到 papa 父元素中。其中的计算:

    let num = rr * key / total; // translate平移的距离:rr除以total的平均数,根据元素索引key的变化而变化
    if (num > rr / 2) num -= rr; // num超出直径的一半时就拿直径去减num
    //下面追加给子元素的样式细节,有随机边框颜色、transform的角度等计算,translate的值已有 num 计算好
    border-color: #${Math.random().toString(16).substr(-6)};
    transform: rotate(${(360/total) * key}deg) translateY(${num}px);

最后给出完整代码:
<style>
#papa {
        width: 1200px;
        height: 800px;
        display: grid;
        place-items: center;
        position: relative;
}

#papa > span {
        position: absolute;
        left: 300px;
        width: 40px;
        height: 40px;
        border-radius: 8px;
        border: 1px solid red;
}
</style>

<div id="papa"></div>

<script>
(function() {
        let total = 100,
                rr = 700;
        Array.from({
                        length: total
                })
                .forEach((item, key) => {
                        item = document.createElement('span');
                        let num = rr * key / total;
                        if (num > rr / 2) num -= rr;
                        item.className = 'circle';
                        item.style.cssText += `border-color: #${Math.random().toString(16).substr(-6)};transform: rotate(${(360/total) * key}deg) translateY(${num}px);`;
                        papa.appendChild(item);
                });
})();
</script>


马黑黑 发表于 2022-11-14 08:41

<style>
#papa {
        margin: auto;
        width: 760px;
        height: 800px;
        display: grid;
        place-items: center;
        position: relative;
}

#papa > span {
        position: absolute;
        left: 300px;
        width: 40px;
        height: 40px;
        border-radius: 8px;
        border: 1px solid red;
}
</style>

<div id="papa"></div>

<script>
(function() {
        let total = 100,
                rr = 700;
        Array.from({
                        length: total
                })
                .forEach((item, key) => {
                        item = document.createElement('span');
                        let num = rr * key / total;
                        if (num > rr / 2) num -= rr;
                        item.className = 'circle';
                        item.style.cssText += `border-color: #${Math.random().toString(16).substr(-6)};transform: rotate(${(360/total) * key}deg) translateY(${num}px);`;
                        papa.appendChild(item);
                });
})();
</script>

马黑黑 发表于 2022-11-14 08:53

本帖最后由 马黑黑 于 2022-11-14 08:55 编辑

以上,实现了外观功能,我们还需要一个自定义函数让子元素中某一个上色:

let lastcircle = 0; //上一个着色的子元素

let changeBgColor = () => {
      let circles = document.querySelectorAll('.circle'); // 声明子元素的操作句柄
      circles.style.background = 'none'; // 将上一个着色的子元素还原背景色为无
      lastcircle = Math.round(Math.random() * (circles.length - 1)); //随机获得将要着色的子元素索引
      circles.style.background = 'red'; // 给子元素着色
};


子元素索引随机获取,使用到 Math.round() 数学方法,四舍五入。Math.random() 得到的是 0.0 至 0.999... 的随机数,它乘上(circles.length - 1) 即 子元素总数减一 得到的是带小数点的浮点数,把整个算式用 Math.round() 处理后得到整数,即 0 至(total-1)的数字,对应的是子元素的索引号。

然后上述自定义函数 changeBgColor() 由某个机制(比如audio的播放进度)触发即可随机给某一个子元素上色:

aud.addEventListener('timeupdate', () => {
      //其他代码
      changeBgColor();
      //其他代码
});

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

这么简单的公式,就能得到这样一条长龙,真神奇{:4_199:}

红影 发表于 2022-11-14 10:23

马黑黑 发表于 2022-11-14 08:53
以上,实现了外观功能,我们还需要一个自定义函数让子元素中某一个上色:

let lastcircle = 0; //上一个 ...

上色是跟音乐关联的么?我这里的网无法播放音乐,这个要等回去再看了。

马黑黑 发表于 2022-11-14 12:15

红影 发表于 2022-11-14 10:22
这么简单的公式,就能得到这样一条长龙,真神奇

算法不是很复杂,却干出看上去很复杂的构图

马黑黑 发表于 2022-11-14 12:17

红影 发表于 2022-11-14 10:23
上色是跟音乐关联的么?我这里的网无法播放音乐,这个要等回去再看了。

不关联。只是通过音乐播放的进度驱动。
音乐的振幅,要获取起来是个复杂的工程,且对音源来源的要求极高,往往因为音源建立不起连接,所以对用 web audio api 播放url音频一直不敢操作。

红影 发表于 2022-11-14 16:17

马黑黑 发表于 2022-11-14 12:15
算法不是很复杂,却干出看上去很复杂的构图

没想到呢,这个算法居然这么简单。

红影 发表于 2022-11-14 16:18

马黑黑 发表于 2022-11-14 12:17
不关联。只是通过音乐播放的进度驱动。
音乐的振幅,要获取起来是个复杂的工程,且对音源来源的要求极高 ...

我现在看不到驱动效果,要等回家才行了。

马黑黑 发表于 2022-11-14 17:28

红影 发表于 2022-11-14 16:18
我现在看不到驱动效果,要等回家才行了。

回家再说

马黑黑 发表于 2022-11-14 17:29

红影 发表于 2022-11-14 16:17
没想到呢,这个算法居然这么简单。

我也只会简单的了

小辣椒 发表于 2022-11-14 18:09

黑黑的新花样真多,每天有新东西{:4_178:}

马黑黑 发表于 2022-11-14 18:10

小辣椒 发表于 2022-11-14 18:09
黑黑的新花样真多,每天有新东西

操旧饭是俺最擅长的{:4_170:}

小辣椒 发表于 2022-11-14 18:13

马黑黑 发表于 2022-11-14 18:10
操旧饭是俺最擅长的

这个好像更加精彩了,昨天我捣鼓很迟完成了一个双语歌词同步

马黑黑 发表于 2022-11-14 18:15

小辣椒 发表于 2022-11-14 18:13
这个好像更加精彩了,昨天我捣鼓很迟完成了一个双语歌词同步

编程歌词有妙招的:先做单语的同步,再加上第二种语言的文本。利用文本编辑器的一些功能,会很容易做的。

小辣椒 发表于 2022-11-14 18:21

马黑黑 发表于 2022-11-14 18:15
编程歌词有妙招的:先做单语的同步,再加上第二种语言的文本。利用文本编辑器的一些功能,会很容易做的。

哈哈,我就这样做的

马黑黑 发表于 2022-11-14 19:04

小辣椒 发表于 2022-11-14 18:21
哈哈,我就这样做的

聪明{:4_187:}

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

马黑黑 发表于 2022-11-14 17:28
回家再说

我去看看那个帖子{:4_173:}

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

马黑黑 发表于 2022-11-14 17:29
我也只会简单的了

但得到的效果不简单呢{:4_187:}

马黑黑 发表于 2022-11-14 20:19

红影 发表于 2022-11-14 20:13
但得到的效果不简单呢

那是碰巧
页: [1] 2 3
查看完整版本: 涅槃重生左侧效果解释