css3 动画的实现的方案,大概有以下方案:
animation()
方法实现动画(这是一个实验功能,此功能某些浏览器尚在开发中。详见这里)。@keyframes
+ animation
:这是一个实现动画的组合,必须一起使用。transition
:表示过渡。transition 可以单独使用,transform
:表示变形。使用 transform 实现动画时有两种选择:
transform
+ transition
:一次性动画。transform 定义行为,transition 驱动,但一次仅能驱动一次。transform
+ @keyframes
+ animation
:支持循环动画。在 @keyframes 里使用 transform 定义行为,animation 驱动,可充分调整动画的实现,包括:指定动画任意的执行次数,指定动画的结束与开始的状态等等。transition 和 animation 实现动画的区别:
CSS animation 属性
@keyframes 用来创建动画。其内部规定一个动画——从目前的样式更改为新的样式。
@keyframes myfirst{
from {background: red;}
to {background: yellow;}
}
/* Safari 与 Chrome */
@-webkit-keyframes myfirst{
from {background: red;}
to {background: yellow;}
}
// 当动画为 25% 及 50% 时改变背景色,然后当动画 100% 完成时再次改变:
@keyframes myfirst
{
0% {background: red;}
25% {background: yellow;}
50% {background: blue;}
100% {background: green;}
}
@-webkit-keyframes myfirst /* Safari 与 Chrome */
{
0% {background: red;}
25% {background: yellow;}
50% {background: blue;}
100% {background: green;}
}
将 @keyframes 嵌套进要添加动画的元素的样式里,然后,通过 animation 执行这个动画:
.action-move {
animation: box-move 3s ease-out;
-webkit-animation: activity-move 3s ease-out;
animation-fill-mode: forwards;
@keyframes box-move {
0% {transform: scale(1); opacity: 1}
20% {transform: scale(1.3); opacity: 1}
40% {transform: scale(1.3); opacity: 1}
60% {transform: scale(1); opacity: 1}
80% {transform: scale(1.2); opacity: 1}
100% {transform: scale(1); opacity: 0}
}
}
在 @keyframes 创建动画后,必须通过 animation 属性把该 keyframes 绑定到指定的选择器上,否则动画不会有任何效果。
语法:
{animation: name duration timing-function delay iteration-count direction
fill-mode play-state;}
animation 属性是以下属性的简写形式:
将创建的动画绑定到一个指定的选择器上:
// 把 "myfirst" 动画捆绑到 div 元素,时长:5 秒:
div{
animation: myfirst 5s;
-webkit-animation: myfirst 5s; /* Safari 与 Chrome */
}
实现一个完全属性的动画——该动画只执行一次,且动画结束后停留在最后一帧的状态:
{animation: set_touch 1s ease 0s 1 normal forwards running;}
必须的。规定 @keyframes 动画的名称。
animation-name 属性的值:
必须的。指定一个动画周期的时长。默认是 0s,表示无动画。
案例:
// 一个值
{animation-duration: 6s;}
//多个值
{animation-duration: 10s, 30s, 230ms;}
可选的。规定动画的速度曲线。
animation-timing-function 属性的值:
函数值:
案例:
// 一个值
{animation-timing-function: linear;}
// 多个值
{animation-timing-function: ease, step-start, cubic-bezier(0.1, 0.7, 1.0, 0.1);}
// cubic-bezier() 函数
{animation-timing-function: cubic-bezier(0, 0.7, 1, 0.1);}
// steps() 函数
{animation-timing-function: steps(4, end);}
// frames() 函数
{animation-timing-function: frames(10);}
可选的。规定动画何时开始,值可以是所有的整数。默认是 0。(这是一个实验中的功能,某些浏览器尚在开发中)
animation-delay 属性的值:
案例:
// 一个值
{animation-delay: 3s;}
// 多个值
{animation-delay: 2s, 4ms;}
可选的。规定动画被播放的次数。默认是 1。(这是一个实验中的功能,某些浏览器尚在开发中)
animation-iteration-count 属性的值:
案例:
// infinite
{animation-iteration-count: infinite;}
//
{animation-iteration-count: 3;}
// 多个值
{animation-iteration-count: 2, 0.5, infinite;}
可选的。指示动画是否反向播放。(这是一个实验中的功能,某些浏览器尚在开发中)
animation-direction 属性的值:
案例:
// 一个值
{animation-direction: normal;}
// 多个值
{animation-direction: alternate, reverse, normal;}
可选的。规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式。
animation-fill-mode 属性的值:
案例:
// 单个值
{animation-fill-mode: backwards;}
// 多个值
{animation-fill-mode: both, forwards, none;}
可选的。规定动画是否运行或暂停。默认是 “running”。
animation-play-state 属性的值:
案例:
// 单个值
{animation-play-state: paused;}
// 多个值
{animation-play-state: paused, running, running;}
CSS transform 属性
CSS transition 属性
用 transform 实现的动画必须用 transition 来驱动。
2D | 3D | ||
---|---|---|---|
属性 | 描述 | 属性 | 描述 |
- | - | backface-visibility | 定义元素在不面对屏幕时是否可见。 |
- | - | transform-style | 定义被嵌套元素如何在 3D 空间中显示。 |
- | - | perspective(n) | 定义 3D 元素的透视效果。 |
transform-origin | 改变元素的中心原点的位置。 | perspective-origin | 定义 3D 元素的底部的中心位置位置。 |
rotate(angle) | 旋转。在一个给定度数顺时针旋转的元素。负值是允许的,这样是元素逆时针旋转。 | rotate3d(x, y, z, angle) | 同 2D 的 rotate。 - rotateX(angle) - rotateY(angle) - rotateZ(angle) |
translate(x, y) | 位移。根据左(X轴)和顶部(Y轴)位置给定的参数,从当前元素位置移动。 - translateX(n):沿着 X 轴移动元素。 - translateY(n):沿着 Y 轴移动元素。 |
translate3d(x, y, z) | 同 2D 的 translate。 - translateX(n) - translateY(n) - translateZ(n) |
scale(x, y) | 缩放。该元素增加或减少的大小,取决于宽度(X轴)和高度(Y轴)的参数。 - scaleX(x):改变元素的宽度。 - scaleY(y):改变元素的高度。 |
scale3d(x, y, z) | 同 2D 的 scale。 - scaleX(x) - scaleY(y) - scaleZ(z) |
skew(x-angle, y-angle) | 倾斜。包含两个参数值,分别表示X轴和Y轴倾斜的角度,如果第二个参数为空,则默认为0,参数为负表示向相反方向倾斜。 - skewX(angle):表示只在 X 轴(水平方向)倾斜。 - skewY(angle):表示只在 Y 轴(竖直方向)倾斜。 |
- | - |
matrix(n,n, n,n, n,n) | 整合。将上面 2D 变化所有的方法整合成一个使用。使用 2x3 的矩阵。包含旋转,缩放,移动(平移)和倾斜功能。 | matrix3d(n,n,n,n, n,n,n,n, n,n,n,n, n,n,n,n) | 整合。将上面 3D 变化所有的方法整合成一个使用。使用 16 个值的 4x4 的矩阵。 |
// translate——位移
div {
transform: translate(50px, 100px);
transition: transform 500ms;
}
// rotate——旋转
div {
transform: rotate(30deg);
transition: transform 500ms;
}
// scale——缩放
div {
transform: scale(2, 3);
transition: transform 500ms;
}
// skew——倾斜
div {
transform: skew(30deg, 20deg);
transition: transform 500ms;
}
// matrix——整合
div {
transform:matrix(0.866, 0.5, -0.5, 0.866, 0, 0);
transition: transform 500ms;
}
从一种样式转变到另一种样式的过程叫做 过渡。
语法:
{ transition: property | duration | timing-function | delay }
要实现这一点,必须定义好两项内容:
例如:
// 定义宽度属性的过渡效果,时长为 2 秒
div{
width: 100px;
transition: width 2s;
-webkit-transition: width 2s; /* Safari */
}
【注意】如果未指定的期限,transition 将没有任何效果,因为默认值是 0。
要添加多个样式的变换效果,添加的属性由逗号分隔:
div{
width: 100px;
height: 100px;
transform: rotateX(120deg);
transition: width 2s, height 2s, transform 2s;
-webkit-transition: width 2s, height 2s, -webkit-transform 2s;
}
.iconfont-loadding {
animation: start_loadding 800ms linear 100ms infinite normal none running;
}
@keyframes start_loadding {
from { transform: rotate(0deg);}
to { transform: rotate(360deg);}
}
进一步组件化:
// 封装一个使用动画的函数,接受一个表示位置的参数(通过调用这个函数就可以使用这个动画)
.entry-animation(@position: top) {
animation: entry 800ms ease 100ms forwards;
@keyframes entry {
0% {
@{position}: 0px;
opacity: 0;
}
100% {
@{position}: 50px;
opacity: 1;
}
}
}
// 创建一个动画
@keyframes start_loadding {
0% { transform: rotate(0deg);}
100% { transform: rotate(360deg);}
}
【注意】经实际验证:
首先,假设在 template 里已经写好了页面头部导航栏,接下来要在 css 中定义好相关的类:
.dark {
color: #333;
background: rgba(255, 255, 255, 1);
transition: color 3s, background 3s;
}
.light {
color: #fff;
background: rgba(255, 255, 255, 0);
transition: color 3s, background 3s;
}
.empty {
opacity: 0;
transition: opacity 3s;
}
然后,在 js 中使用这些类:
export default {
mounted () {
window.addEventListener('scroll', this.handleScroll)
},
beforeDestroy () {
window.removeEventListener('scroll', this.handleScroll)
},
methods: {
// 监听页面滚动
handleScroll (e) {
let scrollTop = window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop
if (scrollTop >=0 && scrollTop <= 30) {
this.$refs.tagTopMenu.className = `tag-top-menu light`
} else if (scrollTop >= 100) {
this.$refs.tagTopMenu.className = `tag-top-menu dark`
} else {
this.$refs.tagTopMenu.className = `tag-top-menu empty`
}
}
}
}
【遇到的问题】:
入参加上 true。让其在捕获阶段而非冒泡阶段执行这个监听。(如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。)
例如:
mounted () {
window.addEventListener('scroll', this.handleScroll, true)
},
beforeDestroy () {
window.removeEventListener('scroll', this.handleScroll, true)
}
我这边是,代码里面写了 min-height: calc(100vh - 268px);,这个一直是不超出屏幕的。并且,我给父元素 div 加了 overflow-y: scroll; 实现了滚动条,但带来了现在的这个问题。可是又不得不加 overflow,否则我就可以通过改 overflow 来解决这个问题了。
此时,还有一种办法:改取 e.target 的 scrollTop 即可。
例如:
// 监听页面滚动
handleScroll (e) {
// let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
let scrollTop = e.target.scrollTop
this.isShowTagTitle = false
if (scrollTop <= 30) {
this.$refs.tagTopMenu.className = `tag-top-menu light`
} else if (scrollTop >= 130) {
this.$refs.tagTopMenu.className = `tag-top-menu dark`
this.isShowTagTitle = true
} else {
this.$refs.tagTopMenu.className = `tag-top-menu empty`
}
},
【参考】
vue中window.addEventListener(‘scroll‘, xx)失效解决办法
解决window.pageYOffset,document.documentElement.scrollTop,document.body.scrollTop获取距离顶部距离都为0的问题
为什么scrollTop设置后一直为0的解释和解决方案(精品)