今日,群友提问,如何实现这么一个 Loading 效果:
这个确实有点意思,但是这是 CSS 能够完成的?
没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现,就是所需的元素可能多点。参考我们之前的:
首先,我们可能需要实现这样一段圆弧:
这里需要用到的技术是:
角向渐变 conic-gradient() + mask 以及两个伪元素。图片示意如下:
核心代码如下图:
<div class="g-container">
<div class="g-circle"></div>
</div>
:root {
--headColor: hsl(130, 75%, 75%);
--endColor: hsl(60, 75%, 40%);
}
.g-container {
position: relative;
background: #000;
}
.g-circle {
position: relative;
width: 300px;
height: 300px;
border-radius: 50%;
background: conic-gradient(
var(--headColor) 0,
var(--headColor) 10%,
hsl(120, 75%, 70%),
hsl(110, 75%, 65%),
hsl(100, 75%, 60%),
hsl(90, 75%, 55%),
hsl(80, 75%, 50%),
hsl(70, 75%, 45%),
var(--endColor) 30%,
var(--endColor) 35%,
transparent 35%
);
mask: radial-gradient(transparent, transparent 119px, #000 120px, #000 120px, #000 100%);
&::before,
&::after {
content: "";
position: absolute;
inset: 0;
width: 30px;
height: 30px;
background: var(--headColor);
top: 0;
left: 135px;
border-radius: 50%;
}
&::after {
background: var(--endColor);
left: unset;
top: 214px;
right: 26px;
}
}
这样,我们就得到了这样一个图形:
接下来,我们来实现尾部气泡向外扩散的效果。
由于这里涉及了多个气泡的不同运动动画,多个标签元素肯定是少不了了。
因此,接下来我们要做的事情:
animation-delay,造成动画上的先后顺序,并以此形成整个无限循环的气泡扩散动画这里,由于有许多小气泡的动画,这个数量,我设置成了 100。那肯定是不能一个一个手写它们的动画代码,需要借助 SASS/LESS 等预处理器的循环、随机等函数。
核心代码如下:
<div class="g-container">
<div class="g-circle"></div>
<ul class="g-bubbles">
<li class="g-bubble"></li>
// ... 共 100 个 bubble 元素
<li class="g-bubble"></li>
</ul>
</div>
// 上面圆环的代码,保持一致,下面只补充气泡动画的代码
.g-bubbles {
position: absolute;
width: 30px;
height: 30px;
border-radius: 50px;
top: 100px;
left: 235px;
background: var(--headColor);
}
.g-bubble {
position: absolute;
border-radius: 50%;
background-color: inherit;
}
@for $i from 1 through 100 {
.g-bubble:nth-child(#{$i}) {
--rotate: calc(#{random(360)} * 1deg);
--dis: calc(#{random(100)} * 1px);
--width: calc(3px + #{random(25)} * 1px);
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: var(--width);
height: var(--width);
animation: move #{(random(1500) + 1500) / 1000}s ease-in-out -#{random(3000) / 1000}s infinite;
}
}
@keyframes move {
0% {
transform: translate(-50%, -50%) rotate(0deg);
}
75% {
opacity: .9;
}
100% {
transform: rotateZ(var(--rotate)) translate(-50%, var(--dis));
opacity: .4;
}
}
核心在于 @for $i from 1 through 100 { } 这段 SASS 代码内部,我们实现了上面说的 (2)(3)(4) 的功能点!
这样,我们就得到了这样一个效果,在尾部有大量气泡动画,不断向外扩散的效果:
OK,到这里整个效果基本就做完了。当然,也是剩下最后最重要的一步,需要让多个气泡之间产生一种粘性融合的效果。
这个技巧在此前非常多篇文章中,也频繁提及过,就是利用 filter: contrast() 滤镜与 filter: blur() 滤镜。
如果你还不了解这个技巧,可以戳我的这篇文章看看:你所不知道的 CSS 滤镜技巧与细节
简述下该技巧:
单独将两个滤镜拿出来,它们的作用分别是:
filter: blur(): 给图像设置高斯模糊效果。filter: contrast(): 调整图像的对比度。但是,当他们“合体”的时候,产生了奇妙的融合现象。
仔细看两圆相交的过程,在边与边接触的时候,会产生一种边界融合的效果,通过对比度滤镜把高斯模糊的模糊边缘给干掉,利用高斯模糊实现融合效果。
基于此,我们再简单改造下我们的 CSS 代码,所需要加的代码量非常少:
.g-container {
// ... 保持一致
background: #000;
filter: blur(3px) contrast(5);
animation: rotate 4s infinite linear;
}
@keyframes rotate {
100% {
transform: rotate(360deg);
filter: blur(3px) contrast(5) hue-rotate(360deg);
}
}
就这样,我们就大致还原了题图的效果:
完整的代码,你可以戳这里:CodePen Demo -- Pure CSS Loading Animation
当然,上面的效果,乍一看还行,仔细看,违和感很重。
原因在于,扩散出来的小球也跟着半圆环一起进行了旋转动画,看上去就有点奇怪。
正确的做法应该是,圆环尾部的气泡应该是原地发散消失的。
那么,怎么能够做到气泡效果,一直发生在圆环的尾部,同时消失的时候又不跟着整个圆环一起进行旋转呢?我们想要的最终效果,应该是这样:
这里,我们可以拆解一下。想象,如果去掉圆环的旋转,其实我们只需要实现这样一个效果即可:
整个动画的核心就转变成了如何实现这么一个效果。看似复杂,其实也很好做。
首先,我们重新改造一下上述的 .g-bubbles。
<div class="g-container">
<div class="g-circle"></div>
<ul class="g-bubbles">
<li class="g-bubble"></li>
// ... 共 200 个 bubble 元素
<li class="g-bubble"></li>
</ul>
</div>
.g-bubbles {
position: absolute;
width: 30px;
height: 30px;
transform: translate(-50%, -50%);
left: 50%;
top: 50%;
border-radius: 50px;
}
.g-bubble {
position: absolute;
inset: 0;
border-radius: 50%;
background: hsl(60, 75%, 40%);
}
得到这么一个效果,所有圆形小点,都暂时汇聚在容器的中心:
这里需要简单解释一下:
其次,我们借助 SASS,按照元素的顺序,把它们顺序排列到圆环轨迹之上:
$count: 200;
@for $i from 1 through $count {
.g-bubble:nth-child(#{$i}) {
--rotate: calc(#{360 / $count} * #{$i} * 1deg);
transform:
rotateZ(var(--rotate))
translate(135px, 0);
opacity: 1;
}
}
由于我们设置了 div 小球的个数为 200 个,这样,我们就得到了一圈由 200 个圆形小球形成的圆环:
接下来这一步非常重要,我们设定一个动画:
75% ~ 100% 阶段做透明度从 1 到 0 的变换,而 0% ~ 75% 的阶段保持透明度为 0@for $i from 1 through $count {
.g-bubble:nth-child(#{$i}) {
--rotate: calc(#{360 / $count} * #{$i} * 1deg);
--delayTime: calc(4000 * #{$i / $count} * -1ms);
transform:
rotateZ(var(--rotate))
translate(135px, 0);
opacity: 1;
animation: showAndHide 4000ms linear var(--delayTime) infinite;
}
}
@keyframes showAndHide {
0% {
opacity: 0;
}
75% {
opacity: 0;
}
75.1% {
opacity: 1;
}
100% {
opacity: 0;
}
}
这样,我们就得到了一个圆形小球气泡围绕圆环渐次消失的效果:
配合上整个圆环,效果就会是这样:
很接近了,但是没有随机的感觉,气泡也没有散开的动画。解决的方案:
当然,整个动画的基础,还是在容器设置了 滤镜 blur() 和 contrast() 的加持之下的,这样,我们给气泡再补上随机动画散开及缩放的动画:
@for $i from 1 through $count {
.g-bubble:nth-child(#{$i}) {
--rotate: calc(#{360 / $count} * #{$i} * 1deg);
--delayTime: calc(4000 * #{$i / $count} * -1ms);
--scale: #{0.4 + random(10) / 10};
--x: #{-100 + random(200)}px;
--y: #{-100 + random(200)}px;
transform:
rotateZ(var(--rotate))
translate(135px, 0);
opacity: 1;
animation: showAndHide 4000ms linear var(--delayTime) infinite;
}
}
@keyframes showAndHide {
0% {
transform:
rotateZ(var(--rotate))
translate(135px, 0);
opacity: 0;
}
75% {
opacity: 0;
}
75.1% {
transform:
rotateZ(var(--rotate))
translate(135px, 0)
scale(var(--scale));
opacity: 1;
}
100% {
transform:
rotateZ(var(--rotate))
translate(calc(135px + var(--x)), var(--y))
scale(.2);
opacity: 0;
}
}
只看一圈的气泡圆形,我们能得到了这样的效果:
配合上圆环的效果:
配合上父容器的 filter: hue-rotate() 动画,就能实现颜色的动态变换,得到我们最终想要的效果:
这样,没有了第一版本的违和感,整个效果也显得比较自然。
完整的代码,你可以戳这里:CodePen Demo -- Pure CSS Loading Animation
好了,本文到此结束,希望对你有帮助 ?
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
这个问题在这里已经有了答案:WhatisRuby'sdouble-colon`::`?(12个答案)关闭8年前。什么是::?@song||=::TwelveDaysSong.new
这个问题在这里已经有了答案:Whatdoes`if__FILE__==$0`meaninRuby(6个答案)关闭6年前。我在审查Ruby代码时偶然发现了这个语法。代码是:if__FILE__==$PROGRAM_NAME#somecode...end我想__FILE__是一个变量,可以让我获取我所在文件的名称?但是$PROGRAM_NAME简化了什么?另外,为什么这个if语句是必需的,因为程序可以使用或不使用它?
我在一个我想在formtasticGem中覆盖的方法中找到了这个。该方法如下所示:defto_htmlinput_wrappingdohidden_field_html是什么意思?在第三行做什么?我知道它对数组有什么作用,但在这里我不知道。 最佳答案 你可以这样读:hidden_field_htmllabel_with_nested_checkbox是连接到hidden_field_html末尾的参数-为了“清晰”,他们将其分成两行 关于ruby-on-rails-没有参数的`
我正在尝试学习Ruby词法分析器和解析器(whitequarkparser)以了解更多有关从Ruby脚本进一步生成机器代码的过程。在解析以下Ruby代码字符串时。defadd(a,b)returna+bendputsadd1,2它导致以下S表达式符号。s(:begin,s(:def,:add,s(:args,s(:arg,:a),s(:arg,:b)),s(:return,s(:send,s(:lvar,:a),:+,s(:lvar,:b)))),s(:send,nil,:puts,s(:send,nil,:add,s(:int,1),s(:int,3))))任何人都可以向我解释生成的
谁能帮我理解下面的表达方式?printf("%3d-%s\n",counter,name)该行打印类似这样的内容6-安装Adobe软件我查阅了资料并阅读了引用资料,但找不到简单的答案,我有点困惑。如果你能给我一个好的引用,请这样做。%3d好的,根据我的理解,%3d是字符数或空格数。请指出解释它的引用资料。%s\n我不知道这是做什么的。我猜\n是一个换行符或类似的东西,但通过查看输出,它似乎并不像那样工作。为什么counter和name变量用逗号分隔?通过查看输出,似乎%3d被替换为counter而%s\n被替换为名称。我不确定它是如何工作的,但我想了解它。
我是ruby语言的新手,所以当我尝试按值对哈希进行排序时我用这个方法排序:movie_popularity.sort_by{|m,p|p}.reverse但是sort方法返回一个数组,而我需要返回一个散列,所以我使用了这个命令:movie_popularity=Hash[*movie_popularity.sort_by{|m,p|p}.reverse.flatten]我的问题是上面一行中的*和flatten是什么意思?谢谢=) 最佳答案 *被称为“splat运算符”;我不确定我能否给你技术上的定义(虽然我相信你会在谷歌的帮助下
这个问题在这里已经有了答案:Ruby|=assignmentoperator(4个答案)关闭9年前。在ruby中,|=操作符是做什么的?示例:a=23a|=3333#=>3351
每当我尝试运行该程序时,都会弹出一条错误消息“条件字符串文字(第10行)”。我做错了什么?puts"Welcometothebestcalculatorthereis.Wouldyouliketo(a)calculatetheareaofageometricshapeor(b)calculatetheequationofaparabola?Pleaseenteran'a'ora'b'togetstarted."response=gets.chompifresponse=="a"or"A"puts"ok."elsifresponse=="b"or"B"puts"awesome."else
运行下面的代码,a=[1,2,3,4,5]head,*tail=apheadptail你会得到结果1[2,3,4,5]谁能帮我解释一下语句head,*tail=a,谢谢! 最佳答案 head,*tail=a表示将数组a的第一个元素赋值给head,其余元素赋值到尾部。*,有时称为“splat运算符”,可以对数组执行多种操作。当它位于赋值运算符(=)的左侧时,如您的示例所示,它仅表示“保留所有剩余内容”。如果您在该代码中省略了splat,它将改为执行以下操作:head,tail=[1,2,3,4,5]phead#=>1ptail#=>2
Ruby常量的真正含义是什么?以下代码不显示任何“常量”属性。警告在那里,但我仍然要更改A所指的内容。A=1putsA#=>1A=2#warning:alreadyinitializedconstantAputsA#=>2或者说Ruby常量只是一种指示,没有任何强制措施? 最佳答案 没错,constants就像ruby中的variables,但如果您更改它们,您会收到警告。此外,与纯变量有一个区别:您可以访问常量,即使它们是在另一个类或模块中定义的,例如给定以下代码段:moduleConstantsPI=3,1415other=