立体圆环频谱
本帖最后由 马黑黑 于 2022-12-23 10:08 编辑早些时候,这里介绍过3d盒子的制作,其中的相关知识与技巧在这里用得上,感兴趣的朋友可以在坛子内搜一搜,在此,仅就实现3d原理做简单复习:
一、CSS 3d景深属性 :这是3d实现的“场景”,3d景深提供具有纵深感的舞台。景深设置在父级元素,可以是body元素,但一般建议需要3d展示的子元素的父元素。设置方法:
perspective: 2000px;
perspective 属性用于设置3d场景,其值为具体数值加尺寸单位。景深的尺寸会直接影响其下子元素的3d样式,所以要设置得当,值越大纵深尺度越大、3d子元素可能会更细腻。
二、CSS 3d样式属性 :用于子元素,表明子元素使用3d渲染样式。语句:
transform-style: preserve-3d;
transform-style 属性声明渲染方式,3d的值是唯一的,preserve-3d。设置此属性的子元素其实也是一个容器,真正要以3d呈现的元素是它的子元素,就是说,它容纳的诸多的子元素才是真的以3d样式渲染,于这些子元素而言,设置了 transform-style: preserve-3d; 的元素是爸爸,设置了 perspective: 2000px; 的元素是爷爷,往下我们称这些3d渲染的元素为子子元素。
至此,3d氛围已经准备就绪,但3d的呈现还需要一些细节操作——
三、使用 transform 通过旋转、移位等方法组装立体盒子
transform属性有一个巧妙的方法,先rotate一定角度、再translate一定距离,能让元素绕圈圈排列。利用这一点,我们先以绝对定位的方式固定好子子元素在相同的位置,然后:
transform: rotateY(??deg) translateZ(??px);
子子元素先绕Y轴旋转一定角度,再往Z轴平移一定距离。每一个子子元素转动多少角度,依据子子元素的数量,用 360/总数得出;平移具体距离,计算方法是子子元素的爸爸(设置了 transform-style: preserve-3d; 那个)的宽度除以2(子子元素的宽度也应考虑在计算之列,这里不详细讨论)。
频谱不用顶盖和底盖,所以仅用 rotateY 和 translateZ 就能解决问题。到这里,就差不多了,再加上一些其他的修饰,比如频谱颜色、频谱帽、频谱旋转、频谱高低变化等等,就完美了。
下面是我刚编写好的示例代码:
<style>
#papa { margin: auto; width: 1024px; height: 640px; background: black linear-gradient(to right bottom,hsla(26,100%,50%,.75),hsla(200,100%,50%,.75)); box-shadow: 3px 3px 20px #000; display: grid; place-items: center; perspective: 3000px; position: relative; z-index: 1; }
#mplayer { position: absolute; bottom: 40px; width: 300px; height: 250px; display: grid; place-items: center; transform-style: preserve-3d; animation: rot3d 100s infinite linear; }
.mline { position: absolute; width: 8px; height: 10px; bottom: 0; border-radius: 10px 10px 0 0; opacity: .95; }
.mline::before { position: absolute; content: ''; width: 100%; height: 8px; background: var(--psecolor); border-radius: 50%; transform: scale(1.5); transition: all var(--ts); animation: up 1s infinite; }
@keyframes rot3d { to { transform: rotateY(1turn); } }
@keyframes up { to { top: -20px; } }
</style>
<div id="papa">
<div id="mplayer"></div>
</div>
<script>
let total = Math.floor(mplayer.offsetWidth / 4), mRad = Math.floor(mplayer.offsetWidth / 2);
for(j=0; j< total; j++) {
let ele = document.createElement('span');
ele.className = 'mline';
ele.style.cssText += `
background: linear-gradient(to bottom, #${Math.random().toString(16).substr(-6)}, #${Math.random().toString(16).substr(-6)});
height: ${Math.floor(Math.random() * 80) + 20}px;
transform: rotateY(${j*360/total}deg) translateZ(${mRad}px);
--psecolor: linear-gradient(135deg, #${Math.random().toString(16).substr(-6)}, #${Math.random().toString(16).substr(-6)});
--ts: ${Math.random()}s;
`;
mplayer.appendChild(ele);
}
let lines = document.querySelectorAll('.mline');
(function update() {
lines.forEach( (item,key) => {
item.style.height = `${Math.floor(Math.random() * 120) + 6}px`;
});
setTimeout(update,500);
})();
</script>楼下是运行效果。
本帖最后由 马黑黑 于 2022-12-25 09:11 编辑 <br /><br /><style>
#papa { margin: 0 0 0 calc(50% - 593px); width: 1024px; height: 640px; background: black linear-gradient(to right bottom,hsla(26,100%,50%,.75),hsla(200,100%,50%,.75)); box-shadow: 3px 3px 20px #000; display: grid; place-items: center; perspective: 3000px; position: relative; z-index: 1; }
#mplayer { position: absolute; bottom: 40px; width: 300px; height: 250px; display: grid; place-items: center; transform-style: preserve-3d; animation: rot3d 100s infinite linear; }
.mline { position: absolute; width: 8px; height: 10px; bottom: 0; border-radius: 10px 10px 0 0; opacity: .95; }
.mline::before { position: absolute; content: ''; left: calc(50% - 6px); width: 12px; height: 12px; background: var(--psecolor); border-radius: 50%; transition: all var(--ts); animation: up 1s infinite; }
@keyframes rot3d { to { transform: rotateY(1turn); } }
@keyframes up { to { top: -20px; } }
</style>
<div id="papa">
<div id="mplayer"></div>
</div>
<script>
let total = Math.floor(mplayer.offsetWidth / 4), mRad = Math.floor(mplayer.offsetWidth / 2);
for(j=0; j< total; j++) {
let ele = document.createElement('span');
ele.className = 'mline';
ele.style.cssText += `
background: linear-gradient(to bottom, #${Math.random().toString(16).substr(-6)}, #${Math.random().toString(16).substr(-6)});
height: ${Math.floor(Math.random() * 80) + 20}px;
transform: rotateY(${j*360/total}deg) translateZ(${mRad}px);
--psecolor: linear-gradient(135deg, #${Math.random().toString(16).substr(-6)}, #${Math.random().toString(16).substr(-6)});
--ts: ${Math.random()}s;
`;
mplayer.appendChild(ele);
}
let lines = document.querySelectorAll('.mline');
(function update() {
lines.forEach( (item,key) => {
item.style.height = `${Math.floor(Math.random() * 120) + 6}px`;
});
setTimeout(update,500);
})();
</script>
黑黑又带来新效果。这个像皇帝的皇冠{:4_173:} 等加上音乐,再跟音乐的暂停播放关联,一个新的播放器就出现了{:4_173:} 红影 发表于 2022-12-23 10:13
黑黑又带来新效果。这个像皇帝的皇冠
是有点像皇冠{:4_173:} 红影 发表于 2022-12-23 10:35
等加上音乐,再跟音乐的暂停播放关联,一个新的播放器就出现了
这个容易吧? 又创造性的把走马灯运用到频谱上了{:4_173:} 樵歌 发表于 2022-12-23 11:48
又创造性的把走马灯运用到频谱上了
这个挺漂亮的吧 马黑黑 发表于 2022-12-23 10:48
是有点像皇冠
也许不高度降低点,或者升高点,就不太像皇冠了。 马黑黑 发表于 2022-12-23 10:48
这个容易吧?
这个我不行,你肯定容易。 红影 发表于 2022-12-23 15:24
这个我不行,你肯定容易。
其实就是将它和 audio 的关系建立起来:点击它,audio播放或停止播放;audio暂停或播放时,它转动起来、跳跃起来。
如果是响应式的,那会复杂一点:要用 audioContext(音频上下文接口)与 audio 建立关系,act 从 aud 这里获得声波信息,再去驱动频谱。 红影 发表于 2022-12-23 15:23
也许不高度降低点,或者升高点,就不太像皇冠了。
像皇冠有啥不好?{:4_203:} 醉美水芙蓉 发表于 2022-12-23 17:57
皇帝的皇冠!好漂亮!
{:4_196:} 马黑黑 发表于 2022-12-23 16:55
其实就是将它和 audio 的关系建立起来:点击它,audio播放或停止播放;audio暂停或播放时,它转动起来、 ...
这里面说道还真不少{:4_187:} 马黑黑 发表于 2022-12-23 16:56
像皇冠有啥不好?
也是哦,像皇冠也挺好的呀{:4_189:} 红影 发表于 2022-12-24 10:18
也是哦,像皇冠也挺好的呀
就是 红影 发表于 2022-12-24 10:17
这里面说道还真不少
三者间的关系 马黑黑 发表于 2022-12-24 10:25
就是
我空了去做个帖子送礼去{:4_173:} 马黑黑 发表于 2022-12-24 10:26
三者间的关系
只有黑黑能弄得明白,我是总是糊里糊涂的.