本文最初發表於 "博客園" ,併在 "GitHub" 上持續更新 前端的系列文章 。歡迎在GitHub上關註我,一起入門和進階前端。 以下是正文。 前言 本文主要內容: 過渡:transition 2D 轉換 transform 3D 轉換 transform 動畫:animation 過渡:tra ...
以下是正文。
前言
本文主要內容:
過渡:transition
2D 轉換 transform
3D 轉換 transform
動畫:animation
過渡:transition
transition
的中文含義是過渡。過渡是CSS3中具有顛覆性的一個特征,可以實現元素不同狀態間的平滑過渡(補間動畫),經常用來製作動畫效果。
補間動畫:自動完成從起始狀態到終止狀態的的過渡。不用管中間的狀態。
幀動畫:通過一幀一幀的畫面按照固定順序和速度播放。如電影膠片。
參考鏈接:補間動畫基礎
transition 包括以下屬性:
transition-property: all;
如果希望所有的屬性都發生過渡,就使用all。transition-duration: 1s;
過渡的持續時間。transition-timing-function: linear;
運動曲線。屬性值可以是:linear
線性ease
減速ease-in
加速ease-out
減速ease-in-out
先加速後減速
transition-delay: 1s;
過渡延遲。多長時間後再執行這個過渡動畫。
上面的四個屬性也可以寫成綜合屬性:
transition: 讓哪些屬性進行過度 過渡的持續時間 運動曲線 延遲時間;
transition: all 3s linear 0s;
其中,transition-property
這個屬性是尤其需要註意的,不同的屬性值有不同的現象。我們來示範一下。
如果設置 transition-property: width
,意思是只讓盒子的寬度在變化時進行過渡。效果如下:
如果設置 transition-property: all
,意思是讓盒子的所有屬性(包括寬度、背景色等)在變化時都進行過渡。效果如下:
案例:小米商品詳情
代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS 過渡</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #eeeeee;
}
.content {
width: 800px;
height: 320px;
padding-left: 20px;
margin: 80px auto;
}
.item {
width: 230px;
height: 300px;
text-align: center;
margin-right: 20px;
background-color: #FFF;
float: left;
position: relative;
top: 0;
overflow: hidden; /* 讓溢出的內容隱藏起來。意思是讓下方的橙色方形先躲起來 */
transition: all .5s; /* 從最初到滑鼠懸停時的過渡 */
}
.item img {
margin-top: 30px;
}
.item .desc {
position: absolute;
left: 0;
bottom: -80px;
width: 100%;
height: 80px;
background-color: #ff6700;
transition: all .5s;
}
/* 滑鼠懸停時,讓 item 整體往上移動5px,且加一點陰影 */
.item:hover {
top: -5px;
box-shadow: 0 0 15px #AAA;
}
/* 滑鼠懸停時,讓下方的橙色方形現身 */
.item:hover .desc {
bottom: 0;
}
</style>
</head>
<body>
<div class="content">
<div class="item">
<img src="./images/1.png" alt="">
</div>
<div class="item">
<img src="./images/2.png" alt="">
<span class="desc"></span>
</div>
<div class="item">
<img src="./images/3.jpg" alt="">
<span class="desc"></span>
</div>
</div>
</body>
</html>
效果如下:
動畫效果錄製的比較差,但真實體驗還是可以的。
工程文件:
2D 轉換
轉換是 CSS3 中具有顛覆性的一個特征,可以實現元素的位移、旋轉、變形、縮放,甚至支持矩陣方式。
轉換再配合過渡和動畫,可以取代大量早期只能靠 Flash 才可以實現的效果。
在 CSS3 當中,通過 transform
轉換來實現 2D 轉換或者 3D 轉換。
- 2D轉換包括:縮放、移動、旋轉。
我們依次來講解。
1、縮放:scale
格式:
transform: scale(x, y);
transform: scale(2, 0.5);
參數解釋: x:表示水平方向的縮放倍數。y:表示垂直方向的縮放倍數。如果只寫一個值就是等比例縮放。
取值:大於1表示放大,小於1表示縮小。不能為百分比。
格式舉例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 1000px;
margin: 100px auto;
}
.box div {
width: 300px;
height: 150px;
background-color: pink;
float: left;
margin-right: 15px;
color: white;
text-align: center;
font: 400 30px/150px “宋體”;
}
.box .box2 {
background-color: green;
transition: all 1s;
}
.box .box2:hover {
/*width: 500px;*/
/*height: 400px;*/
background-color: yellowgreen;
/* transform: css3中用於做變換的屬性
scale(x,y):縮放 */
transform: scale(2, 0.5);
}
</style>
</head>
<body>
<div class="box">
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">3</div>
</div>
</body>
</html>
效果:
上圖可以看到,給 box1 設置 2D 轉換,並不會把兄弟元素擠走。
2、位移:translate
格式:
transform: translate(水平位移, 垂直位移);
transform: translate(-50%, -50%);
參數解釋:
參數為百分比,相對於自身移動。
正值:向右和向下。 負值:向左和向上。如果只寫一個值,則表示水平移動。
格式舉例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 1000px;
margin: 100px auto;
}
.box > div {
width: 300px;
height: 150px;
border: 1px solid #000;
background-color: red;
float: left;
margin-right: 30px;
}
div:nth-child(2) {
background-color: pink;
transition: all 1s;
}
/* translate:(水平位移,垂直位移)*/
div:nth-child(2):hover {
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div class="box">
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">3</div>
</div>
</body>
</html>
效果:
上圖中,因為我在操作的時候,滑鼠懸停後,立即進行了略微的移動,所以產生了兩次動畫。正確的效果應該是下麵這樣的:
應用:讓絕對定位中的盒子在父親里居中
我們知道,如果想讓一個標準流中的盒子在父親里居中(水平方向看),可以將其設置margin: 0 auto
屬性。
可如果盒子是絕對定位的,此時已經脫標了,如果還想讓其居中(位於父親的正中間),可以這樣做:
div {
width: 600px;
height: 60px;
position: absolute; 絕對定位的盒子
left: 50%; 首先,讓左邊線居中
top: 0;
margin-left: -300px; 然後,向左移動寬度(600px)的一半
}
如上方代碼所示,我們先讓這個寬度為600px的盒子,左邊線居中,然後向左移動寬度(600px)的一半,就達到效果了。
現在,我們還可以利用偏移 translate 來做,這也是比較推薦的寫法:
div {
width: 600px;
height: 60px;
background-color: red;
position: absolute; 絕對定位的盒子
left: 50%; 首先,讓左邊線居中
top: 0;
transform: translate(-50%); 然後,利用translate,往左走自己寬度的一半【推薦寫法】
}
3、旋轉:rotate
格式:
transform: rotate(角度);
transform: rotate(45deg);
參數解釋:正值 順時針;負值:逆時針。
舉例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 200px;
height: 200px;
background-color: red;
margin: 50px auto;
color: #fff;
font-size: 50px;
transition: all 2s; /* 過渡:讓盒子在進行 transform 轉換的時候,有個過渡期 */
}
/* rotate(角度)旋轉 */
.box:hover {
transform: rotate(-405deg); /* 滑鼠懸停時,讓盒子進行旋轉 */
}
</style>
</head>
<body>
<div class="box">1</div>
</div>
</body>
</html>
效果:
註意,上方代碼中,我們給盒子設置了 transform 中的 rotate 旋轉,但同時還要給盒子設置 transition 過渡。如果沒有這行過渡的代碼,旋轉會直接一步到位,效果如下:(不是我們期望的效果)
案例1:小火箭
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
html,body{
height:100%;
}
body{
background-color: #DE8910;
}
.rocket{
position: absolute;
left:100px;
top:600px;
height: 120px;
transform:translate(-200px ,200px) rotate(45deg);
transition:all 1s ease-in;
}
body:hover .rocket{
transform:translate(500px,-500px) rotate(45deg);
}
</style>
</head>
<body>
<img class="rocket" src="images/rocket.png" alt=""/>
</body>
</html>
上方代碼中,我們將 transform 的兩個小屬性合併起來寫了。
小火箭圖片的url:http://img.smyhvae.com/20180208-rocket.png
案例2:撲克牌
rotate 旋轉時,預設是以盒子的正中心為坐標原點的。如果想改變旋轉的坐標原點,可以用transform-origin
屬性。格式如下:
transform-origin: 水平坐標 垂直坐標;
transform-origin: 50px 50px;
transform-origin: center bottom; //旋轉時,以盒子底部的中心為坐標原點
我們來看一下 rotate 結合 transform-origin 的用法舉例。
代碼如下:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body {
/*background-color: #eee;*/
}
.box {
width: 300px;
height: 440px;
margin: 100px auto;
position: relative;
}
img {
width: 100%;
transition: all 1.5s;
position: absolute; /* 既然撲克牌是疊在一起的,那就都用絕對定位 */
left: 0;
top: 0;
transform-origin: center bottom; /*旋轉時,以盒子底部的中心為坐標原點*/
box-shadow: 0 0 3px 0 #666;
}
.box:hover img:nth-child(6) {
transform: rotate(-10deg);
}
.box:hover img:nth-child(5) {
transform: rotate(-20deg);
}
.box:hover img:nth-child(4) {
transform: rotate(-30deg);
}
.box:hover img:nth-child(3) {
transform: rotate(-40deg);
}
.box:hover img:nth-child(2) {
transform: rotate(-50deg);
}
.box:hover img:nth-child(1) {
transform: rotate(-60deg);
}
.box:hover img:nth-child(8) {
transform: rotate(10deg);
}
.box:hover img:nth-child(9) {
transform: rotate(20deg);
}
.box:hover img:nth-child(10) {
transform: rotate(30deg);
}
.box:hover img:nth-child(11) {
transform: rotate(40deg);
}
.box:hover img:nth-child(12) {
transform: rotate(50deg);
}
.box:hover img:nth-child(13) {
transform: rotate(60deg);
}
</style>
</head>
<body>
<div class="box">
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
</div>
</body>
</html>
效果如下:
4、傾斜
暫略。
3D 轉換
1、旋轉:rotateX、rotateY、rotateZ
3D坐標系(左手坐標系)
如上圖所示,伸出左手,讓拇指和食指成“L”形,大拇指向右,食指向上,中指指向前方。拇指、食指和中指分別代表X、Y、Z軸的正方向,這樣我們就建立了一個左手坐標系。
瀏覽器的這個平面,是X軸、Y軸;垂直於瀏覽器的平面,是Z軸。
旋轉的方向:(左手法則)
左手握住旋轉軸,豎起拇指指向旋轉軸的正方向,正向就是其餘手指卷曲的方向。
從上面這句話,我們也能看出:所有的3d旋轉,對著正方向去看,都是順時針旋轉。
格式:
transform: rotateX(360deg); //繞 X 軸旋轉360度
transform: rotateY(360deg); //繞 Y 軸旋轉360度
transform: rotateZ(360deg); //繞 Z 軸旋轉360度
格式舉例:
(1)rotateX 舉例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.rotateX {
width: 300px;
height: 226px;
margin: 200px auto;
/* 透視 :加給變換的父盒子*/
/* 設置的是用戶的眼睛距離 平面的距離*/
/* 透視效果只是視覺上的呈現,並不是正真的3d*/
perspective: 110px;
}
img {
/* 過渡*/
transition: transform 2s;
}
/* 所有的3d旋轉,對著正方向去看,都是順時針旋轉*/
.rotateX:hover img {
transform: rotateX(360deg);
}
</style>
</head>
<body>
<div class="rotateX">
<img src="images/x.jpg" alt=""/>
</div>
</body>
</html>
效果:
上方代碼中,我們最好加個透視的屬性,方能看到3D的效果;沒有這個屬性的話,圖片旋轉的時候,像是壓癟了一樣。
而且,透視的是要加給圖片的父元素 div,方能生效。我們在後面會講解透視屬性。
(2)rotateY 舉例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.rotateY {
width: 237px;
height: 300px;
margin: 100px auto;
/* 透視 */
perspective: 150px;
}
img {
transition: all 2s; /* 過渡 */
}
.rotateY:hover img {
transform: rotateY(360deg);
}
</style>
</head>
<body>
<div class="rotateY">
<img src="images/y.jpg" alt=""/>
</div>
</body>
</html>
效果:
(3)rotateZ 舉例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.rotateZ {
width: 330px;
height: 227px;
margin: 100px auto;
/* 透視*/
perspective: 200px;
}
img {
transition: all 1s;
}
.rotateZ:hover img {
transform: rotateZ(360deg);
}
</style>
</head>
<body>
<div class="rotateZ">
<img src="images/z.jpg" alt=""/>
</div>
</body>
</html>
效果:
案例:百度錢包
現在有下麵這張圖片素材:
要求做成下麵這種效果:
上面這張圖片素材其實用的是精靈圖。實現的代碼如下:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body {
background-color: cornflowerblue;
}
.box {
width: 300px;
height: 300px;
/*border: 1px solid #000;*/
margin: 50px auto;
position: relative;
}
.box > div {
width: 100%;
height: 100%;
position: absolute;
/*border: 1px solid #000;*/
border-radius: 50%;
transition: all 2s;
backface-visibility: hidden;
}
.box1 {
background: url(images/bg.png) left 0 no-repeat; /*預設顯示圖片的左半邊*/
}
.box2 {
background: url(images/bg.png) right 0 no-repeat;
transform: rotateY(180deg); /*讓圖片的右半邊預設時,旋轉180度,就可以暫時隱藏起來*/
}
.box:hover .box1 {
transform: rotateY(180deg); /*讓圖片的左半邊轉消失*/
}
.box:hover .box2 {
transform: rotateY(0deg); /*讓圖片的左半邊轉出現*/
}
</style>
</head>
<body>
<div class="box">
<div class="box1"></div>
<div class="box2"></div>
</div>
</body>
</html>
2、移動:translateX、translateY、translateZ
格式:
transform: translateX(100px); //沿著 X 軸移動
transform: translateY(360px); //沿著 Y 軸移動
transform: translateZ(360px); //沿著 Z 軸移動
格式舉例:
(1)translateX 舉例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 200px;
height: 200px;
background: green;
transition: all 1s;
}
.box:hover {
transform: translateX(100px);
}
</style>
</head>
<body>
<div class="box">
</div>
</body>
</html>
效果:
(2)translateY 舉例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 200px;
height: 200px;
background: green;
transition: all 1s;
}
.box:hover {
transform: translateY(100px);
}
</style>
</head>
<body>
<div class="box">
</div>
</body>
</html>
效果:
(3)translateZ 舉例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body {
/* 給box的父元素加透視效果*/
perspective: 1000px;
}
.box {
width: 250px;
height: 250px;
background: green;
transition: all 1s;
margin: 200px auto
}
.box:hover {
/* translateZ必須配合透視來使用*/
transform: translateZ(400px);
}
</style>
</head>
<body>
<div class="box">
</div>
</body>
</html>
效果:
上方代碼中,如果不加透視屬性,是看不到translateZ的效果的。
3、透視:perspective
電腦顯示屏是一個 2D 平面,圖像之所以具有立體感(3D效果),其實只是一種視覺呈現,通過透視可以實現此目的。
透視可以將一個2D平面,在轉換的過程當中,呈現3D效果。但僅僅只是視覺呈現出3d 效果,並不是正真的3d。
格式有兩種寫法:
作為一個屬性,設置給父元素,作用於所有3D轉換的子元素
作為 transform 屬性的一個值,做用於元素自身。
4、3D呈現(transform-style)
3D元素構建是指某個圖形是由多個元素構成的,可以給這些元素的父元素設置transform-style: preserve-3d
來使其變成一個真正的3D圖形。屬性值可以如下:
transform-style: preserve-3d; //讓 子盒子 位於三維空間里
transform-style: flat; //讓子盒子位於此元素所在的平面內(子盒子被扁平化)
案例:立方體
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 250px;
height: 250px;
border: 1px dashed red;
margin: 100px auto;
position: relative;
border-radius: 50%;
/* 讓子盒子保持3d效果*/
transform-style: preserve-3d;
/*transform:rotateX(30deg) rotateY(-30deg);*/
animation: gun 8s linear infinite;
}
.box > div {
width: 100%;
height: 100%;
position: absolute;
text-align: center;
line-height: 250px;
font-size: 60px;
color: #daa520;
}
.left {
background-color: rgba(255, 0, 0, 0.3);
/* 變換中心*/
transform-origin: left;
/* 變換*/
transform: rotateY(90deg) translateX(-125px);
}
.right {
background: rgba(0, 0, 255, 0.3);
transform-origin: right;
/* 變換*/
transform: rotateY(90deg) translateX(125px);
}
.forward {
background: rgba(255, 255, 0, 0.3);
transform: translateZ(125px);
}
.back {
background: rgba(0, 255, 255, 0.3);
transform: translateZ(-125px);
}
.up {
background: rgba(255, 0, 255, 0.3);
transform: rotateX(90deg) translateZ(125px);
}
.down {
background: rgba(99, 66, 33, 0.3);
transform: rotateX(-90deg) translateZ(125px);
}
@keyframes gun {
0% {
transform: rotateX(0deg) rotateY(0deg);
}
100% {
transform: rotateX(360deg) rotateY(360deg);
}
}
</style>
</head>
<body>
<div class="box">
<div class="up">上</div>
<div class="down">下</div>
<div class="left">左</div>
<div class="right">右</div>
<div class="forward">前</div>
<div class="back">後</div>
</div>
</body>
</html>
動畫
動畫是CSS3中具有顛覆性的特征,可通過設置多個節點 來精確控制一個或一組動畫,常用來實現複雜的動畫效果。
1、定義動畫的步驟
(1)通過@keyframes定義動畫;
(2)將這段動畫通過百分比,分割成多個節點;然後各節點中分別定義各屬性;
(3)在指定元素里,通過 animation
屬性調用動畫。
之前,我們在 js 中定義一個函數的時候,是先定義,再調用:
js 定義函數:
function fun