分析uni-app菊花loading的纯CSS绘制
<h2 id="背景">背景</h2><blockquote>
<p>继上拉加载——本着刨根问底的精神,挖了挖引用的uni-load-more组件,其实现比较容易理解,要说核心点,非CSS绘制的loading莫属了。小小的动画图,用到时直接引用就好了,不不不,千万不要这么想,所谓书到用时方恨少,可不是随口一说便成了千古名句的,没准哪天你就遇上了相关知识点,即使有万能度娘,也不能让你拥有灵活运用的能力——自我激励结束,接下来分析绘制过程吧。</p>
</blockquote>
<h2 id="知识点">知识点</h2>
<h4 id="1-keyframes规则">1. @keyframes规则</h4>
<p>通过该规则可以创建动画,实现从一套样式逐渐变化成另一套样式;</p>
<p>亦能够多次改变样式,以百分比规定改变的时间,关键字from和to相当于0%和100%,可以理解为动画中的帧画面</p>
<h4 id="2-animation属性">2. animation属性</h4>
<p>用来控制动画的外观,同时将动画与选择器绑定</p>
<blockquote>
<p>语法:animation: name duration timing-function delay iteration-count direction fill-mode play-state;</p>
</blockquote>
<p>常用属性值:</p>
<ul>
<li>
<p>name=@keyframes创建的关键帧名字</p>
</li>
<li>
<p>duration=完成一轮动画需要的时间</p>
</li>
<li>
<p>timing-function=动画显示的方式,可填值为:<br>
linear:匀速,ease:低速-加快-变慢,ease-in:低速开始,ease-out:低速结束,ease-in-out:低速开始和结束,cubic-bezier(n,n,n,n):自定义速度,n为0-1间的值,默认为ease</p>
</li>
<li>
<p>delay=延迟启动时间,单位为秒(s)或者毫秒(ms),默认为0<br>
若是为负值,则跳过定义时间启动动画</p>
</li>
<li>
<p>iteration-count=执行时间,默认为1,infinite为无限次</p>
<pre><code>其他三个属性了解即可,不算常用:
direction 属性定义是否循环交替反向播放动画
fill-mode 属性规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式
play-state属性指定动画是否正在运行或已暂停
</code></pre>
</li>
</ul>
<h4 id="3-transform属性">3. transform属性</h4>
<p>应用于元素的2D或3D转换。这个属性允许你将元素旋转,缩放,移动,倾斜等,此案例用到2D旋转rotate函数,指定角度即可旋转</p>
<h4 id="4-transform-origin属性">4. transform-origin属性</h4>
<p>用法:transform-origin: x-axis y-axis z-axis;</p>
<p>可以更改转换元素的位置,相当于旋转中心的位置,默认为50% 50% 0</p>
<h2 id="思路">思路</h2>
<p>若用绘画工具,应当是以下步骤去绘制,我们按照这个思路,用CSS将它实现。</p>
<p><img src="https://img2020.cnblogs.com/blog/1672584/202010/1672584-20201012081828067-1335193956.jpg"></p>
<h4 id="1-绘制旋转基图">1. 绘制旋转基图</h4>
<ul>
<li>
<p>定义标签,给所有的短杠赋予uni-load-view_wrapper样式</p>
</li>
<li>
<p>将短杠样式的定位position设置为绝对定位absolute,以便控制每一根短杠的位置</p>
</li>
<li>
<p>给短杠进行rotate旋转,并对每根短杠位置进行设置,制造出中空感</p>
</li>
</ul>
<h4 id="2-旋转基图">2. 旋转基图</h4>
<ul>
<li>
<p>将基图放在单独标签中,为一组,并设置(复制基图所在标签)其他两组标签,由于绝对定位,三组图形是重合的</p>
</li>
<li>
<p>对其中两组标签分别进行30度和60度旋转,达到图③的效果</p>
</li>
</ul>
<h4 id="3-添加渐变动画效果">3. 添加渐变动画效果</h4>
<p>十二根短杠都由高饱和到低饱和的过程(改变每根短杠的透明度),且每根的饱和程度均等差递减(动画延迟),所以:</p>
<ul>
<li>
<p>使用@keyframes规则创建动画load,通过form和to关键字(这是和0%到100%相同),实现透明度的降低</p>
</li>
<li>
<p>用动画延迟animation-delay来控制每根短杠开始动画的时间,实现不同的饱和度</p>
</li>
<li>
<p>给每根短杠uni-load-view_wrapper加上动画,animation: load .96s ease infinite,参数分别是动画名称、持续时间、显示方式、执行次数</p>
</li>
</ul>
<h2 id="代码">代码</h2>
<p>出自Hello uni-app项目模板中的uni-load-more</p>
<pre><code><template>
<view class="uni-load-more">
<view class="uni-load-more__img">
<view class="load1 load">
<view :style="{ background: color }" class="uni-load-view_wrapper" />
<view :style="{ background: color }" class="uni-load-view_wrapper" />
<view :style="{ background: color }" class="uni-load-view_wrapper" />
<view :style="{ background: color }" class="uni-load-view_wrapper" />
</view>
<view class="load2 load">
<view :style="{ background: color }" class="uni-load-view_wrapper" />
<view :style="{ background: color }" class="uni-load-view_wrapper" />
<view :style="{ background: color }" class="uni-load-view_wrapper" />
<view :style="{ background: color }" class="uni-load-view_wrapper" />
</view>
<view class="load3 load">
<view :style="{ background: color }" class="uni-load-view_wrapper" />
<view :style="{ background: color }" class="uni-load-view_wrapper" />
<view :style="{ background: color }" class="uni-load-view_wrapper" />
<view :style="{ background: color }" class="uni-load-view_wrapper" />
</view>
</view>
</view>
</template>
<style>
@charset "UTF-8";
.uni-load-more {
display: flex;
flex-direction: row;
height: 80upx;
align-items: center;
justify-content: center
}
.uni-load-more__img {
position: relative;
height: 24px;
width: 24px;
margin-right: 10px;
}
.uni-load-more__img>.load {
position: absolute
}
.uni-load-more__img>.load .uni-load-view_wrapper {
width: 6px;
height: 2px;
background: #999;
position: absolute;
opacity: .2;
transform-origin: 50%;
animation: load .96s ease infinite
}
.uni-load-more__img>.load .uni-load-view_wrapper:nth-child(1) {
transform: rotate(90deg);
top: 2px;
left: 9px
}
.uni-load-more__img>.load .uni-load-view_wrapper:nth-child(2) {
transform: rotate(180deg);
top: 11px;
right: 0
}
.uni-load-more__img>.load .uni-load-view_wrapper:nth-child(3) {
transform: rotate(270deg);
bottom: 2px;
left: 9px
}
.uni-load-more__img>.load .uni-load-view_wrapper:nth-child(4) {
top: 11px;
left: 0
}
.load1,
.load2,
.load3 {
height: 24px;
width: 24px
}
.load2 {
transform: rotate(30deg)
}
.load3 {
transform: rotate(60deg)
}
.load1 .uni-load-view_wrapper:nth-child(1) {
animation-delay: 0s
}
.load2 .uni-load-view_wrapper:nth-child(1) {
animation-delay: 80ms
}
.load3 .uni-load-view_wrapper:nth-child(1) {
animation-delay: .16s
}
.load1 .uni-load-view_wrapper:nth-child(2) {
animation-delay: .24s
}
.load2 .uni-load-view_wrapper:nth-child(2) {
animation-delay: .32s
}
.load3 .uni-load-view_wrapper:nth-child(2) {
animation-delay: .40s
}
.load1 .uni-load-view_wrapper:nth-child(3) {
animation-delay: .48s
}
.load2 .uni-load-view_wrapper:nth-child(3) {
animation-delay: .56s
}
.load3 .uni-load-view_wrapper:nth-child(3) {
animation-delay: .64s
}
.load1 .uni-load-view_wrapper:nth-child(4) {
animation-delay: .72s
}
.load2 .uni-load-view_wrapper:nth-child(4) {
animation-delay: .8s
}
.load3 .uni-load-view_wrapper:nth-child(4) {
animation-delay: .88s
}
@-webkit-keyframes load {
0% {
opacity: 1
}
100% {
opacity: .2
}
}
</style>
</code></pre>
<h2 id="总结">总结</h2>
<blockquote>
<p>掌握CSS动画的运用可以为页面添彩不少,分析至细节目的就是为了能够灵活运用,每天进步一点点,加油吧!</p>
</blockquote><br><br>
来源:https://www.cnblogs.com/nmrnzb/p/13800789.html 顶一个! 感谢楼主的详细分析~
之前用uni-load-more的时候只想着能跑就行,没仔细研究过这个loading动画是怎么实现的。看了楼主的分析才明白,原来是用12根短杠通过不同角度旋转和动画延迟来模拟那种旋转的视觉效果,确实很巧妙!
有个小问题想请教一下:
看到代码里用了三组load(load1、load2、load3),每组4个短杠,然后分别旋转30度和60度。这个思路我能理解,但如果不用这种分组的方式,直接用12个view分别设置不同的rotate角度,能实现同样的效果吗?两种方案各有什么优缺点呢?
另外感觉楼主的总结说得很好:"掌握CSS动画的运用可以为页面添彩不少"。虽然现在很多组件都封装好了,但自己动手分析一遍真的很有收获,以后遇到类似的需求也能灵活运用了。
期待楼主更多类似的深度分析帖子!https://img2020.cnblogs.com/blog/1672584/202010/1672584-20201012081828067-1335193956.jpg 这个配图也很清晰,赞一个~
頁:
[1]