涅槃重生左侧效果解释
请访问 《涅槃重生》 查看效果,谢谢!帖子左侧的效果,是帖子“动”的组成部分,它的实现思路是:布排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>
<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: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();
//其他代码
});
这么简单的公式,就能得到这样一条长龙,真神奇{:4_199:} 马黑黑 发表于 2022-11-14 08:53
以上,实现了外观功能,我们还需要一个自定义函数让子元素中某一个上色:
let lastcircle = 0; //上一个 ...
上色是跟音乐关联的么?我这里的网无法播放音乐,这个要等回去再看了。 红影 发表于 2022-11-14 10:22
这么简单的公式,就能得到这样一条长龙,真神奇
算法不是很复杂,却干出看上去很复杂的构图 红影 发表于 2022-11-14 10:23
上色是跟音乐关联的么?我这里的网无法播放音乐,这个要等回去再看了。
不关联。只是通过音乐播放的进度驱动。
音乐的振幅,要获取起来是个复杂的工程,且对音源来源的要求极高,往往因为音源建立不起连接,所以对用 web audio api 播放url音频一直不敢操作。 马黑黑 发表于 2022-11-14 12:15
算法不是很复杂,却干出看上去很复杂的构图
没想到呢,这个算法居然这么简单。 马黑黑 发表于 2022-11-14 12:17
不关联。只是通过音乐播放的进度驱动。
音乐的振幅,要获取起来是个复杂的工程,且对音源来源的要求极高 ...
我现在看不到驱动效果,要等回家才行了。 红影 发表于 2022-11-14 16:18
我现在看不到驱动效果,要等回家才行了。
回家再说 红影 发表于 2022-11-14 16:17
没想到呢,这个算法居然这么简单。
我也只会简单的了 黑黑的新花样真多,每天有新东西{:4_178:} 小辣椒 发表于 2022-11-14 18:09
黑黑的新花样真多,每天有新东西
操旧饭是俺最擅长的{:4_170:} 马黑黑 发表于 2022-11-14 18:10
操旧饭是俺最擅长的
这个好像更加精彩了,昨天我捣鼓很迟完成了一个双语歌词同步 小辣椒 发表于 2022-11-14 18:13
这个好像更加精彩了,昨天我捣鼓很迟完成了一个双语歌词同步
编程歌词有妙招的:先做单语的同步,再加上第二种语言的文本。利用文本编辑器的一些功能,会很容易做的。 马黑黑 发表于 2022-11-14 18:15
编程歌词有妙招的:先做单语的同步,再加上第二种语言的文本。利用文本编辑器的一些功能,会很容易做的。
哈哈,我就这样做的 小辣椒 发表于 2022-11-14 18:21
哈哈,我就这样做的
聪明{:4_187:} 马黑黑 发表于 2022-11-14 17:28
回家再说
我去看看那个帖子{:4_173:} 马黑黑 发表于 2022-11-14 17:29
我也只会简单的了
但得到的效果不简单呢{:4_187:} 红影 发表于 2022-11-14 20:13
但得到的效果不简单呢
那是碰巧