CSS+JS:3d粒子一例
<style>#mama {}
#mama > p, #mama > pre { padding: 8px 0; }
#mama > pre { font-size: 14px; }
</style>
<div id="mama">
<p>本帖使用到CSS的3d转换知识点:</p>
<p>一、父元素声明景深:</p>
<pre><span style="color: blue;">perspective</span>: 1000px;</pre>
<p>本例景深设置为 1000px,可以是其他数值。景深针对Z轴,即眼睛和屏幕间的方向的延伸,是物体对象在这个方向上从屏幕的表面到纵深方向的距离,该距离越大,景深就越细腻。一般会根据屏幕分辨率定值。</p>
<p>二、子元素声明使用3d:</p>
<pre><span style="color: blue;">transform-style</span>: preserve-3d;</pre>
<p>三、3d关键帧动画:</p>
<pre><span style="color: red;">@keyframes move </span>{
to { <span style="color: blue;">transform</span>: rotate(0) translate3d(0, 0, 0); }
}
</pre>
<p>关键帧动画设计里,我们使用 transform 的两个转换属性 rotate(旋转)和 translate3d(3d移位),当 rotate 放前、translate或translate3d 放后,会产生物体绕圈圈旋转的效果,我们只需把要移动的物体对象定位就好,比如定位在父元素的中心点。这里,大家可能觉得奇怪,rotate 和 translate3d 咋都参数为 0 呢?这与本例设计有关:我们事先旋转了物体对象,然后通过关键帧动画恢复它们的初始状况。看完整的CSS和HTML代码就能理解这个道理,代码里有该有的注释:</p>
<pre><style>
<span style="color: green">/* 父元素 即帖子外框 */</span>
<span style="color: red;">#papa </span>{
<span style="color: blue;">margin</span>: auto;
<span style="color: green">/* 下面两句使用网格布局快速定位子元素绝对居中 */</span>
<span style="color: blue;">display</span>: grid;
<span style="color: blue;">place-items</span>: center;
<span style="color: blue;">width</span>: 1024px;
<span style="color: blue;">height</span>: 640px;
<span style="color: blue;">background</span>: #000;
<span style="color: blue;">box-shadow</span>: 3px 3px 20px #000;
<span style="color: blue;">perspective</span>: 1000px; <span style="color: green">/* 景深设置 */</span>
<span style="color: blue;">overflow</span>: hidden; <span style="color: green">/* 不显示溢出内容 */</span>
<span style="color: blue;">position</span>: relative; <span style="color: green">/* 父元素相对定位 */</span>
}
<span style="color: green">/* 子元素 即运动对象*/</span>
<span style="color: red;">.stars </span>{
<span style="color: blue;">position</span>: absolute; <span style="color: green">/* 子元素绝对定位 */</span>
<span style="color: blue;">width</span>: 3px; <span style="color: green">/* 宽度 */</span>
<span style="color: blue;">height</span>: 3px; <span style="color: green">/* 高度 */</span>
<span style="color: blue;">border-radius</span>: 50%; <span style="color: green">/* 圆形 */</span>
<span style="color: blue;">background</span>: silver; <span style="color: green">/* 初始背景色 */</span>
<span style="color: blue;">transform-style</span>: preserve-3d; <span style="color: green">/* 以 3d 形态展现 */</span>
}
<span style="color: green">/* 关键帧动画 :恢复初始形态(旋转与3d移位)*/</span>
<span style="color: red;">@keyframes move </span>{
to { <span style="color: blue;">transform</span>: rotate(0) translate3d(0, 0, 0); }
}
</style>
<<span style="color:darkred">div</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: magenta">"papa"</span>><<span style="color: darkred">/div</span>>
</pre>
<p>下面,也是最后一步,我们要用 JS 写若干个 class="stars" 的 span 标签,比如 500 个。我们将在 JS里赋予它们上面 .stars 选择器或许包含或许不包含的属性(包含的,CSS的原始设定会被覆盖),我们用一个 for 语句便可完成这个工作:</p>
<pre><script>
<span style="color: blue">for</span>(j=0; j<500; j++) {
<span style="color: blue">let</span> ele = <span style="color: red">document</span>.createElement(<span style="color: magenta">'span'</span>);
ele.className = <span style="color: magenta">'stars'</span>;
ele.style.cssText += `
background: hsl(${<span style="color: red">Math</span>.random() * 255}, ${<span style="color: red">Math</span>.random() * 50 + 40}%,${<span style="color: red">Math</span>.random() * 70 + 20}%);
transform: rotate(${<span style="color: red">Math</span>.random() * 720}deg) translate3d(${<span style="color: red">Math</span>.random() * 500}px,${<span style="color: red">Math</span>.random() * 300}px,${<span style="color: red">Math</span>.random() * 1000}px);
animation: move 30s infinite ${-10 - <span style="color: red">Math</span>.random() * 20}s linear;
`;
papa.appendChild(ele);
}
</script>
</pre>
<p>for语句中,我们创建了 500个 span 标签并追加到 id="papa" 的父元素中,这些 span 标签 class 名为 stars,便能使用 CSS 选择器 .stars 里定义的属性,同时我们添加了新的属性,也修改了 .stars 选择器的部分属性,通过 ele.style.cssText += `...`; 来实现。符号 `` 里面的内容中,我们设定了背景色 background 是随机的 hsla 值,transform 变换则是,先随机旋转(rotate),再随机3d移位(translate3d)。每一个 span 标签因为随机的设置,它们的初始形态,如旋转多少度、移位到哪里,都是不同的,然后通过 animation 调用关键帧动画 move,加入一个延时机制,便可创建出令人惊艳的画面。效果请看二楼。</p>
<p>补充说明一下:关键帧动画中使用的是 translate3d,其中的第三个参数针对 Z轴,该参数随机获取,本例取值范围在 0 - 1000px 之间,值小时对象大,值大时对象小。</p>
</div>
<style>
#papa {
left: -214px;
display: grid;
place-items: center;
width: 1024px;
height: 640px;
background: #000;
box-shadow: 3px 3px 20px #000;
perspective: 1000px;
overflow: hidden;
position: relative;
z-index: 1;
}
.stars {
position: absolute;
width: 3px;
height: 3px;
border-radius: 50%;
background: silver;
transform-style: preserve-3d;
}
@keyframes move {
to { transform: rotate(0) translate3d(0, 0, 0); }
}
</style>
<div id="papa">
</div>
<script>
for(j=0; j<500; j++) {
let ele = document.createElement('span');
ele.className = 'stars';
ele.style.cssText += `
background: hsl(${Math.random() * 255}, ${Math.random() * 50 + 40}%,${Math.random() * 70 + 20}%);
transform: rotate(${Math.random() * 720}deg) translate3d(${Math.random() * 500}px,${Math.random() * 300}px,${Math.random() * 1000}px);
animation: move 30s infinite ${-10 - Math.random() * 20}s linear;
`;
papa.appendChild(ele);
}
</script>
全部代码
<style>
#papa {
margin: auto;
display: grid;
place-items: center;
width: 1024px;
height: 640px;
background: #000;
box-shadow: 3px 3px 20px #000;
perspective: 1000px;
overflow: hidden;
position: relative;
z-index: 1;
}
.stars {
position: absolute;
width: 3px;
height: 3px;
border-radius: 50%;
background: silver;
transform-style: preserve-3d;
}
@keyframes move {
to { transform: rotate(0) translate3d(0, 0, 0); }
}
</style>
<div id="papa">
</div>
<script>
for(j=0; j<500; j++) {
let ele = document.createElement('span');
ele.className = 'stars';
ele.style.cssText += `
background: hsl(${Math.random() * 255}, ${Math.random() * 50 + 40}%,${Math.random() * 70 + 20}%);
transform: rotate(${Math.random() * 720}deg) translate3d(${Math.random() * 500}px,${Math.random() * 300}px,${Math.random() * 1000}px);
animation: move 30s infinite ${-10 - Math.random() * 20}s linear;
`;
papa.appendChild(ele);
}
</script>
马黑黑 发表于 2022-11-4 20:13
#papa {
left: -214px;
display: grid;
这个效果太漂亮了,给黑黑老师点赞送花花{:4_187:}{:4_199:} 千羽 发表于 2022-11-4 20:42
这个效果太漂亮了,给黑黑老师点赞送花花
你可以考虑用到你的帖子 马黑黑 发表于 2022-11-4 20:58
你可以考虑用到你的帖子
嗯,我去收走{:4_181:} 马黑黑 发表于 2022-11-4 20:58
你可以考虑用到你的帖子
谢谢黑黑老师{:4_187:} 千羽 发表于 2022-11-4 21:02
谢谢黑黑老师
{:4_191:} 千羽 发表于 2022-11-4 20:58
嗯,我去收走
{:4_187:} 这个粒子效果真的美,很喜欢的,黑黑太强大了,无所不能啊{:4_178:} 小辣椒 发表于 2022-11-4 21:51
这个粒子效果真的美,很喜欢的,黑黑太强大了,无所不能啊
这个粒子有中心,这是预设,可以局部或全部去中心化,实现方法是再在JS里随机给开每一个 span 元素left和top值,这个随机值还可以略作控制,中心化就不会那么明显 马黑黑 发表于 2022-11-4 21:54
这个粒子有中心,这是预设,可以局部或全部去中心化,实现方法是再在JS里随机给开每一个 span 元素left和 ...
这个我还得再捣鼓捣鼓,感觉用自己帖里面还是要实践一下 小辣椒 发表于 2022-11-4 22:00
这个我还得再捣鼓捣鼓,感觉用自己帖里面还是要实践一下
代码很完整的,只需把代码放对位置(这个不难)。它比较适合深色背景的帖子 这个粒子能不能修改成 跟着音乐节奏跳动而跳动 那样的话特别棒{:4_196:} 风中飞尘 发表于 2022-11-4 22:07
这个粒子能不能修改成 跟着音乐节奏跳动而跳动 那样的话特别棒
我说过,要让音频带动粒子,需要 audio API,代码量太大太艰涩,不是非常适合做帖用。 马黑黑 发表于 2022-11-4 22:04
代码很完整的,只需把代码放对位置(这个不难)。它比较适合深色背景的帖子
好的,我试一下 小辣椒 发表于 2022-11-4 22:14
好的,我试一下
{:4_181:} 马黑黑 发表于 2022-11-4 22:11
我说过,要让音频带动粒子,需要 audio API,代码量太大太艰涩,不是非常适合做帖用。
用js HTML 调用嘛 风中飞尘 发表于 2022-11-4 22:19
用js HTML 调用嘛
就像你发的那个音频带动频谱,如果不使用 audio API,它是不行的。音频的振幅获取即使通过audio API也十分困难,一般会考虑使用服务器版本的JS做,不过网易云音乐的地址也带动不起,需要纯粹的音频地址。总而言之,我个人觉得这个不现实。 马黑黑 发表于 2022-11-4 22:27
就像你发的那个音频带动频谱,如果不使用 audio API,它是不行的。音频的振幅获取即使通过audio API也十 ...
{:4_197:}
页:
[1]
2