3.1、什么是空间转换
前面我们所讲解的平面转换我们只关心x轴和y轴,空间转换就涉及到了Y轴
空间:是从坐标轴角度定义的。x、y、z,三条坐标轴构成了一个立体空间,z轴位置与视线方向相同
空间转换也被叫做3D转换
-
语法
-
transform:translate3d(x,y,z)
-
transform:translateX(值)
-
transform:translateY(值)
-
transform:translateZ(值)
-
-
取值(正负均可)
- 像素单位数值
- 百分比
3.2、perspective属性实现透视
-
思考:生活中,同一个物体,观察距离不同,视觉上有什么区别?
- 答:近大远小、近清楚远模糊
-
思考:默认情况下为什么没办法观察到Z轴的位移效果
- 答:Z轴是视线方向,移动效果应该是距离的远或者近,电脑屏幕是平面的,默认是无法观察到远近效果的
-
属性(添加给父级)
-
perspective 值
-
取值:像素单位数值,数值一般在800-1200
-
透视距离也被称为视距,所谓视距就是人的眼睛到屏幕的距离
-
-
作用
- 空间转换时,为元素添加近大远小、近实远虚的视觉效果
3.3、空间位移
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
body{
/* 视距:眼睛到屏幕的距离是800 */
perspective: 800px;
}
.box{
width: 200px;
height: 200px;
background-color: red;
transition: all .5s;
margin: 200px auto;
}
.box:hover{
/* 盒子向你移动200px 变大效果 */
transform: translateZ(200px);
/* 盒子向里移动200px 变小效果 负值时往里面去越来越小*/
transform: translateZ(-200px);
/* 复合写法 */
transform: translate3d(0,-50px,0px);
}
</style>
<body>
<div class="box"></div>
</body>
</html>
3.4、空间旋转
- 语法
transform: rotateZ(值);
transform: rotateX(值);
transform: rotateY(值);
- 左手法则
- 判断旋转方向: 左手握住旋转轴, 拇指指向正值方向, 手指弯曲方向为旋转正值方向
- 拓展
rotate3d(x, y, z, 角度度数)
:用来设置自定义旋转轴的位置及旋转的角度- x,y,z 取值为0-1之间的数字
1、空间旋转Z轴
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
/* 透视 */
perspective: 500px;
}
img {
display: block;
margin: 100px auto;
transition: all 3s;
transform-origin: left top;
}
img:active {
/* 正值图片往后倒--负值图片往前倾 */
transform: rotateX(60deg);
}
</style>
</head>
<body>
<img src="./images/hero.jpeg" alt="">
</body>
</html>
2、空间旋转Y轴
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
/* 透视 */
perspective: 500px;
}
img {
display: block;
margin: 100px auto;
transition: all 1s;
}
img:active {
/* 正数:往电脑里边倾斜,负数:往我这方便倾斜 */
transform: rotateY(-60deg);
/* 复合写法 */
/* transform: rotate3d(x,y,z,度数); */
transform: rotate3d(1,0,0,60deg);
/* 以对角线旋转--平面旋转*/
transform: rotate3d(1,1,0,60deg);
/* 以对角线旋转--立体旋转*/
transform: rotate3d(1,1,1,360deg);
}
</style>
</head>
<body>
<img src="./images/hero.jpeg" alt="">
</body>
</html>
3.5、立体呈现
前面讲解了使用perspective属性实现设置视觉、达到立体的旋转位移效果、思考下使用perspective透视属性能否呈现立体图形?
- 答:不可以
那么如何实现3D
立体呈现?实现方式如下:
- 添加
transform-style: preserve-3d
; - 使子元素处于真正的3d空间
- 默认值flat, 表示子元素处于
2D
平面内呈现
注意:空间内,转换元素都有自己独立的坐标轴、互不干扰
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>立体呈现</title>
<style>
body{
perspective: 600px;
}
.box{
width: 200px;
height: 200px;
background-color: pink;
margin: 100px auto;
perspective: 600px;
transform: rotateY(0deg);
/* 给父元素添加、子元素呈现3d效果 */
transform-style: preserve-3d;
}
.son{
width: 100px;
height: 200px;
background-color: yellowgreen;
transform: rotateX(60deg);
}
</style>
</head>
<body>
<div class="box">
<div class="son"></div>
</div>
</body>
</html>
3.6、案例:立体导航
实现思路
- 搭建立方体:绿色盒子是立方体的前面,橙色盒子是立方体的上面
- 添加hover状态旋转切换效果
实现步骤
-
搭建立方体
- 调节a标签的位置
- a标签定位(子绝父相)
- 英文部分添加旋转和位移样式
- 中文部分添加位移样式
- 调节a标签的位置
-
过渡效果
- 鼠标滑过li,添加空间旋转样式
- li添加过渡属性
注意:案例完成后,删除li的旋转样式
测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
.nav{
transform-style:preserve-3d ;
}
.nav li{
width: 100px;
height: 40px;
background-color: pink;
float: left;
margin: 30px;
list-style: none;
position: relative;
transform-style:preserve-3d;
transform: rotateY(0deg);
transition: all .5s;
}
.nav span{
width: 100px;
height: 40px;
position: absolute;
top: 0px;
left: 0px;
background-color: slateblue;
color: #fff;
line-height: 40px;
text-align: center;
}
.nav span:nth-child(1){
background-color: #ff3040;
/* 正数时靠近自己、负数是远离自己 */
transform: translateZ(20px);
}
.nav span:nth-child(2){
background-color: #3040ff;
transform: translateY(20px) rotateX(-90deg);
/* transform: rotateX(-60deg); */
/* transform: rotateX(-90deg); */
}
.nav li:hover{
transform: rotateX(90deg);
}
</style>
</head>
<body>
<ul class="nav">
<li>
<span>祝大家</span>
<span>一帆风顺</span>
</li>
<li>
<span>祝大家</span>
<span>二龙戏珠</span>
</li>
<li>
<span>祝大家</span>
<span>三洋开泰</span>
</li>
</ul>
</body>
</html>
3.7、案例:立方体
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* *{
margin: 0;
padding: 0;
} */
.box{
position: relative;
width: 200px;
height: 200px;
background-color: pink;
margin: 200px auto;
transform-style: preserve-3d;
transition: all .5s;
/* perspective: 800px; */
transform: rotateY(0deg);
}
.box div{
position: absolute;
top: 0px;
left: 0px;
width: 200px;
height: 200px;
}
.front{
background-color: pink;
transform: translateZ(100px);
}
.back{
background-color: brown;
transform: translateZ(-100px) rotateY(180deg);
}
.left{
background-color: green;
/* 先位移、然后在向左转 */
transform: translateX(-100px) rotateY(-90deg);
}
.right{
background-color: yellow;
/* 先位移、然后在向左转 */
transform: translateX(100px) rotateY(90deg);
}
.top{
background-color: magenta;
transform: translateY(-100px) rotateX(90deg);
}
.bottom{
background-color: yellowgreen;
transform: translateY(100px) rotateX(-90deg);
}
.box:hover{
transform: rotateY(360deg);
}
</style>
</head>
<body>
<div class="box">
<div class="front">前面</div>
<div class="back">后面</div>
<div class="left">左面</div>
<div class="right">右面</div>
<div class="top">上面</div>
<div class="bottom">下面</div>
</div>
</body>
</html>
<script>
const box = document.querySelector('.box');
let rotationAngle = 0;
function rotateCube() {
box.style.transform = `rotateY(${rotationAngle}deg)`;
rotationAngle += 10; // 每次增加10度角
// 无论角度大小,始终在100毫秒后再次调用自身
setTimeout(rotateCube, 100);
}
// 当页面加载完成时开始旋转立方体
window.onload = () => {
if (box !== null) {
rotateCube();
} else {
console.error("Element with class '.box' not found!");
}
};
</script>
3.8、空间缩放
- 语法
transform: scaleX(倍数);
transform: scaleY(倍数);
transform: scaleZ(倍数);
transform: scale3d(x, y, z);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
width: 200px;
height: 200px;
margin: 100px auto;
background-color: pink;
transition: all .5s;
}
div:active{
/* 代表宽高同时放大缩小 */
/* transform: scale(2); */
/* 宽放大两倍,高放大三倍 */
/* transform: scale(2,3); */
transform: scaleX(2);
transform: scaleY(2);
}
</style>
</head>
<body>
<div></div>
</body>
</html>
3.9、animation动画
过渡可以实现什么效果?
可以实现2个状态间的变化过程
动画的本质
动画的本质是快速切换大量图片时在人脑中形成具有连续性的画面
构成动画的基本最小单元:帧或者动画帧
动画的实现步骤
定义一个动画
@keyframes 动画名称{
from{}
to{}
}
@keyframes 动画名称{
0%{}
10%{}
15%{}
100%{}
}
使用动画
animation: 动画名称 动画花费时长
体会动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.box{
width: 200px;
height: 200px;
background-color: pink;
animation: move 2s;
}
/* 定义动画 move就是动画名称*/
@keyframes move {
from{
transform: translateX(0);
}
to{
transform: translateX(1000px);
}
}
</style>
<body>
<div class="box"></div>
</body>
</html>
3.1、动画讲解
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box{
width: 200px;
height: 200px;
background-color: pink;
/* animation: 动画名称 动画时间 运动曲线 延迟时间 运动次数 运动方向 执行完毕时的状态; */
/* animation: name duration timing-function delay iteration-count direction fill-mode; */
/* animation: run 5s; 简写形式*/
/* 一、timing-function 运动曲线:
1、ease 默认值 动画以低速度开始,然后加快,在结束前变慢
2、linear 动画从头到尾的速度是相同的 匀速
3、steps(5) 5秒内走五步、时钟一样跳跃
二、delay: 延迟开始
1、什么时候开始
三、iteration-count 运动次数 执行次数 infinite无线运动
1、animation: run 5s linear 0s infinite;
四、direction 运动方向
1、normal 默然值,动画按正常播放
2、reverse 反向动画
3、alternate 反复运动
五、 fill-mode 执行完毕时的状态
1、forwards 停留在最后状态 他不能和 infinite reverse一起用
2、backwards 回到最初始的状态
*/
animation: run 2s linear 0s infinite reverse;
}
@keyframes run{
0%{
transform: translateX(0);
}
100%{
transform: translateX(1000px);
}
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
3.2、多组动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box{
width: 100px;
height: 100px;
background-color: yellow;
border-top: 10px solid green;
/*时间的拆分 */
animation: go 10s linear;
}
@keyframes go {
0%{
transform: translateX(0);
}
25%{
transform: translateX(1000px);
}
50%{
/* 会层叠上一个,所以我们要保留 transform translatex(1000px) */
transform: translateX(1000px) translateY(500px);
}
75%{
/* 会层叠上一个,所以我们要保留 transform translatex(1000px) */
transform: translateX(0px) translateY(500px);
}
100%{
transform: translateY(0);
}
}
</style>
</head>
<body>
<div class="box">奔跑的琪琪</div>
</body>
</html>
3.3、风车案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 定义动画 */
@keyframes rotate{
/* 这里可以删掉、因为一开始就没转 */
/* 0%{
transform: rotate(0deg);
} */
100%{
transform: rotate(360deg);
}
}
/* 使用动画 */
img{
animation: rotate 1s infinite linear;
}
img:nth-child(2n){
/* 偶数反着转 */
animation-direction: reverse;
}
</style>
</head>
<body>
<img src="./images/1148.png_860.png" width="400px" height="400px" alt="">
<img src="./images/1148.png_860.png" width="400px" height="400px" alt="">
</body>
</html>
3.4、心跳案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
img{
display: block;
width: 300px;
margin: 200px auto;
animation: jump .3s infinite alternate;
}
@keyframes jump {
0%{
transform: scale(1);
}
100%{
transform: scale(1.1);
}
}
</style>
</head>
<body>
<img src="./images/4.jpg" alt="">
</body>
</html>
3.5、动画暂停
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
img {
/* 2. 调用动画 */
/* background: #fff no-repeat; */
animation: rotate 1s infinite linear;
/* animation-name: rotate;
animation-duration: 2s;
animation-iteration-count: infinite; */
}
img:hover {
/* 鼠标经过暂停动画 */
animation-play-state: paused;
}
/* 1. 定义动画 */
@keyframes rotate {
to {
transform: rotate(1turn);
}
}
</style>
</head>
<body>
<img src="./images/pic.png" alt="">
</body>
</html>
3.6、案例:剑客
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 140px;
height: 140px;
background: url(./images/bg.png) no-repeat;
/* 2.调用动画 逐帧动画 steps()*/
/* animation: move 1s; */
/* 多组动画,用逗号隔开 */
animation: move .5s steps(12) infinite, run 2s linear forwards;
/* animation: run 1s; */
}
/* 1. 定义动画 */
@keyframes move {
to {
background-position: -1680px 0;
}
}
/* 重新定义一组动画 run */
@keyframes run {
to {
transform: translateX(500px);
}
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
3.7、案例:无缝滚动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
/* box-sizing: border-box; */
}
li {
list-style-type: none;
}
.box {
overflow: hidden;
margin: 100px auto;
width: 600px;
height: 150px;
border: 3px solid #000;
}
.box li {
float: left;
width: 200px;
height: 150px;
}
.box li img {
width: 100%;
height: 100%;
}
/* 停止动画 鼠标经过box 但是停止的是 ul */
.box:hover ul {
animation-play-state: paused;
}
/* 让ul足够宽,小li就不会掉下来 */
/* ul 滚动 */
.box ul {
width: 2000px;
/* 调用动画 */
animation: move 5s linear infinite;
}
/* 定义动画 */
@keyframes move {
to {
transform: translateX(-1400px);
}
}
</style>
</head>
<body>
<div class="box">
<ul>
<li><a href="#"><img src="./images/1.jpg" alt=""></a></li>
<li><a href="#"><img src="./images/2.jpg" alt=""></a></li>
<li><a href="#"><img src="./images/3.jpg" alt=""></a></li>
<li><a href="#"><img src="./images/4.jpg" alt=""></a></li>
<li><a href="#"><img src="./images/5.jpg" alt=""></a></li>
<li><a href="#"><img src="./images/6.jpg" alt=""></a></li>
<li><a href="#"><img src="./images/7.jpg" alt=""></a></li>
<!-- 复制三张 -->
<li><a href="#"><img src="./images/1.jpg" alt=""></a></li>
<li><a href="#"><img src="./images/2.jpg" alt=""></a></li>
<li><a href="#"><img src="./images/3.jpg" alt=""></a></li>
</ul>
</div>
</body>
</html>
3.8、案例:小熊奔跑
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>奔跑的小熊熊</title>
<style>
body {
background-color: #ccc;
}
.bg1 {
/* 使背景1在中间 */
z-index: 2;
position: absolute;
top: 200px;
width: 100%;
height: 336px;
background: url(./images/bg1.png) no-repeat;
animation: bgmove 30s linear infinite;
}
.bg2 {
/* 使背景2在最下面 */
z-index: 1;
position: absolute;
width: 100%;
height: 569px;
background: url(./images/bg2.png) no-repeat;
animation: bgmove 30s linear infinite;
}
.bear {
/* 使北极熊在最上方 */
z-index: 3;
position: absolute;
top: 460px;
/* 可装一只小熊的宽和高 */
width: 200px;
height: 100px;
background: url(./images/bear.png) no-repeat;
/* 我们元素可以添加多个动画 添加的方法是用逗号分隔 */
animation: bear 1s steps(8) infinite, bearmove 3s forwards;
}
@keyframes bear {
0% {
background-position: 0 0;
}
100% {
background-position: -1600px 0;
}
}
@keyframes bearmove {
0% {
left: 0;
}
100% {
left: 50%;
/* 走50%后超过中心位置,需要再往回走小熊宽度的一半 但换算过于麻烦 */
/* margin-left: -100px; */
transform: translateX(-50%);
}
}
@keyframes bgmove {
0% {
background-position: 0 0;
}
100% {
background-position: -1700px 0;
}
}
</style>
</head>
<body>
<div class="bg1"></div>
<div class="bg2"></div>
<div class="bear"></div>
</body>
</html>
3.9、案例:全民出游
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
}
.box {
width: 100%;
height: 100%;
background: url('images/f1_1.jpg') no-repeat top center;
background-size: cover;
position: relative;
}
.cloud img {
position: absolute;
left: 50%;
}
.cloud img:nth-child(1) {
top: 20px;
margin-left: -260px;
animation: cloud 2s linear infinite alternate;
}
.cloud img:nth-child(2) {
top: 100px;
margin-left: 380px;
animation: cloud 2.5s linear infinite alternate;
}
.cloud img:nth-child(3) {
top: 200px;
margin-left: -560px;
animation: cloud 3s linear infinite alternate;
}
.balloon {
position: absolute;
left: 50%;
top: 20%;
margin-left: -390px;
animation: balloon 1.5s linear alternate infinite;
}
.giraffe {
position: absolute;
left: 50%;
margin-left: 160px;
top: 15%;
}
.text {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
animation: text 1s ease forwards;
}
.jump_text img {
position: absolute;
left: 50%;
bottom: 42px;
width: 100px;
}
.jump_text img:nth-child(1) {
margin-left: -390px;
animation: jump_text 0.8s infinite alternate;
}
.jump_text img:nth-child(2) {
margin-left: -180px;
animation: jump_text 0.8s 0.2s infinite alternate;
}
.jump_text img:nth-child(3) {
margin-left: 35px;
animation: jump_text 0.8s 0.4s infinite alternate;
}
.jump_text img:nth-child(4) {
margin-left: 240px;
animation: jump_text 0.8s 0.6s infinite alternate;
}
/* 白云动画 */
@keyframes cloud {
0% {
transform: translateX(0px);
}
100% {
transform: translateX(40px);
}
}
/* 热气球动画 */
@keyframes balloon {
0% {
transform: translateY(0px);
}
100% {
transform: translateY(-30px);
}
}
/* 跳动文字 */
@keyframes jump_text {
0% {
transform: translateY(0px);
}
100% {
transform: translateY(-30px);
}
}
/* 文字 */
/* 注意:因为transform是复合属性,所以我们要重新申明一遍translate */
@keyframes text {
0% {
transform: translate(-50%, -50%) scale(1);
}
20% {
transform: translate(-50%, -50%) scale(0);
}
40% {
transform: translate(-50%, -50%) scale(1.4);
}
70% {
transform: translate(-50%, -50%) scale(0.8);
}
100% {
transform: translate(-50%, -50%) scale(1);
}
}
</style>
</head>
<body>
<div class="box">
<!-- 白云 -->
<div class="cloud">
<img src="images/yun1.png" />
<img src="images/yun2.png" />
<img src="images/yun3.png" />
</div>
<!-- 热气球 -->
<div class="balloon">
<img src="images/san.png" />
</div>
<!-- 长颈鹿 -->
<div class="giraffe">
<img src="images/lu.png" />
</div>
<!-- 文字 -->
<div class="text">
<img src="images/font1.png" />
</div>
<!-- 跳动文字 -->
<div class="jump_text">
<img src="images/1.png" />
<img src="images/2.png" />
<img src="images/3.png" />
<img src="images/4.png" />
</div>
</div>
</body>
</html>