在web应用中,前端同窗在实现动画效果时每每经常使用的几种方案:css
在大多数需求中,css3的 transition / animation
都能知足咱们的需求,而且相对于js实现,能够大大提高咱们的开发效率,下降开发成本。html
本篇文章将着重对 animation
的使用作个总结,若是你的工做中动画需求较多,相信本篇文章可以让你有所收获:前端
介绍完 animation 经常使用属性,为了将这些属性更好地理解与运用,下面将手把手实现一些DEMO具体讲述css3
经过修改内容在父元素中的y轴的位置来实现广播效果git
@keyframes scroll {
0%{
transform: translate(0, 0);
}
100%{
transform: translate(0, -$height);
}
}
.ul {
animation-name: scroll;
animation-duration: 5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
/* animation: scroll 5s linear infinite; 动画属性简写 */
}
复制代码
此处为了保存广播滚动效果的连贯性,防止滚动到最后一帧时没有内容,
须要多添加一条重复数据进行填充
github
<div class="ul">
<div class="li">小刘同窗加入了凹凸实验室</div>
<div class="li">小邓同窗加入了凹凸实验室</div>
<div class="li">小李同窗加入了凹凸实验室</div>
<div class="li">小王同窗加入了凹凸实验室</div>
<!-- 插入用于填充的数据数据 -->
<div class="li">小刘同窗加入了凹凸实验室</div>
</div>
复制代码
经过将过渡动画拆分为多个阶段,每一个阶段的top属性停留在不一样的位置来实现web
/* 规定动画,改变top,opacity */
@keyframes animate {
0% {
top: -100%;
opacity: 0;
}
25% {
top: 60;
opacity: 1;
}
50% {
top: 48%;
opacity: 1;
}
75% {
top: 52%;
opacity: 1;
}
100%{
top: 50%;
opacity: 1;
}
}
复制代码
为了让过渡效果更天然,这里经过
cubic-bezier()
函数定义一个贝塞尔曲线来控制动画播放速度segmentfault
过渡动画执行完后,为了将让元素应用动画最后一帧的属性值,咱们须要使用
animation-fill-mode: forwards
app
.popup {
animation-name: animate;
animation-duration: 0.5s;
animation-timing-function: cubic-bezier(0.21, 0.85, 1, 1);
animation-iteration-count: 1;
animation-fill-mode: forwards;
/* animation: animate 0.5s cubic-bezier(0.21, 0.85, 1, 1) 1 forwards; 动画属性简写 */
}
复制代码
相信大多数同窗都知道点赞效果,本文章会实现一个简易版的点赞效果,主要讲述一下实现思路:svg
1.为了让气泡能够向上偏移,咱们须要先实现一个y轴方向上移动的 @keyframes 动画
/* 规定动画,改变y轴偏移距离*/
@keyframes animation-y {
0%{
transform: translate(-50%, 100px) scale(0);
}
50%{
transform: translate(-50%, -100px) scale(1.5);
}
100%{
transform: translate(-50%, -300px) scale(1.5);
}
}
复制代码
2.为了让气泡向上偏移时显得不太单调,咱们能够再实现一个x轴方向上移动的 @keyframes 动画
/* 规定动画,改变x轴偏移距离 */
@keyframes animation-x {
0%{
margin-left: 0px;
}
25%{
margin-left: 25px;
}
75%{
margin-left: -25px;
}
100%{
margin-left: 0px;
}
}
复制代码
这里我理解:
修改 margin
来改变x轴偏移距离,但实际上与修改 transform
没有太大的性能差别@keyframes animation-y
中的 transform
已经新建了一个渲染层 ( PaintLayers )
animation
属性 可让该渲染层提高至 合成层(Compositing Layers)
拥有单独的图形层 ( GraphicsLayer )
,即开启了硬件加速 ,不会影响其余渲染层的 paint、layout
如笔者这里理解有误,还请读者大佬指出,感激涕零~
3.给气泡应用上咱们所实现的两个 @keyframes 动画
.bubble {
animation: animation-x 3s -2s linear infinite,animation-y 4s 0s linear 1;
/* 给 bubble 开启了硬件加速 */
}
复制代码
4.在点赞事件中,经过 js 操做动态添加/移除气泡元素
function like() {
const likeDom = document.createElement('div');
likeDom.className = 'bubble'; // 添加样式
document.body.appendChild(likeDom); // 添加元素
setTimeout( () => {
document.body.removeChild(likeDom); // 移除元素
}, 4000)
}
复制代码
1.首先,咱们使用 svg 绘制一个圆周长为2 * 25 * PI = 157
的圆
<svg with='200' height='200' viewBox="0 0 100 100" >
<circle cx="50" cy="50" r="25" fill="transparent" stroke-width="4" stroke="#0079f5" ></circie>
</svg>
复制代码
2.将实线圆绘制成虚线圆,这里须要用 stoke-dasharray:50, 50 (可简写为50)
属性来绘制虚线, stoke-dasharray 参考资料
短划线(50px)
和缺口(50px)
的长度。50(短划线) + 50(缺口) + 50(段划线) = 150, 150 < 157
,没法绘制出完整的圆,因此会致使右边存在缺口(7px)
<svg with='200' height='200' viewBox="0 0 100 100" >
<circle cx="50" cy="50" r="25" fill="transparent" stroke-width="4" stroke-dasharray="50" stroke="#0079f5" ></circie>
</svg>
复制代码
3.stroke-dashoffset
属性可使圆的短划线和缺口产生偏移,添加 @keyframes 动画后可以实现从无到有的效果,stoke-dashoffset参考资料
stroke-dasharray="157 157
",指定 短划线(157px)
和 缺口(157px)
的长度。修改stroke-dashoffset值
, 值为正数
时逆时针偏移
🔄,, 值为负数
时,顺时针偏移
🔃@keyframes loading {
0%{
stroke-dashoffset: 0;
}
100%{
stroke-dashoffset: -157; /* 线条顺时针偏移 */
}
}
circle{
animation: loading 1s 0s ease-out infinite;
}
复制代码
4.修改短划线和缺口值
50px
的短划线,设置 stroke-dasharray="50"
缺口须要大于或等于圆周长157
,设置 stroke-dasharray="50 157"
动画结束时仍处理动画开始位置
,须要修改 stroke-dashoffset:-207(短划线+缺口长度)
stroke-dashoffset
属性,具体实现请查看示例@keyframes loading {
0%{
stroke-dashoffset: 0;
}
100%{
stroke-dashoffset: -207; /* 保证动画结束时仍处理动画开始位置 */
}
}
circle{
animation: loading 1s 0s ease-out infinite;
}
复制代码
steps()
是 animation-timing-function
的属性值
animation-timing-function : steps(number[, end | start])
复制代码
两个参数
第一个参数接受一个整数值
,表示两个关键帧之间分几步完成第二个参数有两个值 start or end
。默认值为 endsteps 适用于关键帧动画,第一个参数将两个关键帧
细分为N帧
,第二个参数决定从一帧到另外一帧的中间间隔是用开始帧
仍是结束帧
来进行填充。
看下图能够发现:
steps(N, start)
将动画分为N段
,动画在每一段的起点
发生阶跃(即图中的空心圆 → 实心圆),动画结束时停留在了第N帧steps(N, end)
将动画分为N段
,动画在每一段的终点
发生阶跃(即图中的空心圆 → 实心圆),动画结束时第N帧已经被跳过(即图中的空心圆 → 实心圆),停留在了N+1帧。13
个字符。[经测试,多数中文字体每一个字符宽高都相等]steps(13)
能够将 @keyframes 动画分为13阶段
运行,且每一阶段运行距离相等
。效果以下:
/* 改变容器宽度 */
@keyframes animate-x {
0%{
width: 0;
}
}
p {
width: 125px;
overflow: hidden;
border-right: 1px solid transparent;
animation: animate-x 3s 0s steps(13) 1 forwards;
}
复制代码
每一个字符的width与动画每一阶段运行的距离相等
Monaco
字体属性,用以保证每一个字符的 width 相同
,具体像素受fontSize
属性影响,示例中的字体宽度约为 9.6px,9.6px * 13(段数) = 124.8px (125px)
,因此当咱们设置容器宽度为 125px,便可的达成目的:每一个字符的 width 与动画每一阶段运行的距离相等(约为 9.6px )
。p {
/* 设置 Monaco 字体属性,字体大小为16px,用以保证每一个字符的 width 相同,width 约为9.6p */
font-family: Monaco;
/* 9.6px * 13 = 124.8px (125px) */
width: 125px ;
font-size: 16px;
overflow: hidden;
border-right: 1px solid transparent;
/* 同时应用动画 animate-x、cursor-x */
animation: animate-x 3s 0s steps(13) 1 forwards,cursor-x 0.4s 0s linear infinite;
}
复制代码
47帧
的雪碧图(css spirit),设置背景图.main {
width: 260px;
height: 200px;
background: url(url) no-repeat;
background-size: 100%;
background-position: 0 0;
}
复制代码
修改 background-position
,让背景图移动@keyframes animate {
0% {
background-position: 0 0;
}
100% {
background-position: 0 100%;
}
}
.main{
width: 260px;
height: 200px;
background: url(url) no-repeat;
background-size: 100%;
background-position: 0 0;
animation: animate 2s 1s steps(47) infinite alternate;
}
复制代码
animation-play-state
用于控制动画是否暂停input:checked+.main{
animation-play-state: paused;
}
复制代码
CSS 参考手册
SVG学习之stroke-dasharray 和 stroke-dashoffset 详解
理解CSS3 Animation中的steps()
【译】css动画里的steps()用法详解
CSS Will Change