CSS怎样画涟漪
本帖最后由 马黑黑 于 2022-2-3 08:48 编辑 <br /><br />此前我们讨论了单个雨丝的CSS绘制,今天来画个涟漪。<p></p><div><br></div><div>雨丝是直的用直线表示,涟漪大致是圆的,所以用圆圈来模拟。做一个 1*1 无背景的元素,令其1像素的边框完成圆圈,边框的样式可以是 solid,dashed,dotted,多试几次看哪一个更合适。然后设计一个 @keyframes 变化过程令其变大、消失。制作中巧妙使用 opacity 不透明属性调节变化过程的可视度,达到逼近自然的观感。</div><div><br></div><div>同样的,涟漪也需要展示场景,就是说,涟漪自身依托于一个子元素 div 而存在,而这个子 div 隶属于一个父 div,父 div 给子div 提供模拟涟漪的场地。这里,我们仍然使用 <a href="https://www.huachaowang.com/forum.php?mod=viewthread&tid=56655&extra=page%3D1">CSS如何模拟雨丝</a> 布置的场景,相关背景的营造请参照该帖子的一楼。</div><div><br></div><div>一、CSS绘制涟漪的代码:</div><div><br></div><div><div>.circle {</div><div><span style="white-space:pre"> </span><font color="#8b0000">position: absolute;</font></div><div><span style="white-space:pre"> </span>left: 80px;</div><div><span style="white-space:pre"> </span>top: 80%;</div><div><span style="white-space:pre"> </span><font color="#8b0000">width: 1px;</font></div><div><font color="#8b0000"><span style="white-space:pre"> </span>height: 1px;</font></div><div><span style="white-space:pre"> </span><font color="#ff0000">background: none;</font></div><div><span style="white-space:pre"> </span><font color="#ff0000">border: 1px dotted #eee;</font></div><div><span style="white-space:pre"> </span><font color="#ff0000">border-radius: 50%;</font></div><div><span style="white-space:pre"> </span><font color="#ff0000">opacity: 0.2;</font></div><div><span style="white-space:pre"> </span>animation:<font color="#0000ff">circle</font> 1s ease-out infinite;</div><div>}</div></div><div><br></div><div>上面的代码,涟漪元素样式表类名叫 circle,它绝对定位;left和top都设定有值,是配合雨丝位置而定的,可以灵活改变;高宽都是1px,其实0px也是可以的,甚至不设置width和height也可是完全可以的,因为它的实际外观将由动画来演变;背景色无,边框1px、点状、接近白色;不透明度0.2,透明度较高了;然后通过 animation 调用马上设计的 circle 动画(动画名称可随意,对得上就行)——</div><div><br></div><div>二、CSS <span id="kM0.413728012591859">@keyframes 动画设计:</span></div><div><span><br></span></div><div><div>@keyframes <font color="#0000ff">circle</font> {</div><div><span style="white-space:pre"> </span>0% { width:0; height:0; }</div><div><span style="white-space:pre"> </span>50% { opacity:0.1; width:5%; height:5%; }</div><div><span style="white-space:pre"> </span>60% { opacity:0; width:5%; height:5%; }</div><div><span style="white-space:pre"> </span>100% { opacity:0; width:5%; height:5%; }</div><div>}</div></div><div><br></div><div>这里,将动画过程设定为4个步骤,实际上就三种状态:从无到有。60%和100%是一模一样的,设为不可见,是想让50%时的状态持续动画过程的一半的时长,就是说让涟漪最大状态时停留一小阵子。至于高宽的百分比,它是基于父窗体计算的,所以具体用到百分之几还需考虑父元素的高宽,其实也可以用多少个像素来指定涟漪变到最大时的尺寸。</div><div><br></div><div>就酱。效果看下楼雨丝和涟漪合在一起的演示。</div> 本帖最后由 马黑黑 于 2022-2-3 09:40 编辑 <br /><br /><style type="text/css">.papaDiv {
margin: auto;
position: relative;
background: #333;
width: 700px;
height: 460px;
}
/* 雨丝 */
.rain {
width: 1px;
height: 4px;
top: -5px;
left: 100px;
background: #eee;
position: absolute;
animation: rain 0.5s linear infinite;
}
/* 涟漪 */
.circle {
position: absolute;
left: 80px;
top: 80%;
width: 1px;
height: 1px;
background: none;
border: 1px dotted #eee;
border-radius: 50%;
opacity: 0.2;
animation:circle 1s ease-out infinite;
}
@keyframes rain {
0% { opacity:0.2; }
100% { opacity:0.5; top:80%;}
}
@keyframes circle {
0% { width:0; height:0; }
50% { opacity:0.1; width:5%; height:5%; }
60% { opacity:0; width:5%; height:5%; }
100% { opacity:0; width:5%; height:5%; }
}
</style>
<div id="papaDiv" class="papaDiv">
<div class="rain"></div>
<div class="circle"></div>
</div>
本帖最后由 马黑黑 于 2022-2-3 08:50 编辑
二楼效果全部代码:
<style type="text/css">
.papaDiv {
margin: auto;
position: relative;
background: #333;
width: 800px;
height: 460px;
}
/* 雨丝 */
.rain {
width: 1px;
height: 4px;
top: -5px;
left: 100px;
background: #eee;
position: absolute;
animation: rain 0.5s linear infinite;
}
/* 涟漪 */
.circle {
position: absolute;
left: 80px;
top: 80%;
width: 1px;
height: 1px;
background: none;
border: 1px dotted #eee;
border-radius: 50%;
opacity: 0.2;
animation:circle 1s ease-out infinite;
}
@keyframes rain {
0% { opacity:0.2; }
100% { opacity:0.5; top:80%;}
}
@keyframes circle {
0% { width:0; height:0; }
50% { opacity:0.1; width:5%; height:5%; }
60% { opacity:0; width:5%; height:5%; }
100% { opacity:0; width:5%; height:5%; }
}
</style>
<div id="papaDiv" class="papaDiv">
<div class="rain"></div>
<div class="circle"></div>
</div>
雨丝的批量生成已介绍过,涟漪的批量生成的实现思路是一样的:
for(j=0; j<20; j++){
var circle = document.createElement('div');
var cLeft = Math.floor(Math.random() * 100);
var cTop =Math.round(Math.random()*20+70);
var cTime = Math.random();
circle.className = "circle";
circle.style.left = cLeft + "%";
circle.style.top = cTop + "%";
circle.style.animation = "circle " +cTime + "s ease-out infinite";
papa.appendChild(circle);
}
我们用JS的for语句生成20个随机的涟漪,涟漪的水平方向 cLeft 分布在 0%-100% 之间、垂直方向 cTOp 分布在 20%-90%之间(水平方向如需限制范围可参照 cTop 的取值方式)。动画时长的随机生成数值也是在0-0.9秒之间,与雨丝接近合拍。
效果看下楼,注意给 papaDiv 弄个id索引。
本帖最后由 马黑黑 于 2022-2-3 09:43 编辑 <br /><br /><style type="text/css">
.papa {
margin: auto;
position: relative;
background: #333;
width: 700px;
height: 460px;
display: block;
}
/* 雨丝 */
.rain {
width: 1px;
height: 4px;
top: -5px;
left: 100px;
background: #eee;
position: absolute;
animation: rain 0.5s linear infinite;
}
/* 涟漪 */
.circle {
position: absolute;
left: 80px;
top: 80%;
width: 1px;
height: 1px;
background: none;
border: 1px dotted #eee;
border-radius: 50%;
opacity: 0.2;
animation:circle 1s ease-out infinite;
}
@keyframes rain {
0% { opacity:0.2; }
100% { opacity:0.5; top:80%;}
}
@keyframes circle {
0% { width:0; height:0; }
50% { opacity:0.1; width:5%; height:5%; }
60% { opacity:0; width:5%; height:5%; }
100% { opacity:0; width:5%; height:5%; }
}
</style>
<div id="papa" class="papa">
<div class="rain"></div>
<div class="circle"></div>
</div>
<script language="javascript">
function addrain() {
var papa = document.getElementById('papa');
for(i=0; i<50; i++) { //50个雨丝
var rain = document.createElement('div');
var rLeft = Math.ceil(Math.random()*100);
var aTime = Math.random();
rain.className = "rain";
rain.style.left = rLeft + "%";
rain.style.animation = "rain " + aTime + "s linear infinite";
papa.appendChild(rain);
}
for(j=0; j<20; j++){ // 20个涟漪
var circle = document.createElement('div');
var cLeft = Math.floor(Math.random() * 100);
var cTop =Math.round(Math.random()*20+70);
var cTime = Math.random();
circle.className = "circle";
circle.style.left = cLeft + "%";
circle.style.top = cTop + "%";
circle.style.animation = "circle " +cTime + "s ease-out infinite";
papa.appendChild(circle);
}
}
addrain();
</script> 5楼完整代码(为了避免与前面演示的相冲突,一些名称略作改变):
<style type="text/css">
.papa {
margin: auto;
position: relative;
background: #333;
width: 700px;
height: 460px;
display: block;
}
/* 雨丝 */
.rain {
width: 1px;
height: 4px;
top: -5px;
left: 100px;
background: #eee;
position: absolute;
animation: rain 0.5s linear infinite;
}
/* 涟漪 */
.circle {
position: absolute;
left: 80px;
top: 80%;
width: 1px;
height: 1px;
background: none;
border: 1px dotted #eee;
border-radius: 50%;
opacity: 0.2;
animation:circle 1s ease-out infinite;
}
@keyframes rain {
0% { opacity:0.2; }
100% { opacity:0.5; top:80%;}
}
@keyframes circle {
0% { width:0; height:0; }
50% { opacity:0.1; width:5%; height:5%; }
60% { opacity:0; width:5%; height:5%; }
100% { opacity:0; width:5%; height:5%; }
}
</style>
<div id="papa" class="papa">
<div class="rain"></div>
<div class="circle"></div>
</div>
<script language="javascript">
function addrain() {
var papa = document.getElementById('papa');
for(i=0; i<50; i++) { //50个雨丝
var rain = document.createElement('div');
var rLeft = Math.ceil(Math.random()*100);
var aTime = Math.random();
rain.className = "rain";
rain.style.left = rLeft + "%";
rain.style.animation = "rain " + aTime + "s linear infinite";
papa.appendChild(rain);
}
for(j=0; j<20; j++){ // 20个涟漪
var circle = document.createElement('div');
var cLeft = Math.floor(Math.random() * 100);
var cTop =Math.round(Math.random()*20+70);
var cTime = Math.random();
circle.className = "circle";
circle.style.left = cLeft + "%";
circle.style.top = cTop + "%";
circle.style.animation = "circle " +cTime + "s ease-out infinite";
papa.appendChild(circle);
}
}
addrain();
</script>
学习了,谢谢老黑!{:4_190:} 五楼好一场急雨,很逼真的感觉{:4_187:} 这些代码语句太神奇了{:4_199:} 加林森 发表于 2022-2-3 11:25
学习了,谢谢老黑!
{:4_190:} 红影 发表于 2022-2-3 11:56
这些代码语句太神奇了
JS有些复杂,我得专门讲一讲 createElement 和 appendChild 马黑黑 发表于 2022-2-3 11:56
谢谢! 红影 发表于 2022-2-3 11:53
五楼好一场急雨,很逼真的感觉
动画运行时长越短,连续性就越好吧 马黑黑 发表于 2022-2-3 11:57
JS有些复杂,我得专门讲一讲 createElement 和 appendChild
这个涟漪比前面那个帖子里的好,这个里面是随机的,更真实。 红影 发表于 2022-2-3 15:03
这个涟漪比前面那个帖子里的好,这个里面是随机的,更真实。
那个也是随机的,它们没有那么模糊,而且border用的是实线,所以感觉不那么好 马黑黑 发表于 2022-2-3 15:54
那个也是随机的,它们没有那么模糊,而且border用的是实线,所以感觉不那么好
哦,比较了一下,还是这里的感觉更真实呢。 红影 发表于 2022-2-3 16:31
哦,比较了一下,还是这里的感觉更真实呢。
嗯,通过你的感受,我加入了一些看不着的机制,让效果更具欺骗性 马黑黑 发表于 2022-2-3 21:34
嗯,通过你的感受,我加入了一些看不着的机制,让效果更具欺骗性
黑黑厉害{:4_187:} 红影 发表于 2022-2-4 14:56
黑黑厉害
(=@__@=)哪里?(=@__@=)哪里? 马黑黑 发表于 2022-2-5 16:15
(=@__@=)哪里?(=@__@=)哪里?
又换了个谦虚语啊{:4_173:}
页:
[1]
2