马黑黑 发表于 2022-2-3 08:44

CSS怎样画涟漪

本帖最后由 马黑黑 于 2022-2-3 08:48 编辑 <br /><br />此前我们讨论了单个雨丝的CSS绘制,今天来画个涟漪。<p></p><div><br></div><div>雨丝是直的用直线表示,涟漪大致是圆的,所以用圆圈来模拟。做一个 1*1 无背景的元素,令其1像素的边框完成圆圈,边框的样式可以是&nbsp;solid,dashed,dotted,多试几次看哪一个更合适。然后设计一个 @keyframes&nbsp;变化过程令其变大、消失。制作中巧妙使用 opacity&nbsp;不透明属性调节变化过程的可视度,达到逼近自然的观感。</div><div><br></div><div>同样的,涟漪也需要展示场景,就是说,涟漪自身依托于一个子元素 div 而存在,而这个子 div 隶属于一个父 div,父 div 给子div 提供模拟涟漪的场地。这里,我们仍然使用&nbsp;<a href="https://www.huachaowang.com/forum.php?mod=viewthread&amp;tid=56655&amp;extra=page%3D1">CSS如何模拟雨丝</a>&nbsp;布置的场景,相关背景的营造请参照该帖子的一楼。</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>上面的代码,涟漪元素样式表类名叫&nbsp;circle,它绝对定位;left和top都设定有值,是配合雨丝位置而定的,可以灵活改变;高宽都是1px,其实0px也是可以的,甚至不设置width和height也可是完全可以的,因为它的实际外观将由动画来演变;背景色无,边框1px、点状、接近白色;不透明度0.2,透明度较高了;然后通过&nbsp;animation 调用马上设计的&nbsp;circle 动画(动画名称可随意,对得上就行)——</div><div><br></div><div>二、CSS&nbsp;<span id="kM0.413728012591859">@keyframes&nbsp;动画设计:</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 08:48

本帖最后由 马黑黑 于 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:48

本帖最后由 马黑黑 于 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>

马黑黑 发表于 2022-2-3 09:29

雨丝的批量生成已介绍过,涟漪的批量生成的实现思路是一样的:

        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:30

本帖最后由 马黑黑 于 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>

马黑黑 发表于 2022-2-3 09:45

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>

加林森 发表于 2022-2-3 11:25

学习了,谢谢老黑!{:4_190:}

红影 发表于 2022-2-3 11:53

五楼好一场急雨,很逼真的感觉{:4_187:}

红影 发表于 2022-2-3 11:56

这些代码语句太神奇了{:4_199:}

马黑黑 发表于 2022-2-3 11:56

加林森 发表于 2022-2-3 11:25
学习了,谢谢老黑!

{:4_190:}

马黑黑 发表于 2022-2-3 11:57

红影 发表于 2022-2-3 11:56
这些代码语句太神奇了

JS有些复杂,我得专门讲一讲 createElement 和 appendChild

加林森 发表于 2022-2-3 12:03

马黑黑 发表于 2022-2-3 11:56


谢谢!

马黑黑 发表于 2022-2-3 13:29

红影 发表于 2022-2-3 11:53
五楼好一场急雨,很逼真的感觉

动画运行时长越短,连续性就越好吧

红影 发表于 2022-2-3 15:03

马黑黑 发表于 2022-2-3 11:57
JS有些复杂,我得专门讲一讲 createElement 和 appendChild

这个涟漪比前面那个帖子里的好,这个里面是随机的,更真实。

马黑黑 发表于 2022-2-3 15:54

红影 发表于 2022-2-3 15:03
这个涟漪比前面那个帖子里的好,这个里面是随机的,更真实。

那个也是随机的,它们没有那么模糊,而且border用的是实线,所以感觉不那么好

红影 发表于 2022-2-3 16:31

马黑黑 发表于 2022-2-3 15:54
那个也是随机的,它们没有那么模糊,而且border用的是实线,所以感觉不那么好

哦,比较了一下,还是这里的感觉更真实呢。

马黑黑 发表于 2022-2-3 21:34

红影 发表于 2022-2-3 16:31
哦,比较了一下,还是这里的感觉更真实呢。

嗯,通过你的感受,我加入了一些看不着的机制,让效果更具欺骗性

红影 发表于 2022-2-4 14:56

马黑黑 发表于 2022-2-3 21:34
嗯,通过你的感受,我加入了一些看不着的机制,让效果更具欺骗性

黑黑厉害{:4_187:}

马黑黑 发表于 2022-2-5 16:15

红影 发表于 2022-2-4 14:56
黑黑厉害

(=@__@=)哪里?(=@__@=)哪里?

红影 发表于 2022-2-5 20:05

马黑黑 发表于 2022-2-5 16:15
(=@__@=)哪里?(=@__@=)哪里?

又换了个谦虚语啊{:4_173:}
页: [1] 2
查看完整版本: CSS怎样画涟漪