过渡,变换与动画
过渡transition
通常,我们的css样式是静态的,也就是说css中定义的属性就是页面渲染后的最终呈现效果。但发生像为某个元素设置:hover伪类并且此时改变一些属性(鼠标悬停在该元素时样式生效),或者使用JavaScript修改页面的某些元素的style这类操作,如果我们为该元素的一个或多个css属性中设置了过渡,那么当它们发生改变时,它会由初始值相对缓慢地变成新值,而不是直接变成新值,其中过渡的中间效果由浏览器实现。简写属性transition依次接收四个参数:
- transition-property:需要进行过渡的属性。可以设置为关键字all,表示所有过渡能生效的属性都进行过渡;
- transition-duration:过渡持续的时间;
- transition-timing-function:定时函数,控制过渡过程中变化率如何加速或减速;
- transition-delay:延迟时间,表示经过指定时间后过渡才开始生效;
一个过渡高度值的菜单
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .dropdown_toggle{ display: block; padding: 0.5em 1em; border: 1px solid hsl(280,10%,80%); color: hsl(280,30%,60%); background-color: white; text-decoration: none; transition: background-color 0.2s linear; } .dropdown_toggle:hover{ background-color: hsl(280,15%,95%); } .dropdown_drawer{ position: absolute; background-color: white; width: 150px; height: 0; /*关闭状态下高度为0,且溢出部分隐藏*/ overflow: hidden; transition: height 1s ease-out; /*为高度添加过渡属性*/ text-align: center; } .dropdown.is-open .dropdown_drawer{ /*打开状态时的高度由内容确定*/ height: auto; } .menu{ padding-left: 0; margin: 0; list-style: none; } .menu >li+li >a{ border-top: 0; } .menu>li>a{ display: block; padding: 0.5em 1em; color: hsl(280,40%,60%); background-color: white; text-decoration: none; transition: all .2s linear; border: 1px solid hsl(280,10%,80%); } .menu>li>a:hover{ background-color: hsl(280,15%,95%); color: hsl(280,25%,10%); } </style> </head> <body> <div class="dropdown" aria-haspopup="true"> <button class="dropdown_toggle" style="width: 150px">Menu</button> <div class="dropdown_drawer"> <ul class="menu" role="menu"> <li role="menuitem"> <a href="/features">Features</a> </li> <li role="menuitem"> <a href="/pricing">Pricing</a> </li> <li role="menuitem"> <a href="/support">Support</a> </li> <li role="menuitem"> <a href="/about">About</a> </li> </ul> </div> </div> </body> <script type="text/javascript"> (function (){ var toggle = document.getElementsByClassName('dropdown_toggle')[0]; var dropdown = toggle.parentElement; var drawer = document.getElementsByClassName('dropdown_drawer')[0]; var height = drawer.scrollHeight toggle.addEventListener('click',function (e){ e.preventDefault(); dropdown.classList.toggle('is-open'); //点击后,为.dropdown添加.is-open类,表示菜单打开状态 if(dropdown.classList.contains('is-open')){ drawer.style.setProperty('height',height+'px');//打开状态时精确设置高度值 }else { drawer.style.setProperty('height','0')//关闭状态时高度设置为0,可以实现关闭时的滑动效果 } }); }()); </script> </html>
我们想让用户在点击菜单时,菜单项滑动打开,也即高度由0过渡到菜单项内容占据的高度。但由于并不清楚菜单项容器的高度是多少,一开始我想让高度值由0过渡到auto,但发现过渡不生效。因此,使用JavaScript获取容器的scrollHeight属性值,来计算容器的高度,然后在菜单被点击时修改.is-open状态下容器的高度,这样就能使高度由0过渡到确切值。
变换transform
使用transform可以改变元素的形状和位置,其中包括二维或三维的平移、旋转、缩放和倾斜。通常结合过渡或动画一起使用。它有如下变换规则:
- rotate(angle):元素绕一个轴心转动一定角度,值为<angle>deg;在2D空间上rotate()相当于rotateZ(),也即绕Z轴旋转;
- translate(x,[y,[z):元素沿着x轴、y轴和z轴分别移动,值为长度或百分比;
- scale(sx,xy):缩小或放大元素,可以为不同方向设置不同的缩放值。当需要进行3D空间上的缩放时必须使用Scale3D();
- skew(sx,xy):倾斜元素,参数分别指定x轴与y轴方向上的倾斜量
通常,元素的变换是基于元素中心的,我们可以使用transform-origin属性来更改变换的基点。
坐标系
坐标系会随着元素的变换进行改变,因此要注意使用多重变换时,每次变换的参考坐标系是怎样的。正常的3D视角下,坐标系中的Z轴正方向指向屏幕外的我们。
3D变换
首先要理解“透视距离”,可以把透视距离想象成摄像机与物体之间的距离,镜头越近(透视距离越小),3D效果越强。下面是不同透视距离的效果,可以看到虚线连接的交点处与摄像机的距离便是“透视距离”。
默认情况下,透视距离的渲染是假设镜头在元素中心的正前方,可以通过修改perspective-origin属性来上下左右移动镜头的位置。
实现一个简单的3D立方体
代码实现:
<!DOCTYPE html> <html> <head> <title>一个简单的3D立方体</title> <style> .container { margin: 0 auto; width: 400px; height:400px; background:#d8d8d8; border: 4px solid rgba(255, 0, 0, 0.9); border-radius: 10%; } .cube { position: relative; width: 200px; height: 200px; margin: 100px auto; transform-style:preserve-3d; perspective: 800px; perspective-origin: -50% -100px; /*修改透视角度,使更好地观察图像*/ } .cube div { position: absolute; width: 200px; /*初始状态时,立方体的六个面都重叠在一起,此时的位置就是它们的初始位置*/ height: 200px; background: rgba(255,255,255,0.1); box-shadow: inset 0 0 30px rgba(125,125,125,0.8); text-align: center; line-height: 200px; font-weight:bold; text-shadow:-1px 1px 5px #f60; color:#fff; font-family: sans-serif; text-transform: uppercase; font-size:30px; } .front { transform: translateZ(100px); /*front面向屏幕方向前进100px*/ } .back { transform: translateZ(-100px) rotateY(180deg); /*back面先后退100px,再沿Y轴旋转180度(也即向下旋转一周进行翻面)*/ } .left { transform:rotateY(270deg) translateX(-100px); transform-origin: left; /*先以正方形的左边为基点,绕Y轴旋转270度,此时坐标轴改变,X轴正向指向屏幕外,然后沿X轴负方向移动100px*/ } .right { transform:rotateY(-270deg) translateX(100px); transform-origin:right; /*先以正方形的右边为基点,绕Y轴负方向旋转270度(正向90度),此时X轴正向指向屏幕里,然后沿X轴正向移动100px*/ } .top { transform:rotateX(90deg) translateY(-100px); transform-origin: top; } .bottom { transform:rotateX(90deg) translateY(100px); transform-origin: bottom; } </style> </head> <body> <div class="container"> <div class="cube"> <div class="front">front</div> <div class="back">back</div> <div class="top">top</div> <div class="bottom">bottom</div> <div class="left">left</div> <div class="right">right</div> </div> </div> </body> </html>
动画animation
CSS中的动画由两部分组成——用来定义动画关键帧的@keyframes规则以及为元素添加动画的animation属性。从原理上看,过渡和关键帧动画类似:过渡是定义了第一帧(起始点)和最后一帧(结束点),由浏览器计算中间过程的值,使元素实现平滑变换;而关键帧动画则不局限于起始点和结束点,在中间过程我们可以添加自己想要的值,从而生成一系列无缝衔接的过渡。
简写的animation属性包含以下几个属性:
animation-name:动画的名称,该名称需要放在@keyframes规则后面进行指定;
animation-duration:动画持续的时间;
animation-timing-function:与transition属性一样,是定时函数;
animation-iteration-count:动画的重复次数,默认值为1
实现一个加载动画
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .loading{ width: 150px; height: 15px; margin: 100px auto 0; } .loading span{ display: inline-block; width: 15px; height: 100%; margin-right: 5px; border-radius: 50%; background-color: lightgreen; animation: load 1.04s ease infinite; } .loading span:last-child{ margin-right: 0; } @keyframes load { 0%{ opacity: 1; } 100%{ opacity: 0; } } .loading span:nth-child(1){ animation-delay: 0.13s; } .loading span:nth-child(2){ animation-delay: 0.26s; } .loading span:nth-child(3){ animation-delay: 0.39s; } .loading span:nth-child(4){ animation-delay: 0.52s; } .loading span:nth-child(5){ animation-delay: 0.65s; } </style> </head> <body> <div class="loading"> <span></span> <span></span> <span></span> <span></span> <span></span> </div> </body> </html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)