内容简介:动画系列之CSS3动画基础
CSS3添加了几个动画效果的属性,通过设置这些属性,可以做出一些简单的动画效果而不需要再去借助JavaScript。
CSS3动画的属性主要分为三类:transform、transition以及animation。
基本内容
-
动画的基本概念
- 补间动画
- 逐帧动画
-
Transform
- 2D变换
- 3D变换
- Tranform过渡控制
- 可动画的属性
-
Transition
- 基本属性
- 为不同属性指定过渡时长
- 变换多个动画属性
- 时长的简写
- 强制开启GPU硬件加速
- 消除Tansition动画闪屏和文字变虚
-
Animation动画
- 基本属性
- 关键帧序列
- 运动方向
- 重复次数
- 播放与暂停
- 起始状态控制
- Transition 与 Animation 动画的触发
-
监听动画结束的事件
- 确保 transitioned 事件触发
- 强制重绘触发动画
- 会引起界面重绘的属性
- Transition动画应用示例
- Animation动画应用示例
动画的基本概念
补间动画
过滤动画 具有连贯性的动画,从一个关键帧到另一个关键帧的过滤,Transition 动画属于此类动画
逐帧动画
使用steps过渡的动画,在时间帧上逐帧绘制帧内容,由于是一帧一帧的画,所以逐帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容。与电影相似,适用于表现细腻的动画,如人物动作,3D动画等。
缺点是:制作难度大,需要大量素材,导致最终文件的体积很大。
Transform过渡
位移Translate、旋转Rotate、倾斜Skew、缩放Scale 及矩阵变形Matrix
2D变换
- 位移:translate(12px, 50%); 单位可指定 px % em rem
- 缩放:scale(x, y)
- 斜切:skew(0deg, 0deg)
- 旋转:rotate(0deg)
- 矩阵:matrix(0, 0, 0, 0, 0, 0)
3D变换
-
位移:
translateX() / translateY() / translateZ() /translate3d()
-
缩放:
scaleX() / scaleZ() / scaleY() / scale3d(2.5, 1.2, 0.3);
-
斜切:
skewX() / skewY()
-
旋转:
rotate3d(1, 2.0, 3.0, 10deg);
-
矩阵:
matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
触发3D变形的属性
.parent { perspective: 300px; 透视点 perspective-origin: center center; 观察者(消失点)的位置(默认为中心点) backface-visibility: visible; 3D元素的背面是否可见(默认是visible) }
MDN backface-visibility perspective perspective-origin
在子元素上触发3D空间
transform: perspective(600);
一本书平放在面前,看着书感受一下透视感,perspective属性值就是眼睛和书之间的距离,距离越远,数值越大,透视感越小;距离越近,数值越小,透视感越强。
简单易懂的教程示例: CSS3 3D教程
Transform 过渡控制
transform-origin / transform-style
定义过渡原点
transform-origin ( transform-origin-x 、transform-origin-y、transform-origin-z )
默认为元素的中心原点
transform-origin: left top; 左上角 transform-origin: right bottom; 右下角 transform-origin: center bottom; 底部中心 transform-origin: 50% 50%; 中心 transform-origin: 10px 2em; transform-origin: right 20%; transform-origin: right 20% 30px; transform-origin: bottom top 2px;
定义子元素的是扁平化还是三维展示
transform-style: flat | preserve-3d
transform-style: preserve-3d; 用于触发子元素三维展示
可动画的属性
border / color / backgorund / height、width / left、right、top、bottom / padding / margin / opacity / font-size / box-shadow / text-shadow / transform
这里列举了 一些常见的可动画的属性,详情请查看 MDN 可动画的属性列表
Transition
定义过渡动画效果
基本属性
- transition-property 需要进行过渡属性(只有指定的属性才进行过滤动画) 或者 全部可动画的属性 all
- transition-delay 延迟时间
- transition-duration 进行过渡的时间
- transition-timing-function 指定动画函数
简写
transition: <property> <duration> <timing-function> <delay>
;
为不同属性指定过渡时长
transition-property: opacity, left, top, height; transition-duration: 3s, 5s, 1s, 2s;
时长的简写
如果有部分属性没有指定时长,则重复前面的时长
transition-property: opacity, left, top, height; transition-duration: 3s, 5s; 等价于 transition-duration: 3s, 5s, 3s, 5s;
! 为了过渡的流畅性,一般需要指定动画的属性,可以有以下几种指定方式
transition: margin-left 4s; /* property name | duration | delay */ transition: margin-left 4s 1s; /* property name | duration | timing function | delay */ transition: margin-left 4s ease-in-out 1s; /* Apply to 2 properties */ transition: margin-left 4s, color 1s; /* duration | delay | property name */ transition: 4s 1s color;
变换多个动画属性
.box { width: 100px; height: 100px; background-color: #0000FF; transition: width 2s, height 2s, background-color 2s, transform 2s; } .box:hover { width: 200px; height: 200px; background-color: #FFCCCC; transform: rotate(180deg); }
强制开启GPU硬件加速
.box { transition: tanslate3d(0,0,0)或 tansition: translateZ(0) }
消除Tansition动画闪屏和文字变虚
.box{ transform-style: preserve-3d; backface-visibility:hidden; }
注意
避免使用会引起重排的属性做动画,如: letf / margin / padding / width / height
等会引起大量重排重绘的属性
Animation动画
可以将从一个CSS样式配置转换到另一个CSS样式配置
动画包括两个部分: 描述动画的样式规则和用于指定动画开始、结束以及中间点样式的关键帧。
优点:简单,性能良好,浏览器可以自动优化
基本属性
动画的实际表现是由
@keyframes
规则实现
-
animation-name
动画的名称(由@keyframes定义) -
animation-delay
动画延时 -
animation-direction
定义动画完成后,是从初始状态还是从最终状态重复动画 -
animation-duration
动画时长 -
animation-iteration-count
动画重复次数 -
animation-play-state
播放或暂停动画 -
animation-timing-function
设置动画关键帧之间的运动函数 -
animation-fill-mode
指定动画前后如何为元素应用样式
关键帧序列 keyframes
使用 @keyframes
定义动画序列关键帧
简单的动画可以使用 form/to
来定义 开始和结束关键帧
p { animation-duration: 3s; animation-name: slidein; } @keyframes slidein { from { margin-left: 100%; width: 300%; } to { margin-left: 0%; width: 100%; } }
复杂的动画可以使用 百分比 更精确的控制
.tada { animation-name: tada; animation-duration: 3s; } @keyframes tada { 0% { transform: scale3d(1, 1, 1); } 10%, 20% { transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); } 30%, 50%, 70%, 90% { transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); } 40%, 60%, 80% { transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); } 100% { transform: scale3d(1, 1, 1); } }
运动方向 animation-direction
animation-direction:normal | alternate | alternate-reverse | reverse
-
normal
: 正向运动 -
alternate
: 先正向再反向再正再反循环反复 -
alternate-reverse
: 先反向再正向再反再正循环反复 -
reverse
: 反向运动
重复次数 animation-iteration-count
animation-iteration-count: infinite | <single-animation-iteration-count>
-
infinite
: 循环执行 -
single-animation-iteration-count
:循环的周期数值(可以是小数)
播放暂停 animation-play-state
animation-play-state: running | paused [ , running | paused ]*
-
running
:运动 -
paused
:暂停
起始状态控制 animation-fill-mode
animation-fill-mode: none | forwards | backwards | both
设置元素动画之后的状态
-
none
:不应用状态 -
forwards
: 应用动画结束帧的状态(结束帧与动画运动次数和方向有关) -
backwards
: 应用动画起始帧的状态 (与动画运动方向有关) -
both
: 应用首帧与结束帧(同时应用 forwards 与 backwrads)
Transition 与 Animation 动画的触发
可以通过伪类 (:link、:visited、:hover、:active、:focus、:checked、:enabled、:disabled)
和 事件触发
如果直接给元素设置 transform
,用户将直接看到元素的最终状态,而不会有动画
通过切换元素设定好的动画类可以很方便的控制 Transiton
或 Animation
动画
Transiton动画 有入场和出场动画,比如一个元素在 :hover
状态时触发 transiton
动画,在鼠标离开后,动画自动反向播放回到 transition
之前的状态
Transition 通过伪类、事件或一个 Class
切换,可以很方便的实现入场和出场动画, 而 Animation
动画则要通过不同的 Class
来控制入场和出场
监听动画结束的事件
-
Transition动画监听
transitionend
事件 -
Animation动画监听
animationend
事件
简单粗暴的方法: 监听所有可能支持的事件
var transitionEndEventNames = { 'WebkitTransition' : 'webkitTransitionEnd', 'OTransition' : 'oTransitionEnd', 'msTransition' : 'MSTransitionEnd', 'transition' : 'transitionend' } var animationEndEventNames = { 'WebkitAnimation' : 'webkitAnimationEnd', 'OAnimation' : 'oAnimationEnd', 'msAnimation' : 'MSAnimationEnd', 'animation' : 'animationend' } function getEventNames(nameMap){ retunr Object.keys(nameMap).map(v=>nameMap[v]).join(' '); } var animationEndEventName = getEventNames(transitionEndEventNames); var transitionEndEventName = getEventNames(animationEndEventNames); oDiv.addEventListener( transitionEndEventName, callbackFn ) oDiv.addEventListener( animationEndEventName, callbackFn )
只监听受支持的事件
通过检测 body.style
中是否有相关属性来获取受支持的属性名称
var transEndEventNames = { WebkitTransition: 'webkitTransitionEnd', MozTransition: 'transitionend', OTransition: 'oTransitionEnd otransitionend', transition: 'transitionend' }; var animEndEventNames = { WebkitAnimation: 'webkitAnimationEnd', MozAnimation: 'animationend', OAnimation: 'oAnimationEnd oanimationend', animation: 'animationend' }; var elStyle = (document.body || document.documentElement).style; function getSupportName(nameMap){ var keys = Object.keys(nameMap).filter(v=>elStyle[v] !== undefined); return nameMap[keys[0]]; } var transitionEnd = getSupportName(transEndEventNames); var animationEnd = getSupportName(animEndEventNames); oDiv.addEventListener( transitionEnd, callbackFn ) oDiv.addEventListener( animationEnd, callbackFn )
注意
- 当属性值没有发生变化或没有绘制行为发生,transitionend 事件不会被触发
- 如果有多个属性进行transtion动画,则会触发多次 transitierend 事件
确保 transitioned 事件触发
结合jQuery 确保 transitioned
事件能被触发
$.fn.emulateTransitionEnd = function(duration){ var called = false, $el = this; $(this).once('webkitTransitionEnd', function(){ called = true; }); var callback = function(){ if (!called) $($el).trigger('webkitTransitionEnd'); }; setTimeout(callback, duration); };
使用
$(this).one('webkitTransitionEnd', callback); $(this).emulateTransitionEnd(options.duration + 50); $(this).css(properties);
原理:同时给 元素 绑定两个 webkitTransitionEnd
事件和一个 setTimeout
,如果 webkitTransitionEnd
能正确触发,则 called
为 true
, setTimeout
中回调内的代码则不执行
强制重绘触发动画
给一个 display:none
元素添加 Transition
动画时,先要将 display
设置为 block
,同时应用 Transition
动画,但是两套css执行的时间间隔太近,浏览器会尝试优化css属性的变化,直接表现为transition最终的状态,无法显示动画效果,为了避免这种情况,可以在将 display
设置为 block
时,同时强制浏览器对css进行重绘,触发 transition
动画(一般获取一次元素的 offsetHeight
属性即可)。
会引起界面重绘的属性
- offsetTop, offsetLeft, offsetWidth, offsetHeight
- scrollTop/Left/Width/Height
- clientTop/Left/Width/Height
- width,height
- 请求了getComputedStyle()
当请求上面的一些属性的时候,浏览器为了给你最精确的值,需要flush队列,因为队列中可能会有影响到这些值的操作。
结合 jQuery
添加一个强制重绘的方法:
$.fn.redraw = function(){ $(this).each(function(){ var redraw = this.offsetHeight; }); };
使用
$('.element').css({left: '10px'}) .redraw() .transition({left: '20px'});
这种方法在大多数浏览器都有效,但在个别 Andorid默认浏览器上偶尔还是会失效。这时就只能使用定时器或者增加class了。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Flutter尝鲜2——动画处理<基础>
- Vue中的基础过渡动画原理解析
- Html5 Canvas动画基础(碰撞检测)
- 贝塞尔曲线的css实现——淘宝加入购物车基础动画
- 【Android 动画】动画详解之属性动画(三)
- 【Android 动画】动画详解之属性动画(五)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。