css进阶--02
HTML-CSSbasecss进阶第二部分,包括平面及空间转换、动画效果
写在前面:此笔记对应课程为b站前端Web开发HTML5+CSS3+移动web视频教程
平面转换
平面转换也称2D转换,改变盒子在平面内的形态(位移、旋转、缩放、倾斜等),一般与过渡配合使用,从而为元素添加动态效果。
约定平面内坐标轴如图:
即水平X轴正向为右侧,垂直Y轴正向为下侧
平移
transform:translate(X轴移动距离,Y轴移动距离)
两个移动距离的取值:
-
px单位
-
百分比(参照盒子自身尺寸)
-
可正可负
例:鼠标移入父盒子,子盒子改变位置
<style>
.father {
width: 500px;
height: 300px;
border: 1px solid black;
}
.son {
width: 200px;
height: 100px;
background-color: pink;
transition: all 0.5s;
}
.father:hover .son { /*父盒子hover,改变子盒子属性*/
transform: translate(200px, 100px);
}
</style>
<body>
<div class="father">
<div class="son">我是小盒子</div>
</div>
</body>
效果:当鼠标进入父盒子后,子盒子移动;鼠标出父盒子,子盒子再移回原来的位置。
->
其中transform: translate(200px, 100px);
表示向右移动200px,向下移动100px,设置为负就是往反方向;
transform: translate(50%, 100%);
表示向右移动自身宽度的50%,向下移动自身高度的100%,设置为负就是往反方向;
translate()
也可以只传入一个值,表示沿X轴移动的距离,取值同上;
也可以单独设置X和Y轴移动距离:translateX()
和translateY()
,取值同上。
例:双开门效果–两张图片横向放置:
鼠标放上去时,两张图片分别向左/右移动:
最后显示出下层图片:
鼠标移走后图片又自动恢复原来的状态。
布局:父子结构,父级是下层的大图,子级是上层的两张小图。初始状态下子级图片会自动覆盖父级图片。
其中两张小图的资源图片是精灵图,即尺寸与大图相同,能正好覆盖两个小盒子,需要设置右子盒子的background-position,使它显示精灵图的右半部分
<style>
*{
margin: 0;
padding: 0;
}
.box {
display: flex; /*弹性布局,自动使两张小图左右排列*/
margin: 50px auto; /*水平居中*/
width: 1366px;
height: 600px;
background-image: url(./bg.jpg);
overflow: hidden; /*超出部分隐藏,让移动后两张小图超出大图的部分消失*/
}
.box .left,
.box .right{
width: 50%; /*宽度是父级的一半*/
height: 100%; /*高度与父级相同*/
background-image: url(./fm.jpg);
transition: all .5s; /*.5s相当于0.5s*/
}
.box .right{
background-position: right 0; /*right表示取图片的右侧,0就是上下位置不变*/
}
.box:hover .left{
transform: translate(-100%); /*往左移动一倍的自身宽度*/
}
.box:hover .right{
transform: translateX(100%); /*往右移动一倍的自身宽度*/
}
</style>
<body>
<div class="box">
<div class="left"></div>
<div class="right"></div>
</div>
</body>
旋转
transform:rotate(旋转角度)
角度单位是deg
(就是°),取值正负均可,正–顺时针旋转、负–逆时针旋转。
常与transition联用,以形成旋转的动画。
如transform:rotate(360deg)
就是顺时针旋转一圈
改变转换原点
默认情况下,所有转换的原点都是盒子中心点,如旋转是绕中心旋转。
有些时候需要改变转换原点,如时钟的秒/分/时针就是以端点为旋转中心:
transform-origin:水平原点位置 垂直原点位置
取值:
-
方位名词(left top right bottom center)
-
px
-
百分比
常用方位名词,如transform-origin:right bottom
表示以图片(盒子)的右下角端点旋转
例:时钟,已有初始状态如下
需要将三根表针以它们的正下端旋转:
transform-origin: center bottom; /*改变转换原点*/
transform: rotate(360deg);
transition: all 60s; /*转一圈60s*/
多重转换
即同时进行平移和旋转
注意:要先平移再旋转
transform:translate() rotate()
例:滚动的轮胎
设大盒子宽度为800px,轮胎宽度200px,则滚动距离应为600px
img{
transition: all 5s;
}
.box:hover img {
transform: translate(600px) rotate(360deg);
}
为什么必须先平移再旋转:
transform
以第一种转换形态的坐标轴为准,而旋转会改变坐标轴方向,而translate(600px)
是以x轴为平移方向,x轴方向改变,平移方向也改变,导致图片螺旋运动。
为什么不能分开写两个transform
属性:
旋转平移都是transform属性,后面的transform会覆盖前面的。
缩放
实现图片放大效果:正常状态下–
当鼠标移到图片上时–
(鼠标移出时图片复原)
使用:transform:scale(缩放倍数)
表示XY轴均按此倍数等比例缩放,也可单独设置:
transform:scale(X轴缩放倍数,Y轴缩放倍数)
取值大于1表示放大,小于1表示缩小,等于1则不变;
默认以中心点为原点进行缩放
.box {
overflow: hidden; /*超出部分隐藏,保证总大小不变*/
}
.box img {
transition: all 0.5s;
}
.box:hover img {
transform: scale(1.1); /*放大1.1倍*/
}
如果使用width和height进行设置,则是图片以左上角为原点缩放,向右下方扩大,不好看
例:播放效果–鼠标进入大图片时,播放按钮显示到图片中间;移出时按钮放大并消失。
效果:
初始状态:
当鼠标移到图片上时: ->
分析:按钮是悬浮在图片之上的,所以使用子绝父相,同时居中定位;在居中定位时,使用margin
设置最好,若使用translate
需要为hover前后都添加该属性,要不transform
会覆盖;
关于缩放效果:初始状态播放按钮处于放大并隐藏状态,当移到图片上时,按钮缩小并显示。
核心代码:
.pic {
position: relative; /*子绝父相--悬浮效果*/
overflow: hidden; /*超出部分不可见*/
}
.pic::after { /*使用伪元素的背景图片放置按钮*/
position: absolute; /*子绝父相--悬浮效果*/
left: 50%;
top: 50%;
/* transform: translate(-50%, -50%); 居中定位,为避免transform覆盖与缩放写到一起*/
content: ''; /*伪元素必须设置content:""属性用来设置内容*/
opacity: 0; /*初始状态下不可见*/
width: 58px;
height: 58px;
background-image: url(./images/play.png);
transform: translate(-50%, -50%) scale(5);
transition: all .5s;
}
.box li:hover .pic::after {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}
倾斜
transform:skew(倾斜角度)
角度单位是deg
(就是°),取值正负均可,正–向左倾斜、负–向右倾斜。
如transform: skew(30deg);
:
->
渐变
多个颜色逐渐变化的效果,一般用于设置盒子背景
分为线性渐变(从一端向另一端)
和径向渐变(从中心向四周)
线性渐变
background-image: linear-gradient(渐变方向,颜色1 终点位置1,颜色2 终点位置2,...)
表示从终点位置1
到终点位置2
是颜色1
到颜色2
的渐变,…
-
渐变方向:可选,取值为
to 方位名词
或角度度数;默认从上到下竖直方向,若为to right
就是从左到右 -
终点位置:可选,取值为百分比;默认按传入的颜色数均分
background-image: linear-gradient(
45deg,
red 80%,
green
);
background-image: linear-gradient(
to right,
red,
green
);
例:为图片添加渐变背景,使图片下部的文字更加清晰
->
.mask { /*单独设置一个盒子作渐变,之后把盒子加到图片上*/
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%; /*把盒子加到图片上,绝对定位(子绝父相)、位置靠左上、宽高同父级*/
background-image: linear-gradient(
transparent, /*透明色*/
rgba(0,0,0,0.5) /*半透明黑色*/
);
}
径向渐变
background-image: radial-gradient(半径 at 圆心水平位置 圆心垂直位置,颜色1 终点位置1,颜色2 终点位置2,...)
-
半径可以为2条,此时为椭圆
-
圆心位置取值:像素单位数值/百分比/方位名词
.box {
width: 100px;
height: 100px;
background-color: pink;
border-radius: 50%;
}
-
background-image:radial-gradient( 50px at center center, /*在正中心(水平垂直方向的中心)画一个R=50的圆*/ red, /*圆心是red*/ pink /*四周是pink*/ );
-
background-image: radial-gradient( 50px 20px at 50px 30px, red, pink 50% );
-
为按钮添加高光效果:
button { width: 100px; height: 40px; background-color: green; border: 0; border-radius: 5px; color: white; }
高光效果:
background-image: radial-gradient( 50px at 50px 20px, rgba(255, 255, 255, 0.5), transparent );
空间转换
相比平面转换,多了一条Z轴,方向与视线方向相同,即Z轴垂直于屏幕,Z轴正向指向用户(屏幕向外)。因此空间转换也叫3D转换
平移
transform: translate3d(x,y,z)
xyz分别为向对应轴平移的距离,可以是像素单位数值,也可以是百分比(参照盒子自身尺寸)。注意必须传入3个参数
如transform: translate3d(100px,200px,300px);
,因为电脑屏幕是平面,所以只使用平移函数时看不到Z轴的平移效果
上述代码等效于transform: translateX(100px) translateY(200px) translateZ(300px);
视距
指定了观察者与Z=0平面的距离,为元素添加透视效果。
效果:近大远小、近实远虚
perspective:视距值
添加给直接父级,一般视距值取800-1200px
.father {
width: 100px;
height: 100px;
perspective: 800px; /*父级设置视距*/
border: 2px solid black;
}
.son {
width: 100px;
height: 100px;
background-color: pink;
}
.son:hover {
transform: translateZ(-300px);
}
<div class="father">
<div class="son"></div>
</div>
->
可以看到子盒子变小,因为translateZ(-300px)
表示远离人眼,若是translateZ(300px)
则子盒子放大。
规律:同样的位移下,视距越小,变化就越大
旋转
transform: rotateZ(角度值)
因为Z轴穿过图片的中心点,所以它等效于平面旋转
transform: rotateX(角度值)
沿横向轴旋转,如transform: rotateX(60deg)
:
->
角度值为正数时图片上端向屏幕内转,反之外转
为父级元素添加透视属性,可以更清晰地查看图片是向哪个方向旋转:
上边较短,说明上端向屏幕内转
transform: rotateY(角度值)
沿纵向轴旋转;角度值为正数时图片右端向屏幕内转,反之外转
如设置transform: rotateY(60deg)
和透视时的效果:
左手法则–根据旋转方向确定取值正负:左手握住旋转轴,拇指指向轴的正方向,其它四指弯曲方向即为旋转正值方向
不常用:rotate3d(x,y,z,角度)
用来设置自定义旋转轴的位置及旋转角度,其中xyz取值为0-1
立体呈现
设置某个元素的子元素是位于3D空间中还是平面中
transform-style:属性值
属性值:
-
flat
:默认值,子级处于平面中 -
preserve-3d
:子级处于3D空间
呈现立体图形的步骤:
-
父元素设置
transform-style:preserve-3d
-
子级定位(子绝父相)
-
调整子盒子的位置(位移/旋转)
.cube {
width: 200px;
height: 200px;
margin: 100px auto;
transform-style: preserve-3d; /*父元素设置立体呈现*/
position: relative; /*子绝父相*/
transform: rotateY(-30deg) rotateX(-30deg); /*旋转父盒子,使效果更清晰*/
}
.cube div {
position: absolute; /*子绝父相*/
left: 0;
top: 0; /*与父元素位置重合*/
width: 200px;
height: 200px;
opacity: 0.7;
}
.front {
background-color: yellow;
transform: translateZ(100px); /*前面盒子向前移100px*/
}
.back {
background-color: green;
transform: translateZ(-100px); /*后面盒子向后移100px*/
}
<div class="cube">
<div class="front">前面</div>
<div class="back">后面</div>
</div>
没有设置立体呈现时:
设置后:
例:3D翻转
->
思路:
-
搭建立方体:绿色是前面,橙色是上面
-
定位两个面
-
鼠标悬停后旋转
初始状态下:
<div class="nav">
<ul>
<li>
<a href="#">首页</a>
<a href="#">Index</a>
</li>
<li>
<a href="#">登录</a>
<a href="#">Login</a>
</li>
<li>
<a href="#">注册</a>
<a href="#">Register</a>
</li>
</ul>
</div>
核心代码:
.nav li {
position: relative; /*子绝父相*/
transition: all 0.5s; /*翻转动画*/
transform-style: preserve-3d; /*父元素设置立体呈现*/
/* transform: rotateX(-20deg) rotateY(30deg); 为了看到橙色和绿色的移动过程,给立方体添加旋转*/
}
.nav li a {
position: absolute; /*子绝父相*/
left: 0;
top: 0; /*与父元素位置重合*/
}
.nav li a:first-child { /*绿色盒子*/
transform: translateZ(20px); /*绿色Z轴平移*/
}
.nav li a:last-child { /*橙色盒子*/
transform: rotateX(90deg) translateZ(20px); /*橙色X轴旋转 Z轴平移*/
}
.nav li:hover {
transform: rotateX(-90deg);
}
注意:立方体每个面都有单独的坐标轴体系。
在判断橙色面的位移时,我们应该面向橙色,因此
实际上是橙色面Z轴的位移;
而实际上是绿色面Z轴的位移。
缩放
transform: scale3d(x,y,z)
指定三条坐标轴上的缩放倍数,也可以分别指定:
-
transform: scaleX()
-
transform: scaleY()
-
transform: scaleZ()
如transform: scale3d(0.5,2,3)
,取值与平面缩放相同,效果也类似
动画
前面介绍的过渡transform方法都是实现两个状态间的变化;
而动画animation可以实现多个状态间的变化过程,且过程可控(如设置最终画面、是否重复播放、是否暂停等)。
基本用法
定义动画:在<style>
中添加–
@keyframes 动画名称 {
from {...}
to {...}
}
或
@keyframes 动画名称 {
0% {...}
10% {...}
...
100% {...}
}
前者只有起始和结束两个状态,后者可以设置多个中间状态。
其中百分比指的是动画时长的百分比,若设动画时长为2s,0% {...}
就是初始状态,10% {...}
就是2*10%
秒时的状态,依此类推,100% {...}
就是最终状态。
使用动画:在<style>
中的元素选择器ele{...}
中添加–
animation: 动画名称 动画花费时长;
一个简单的例子
例1:盒子宽度从200变化到800
@keyframes change_width {
from {
width: 200px;
}
to {
width: 800px;
}
}
.box {
width: 200px;
height: 100px;
background-color: pink;
animation: change_width 1s; /*时间为1s*/
}
<div class="box"></div>
例2:从200*100变化到300*300变化到800*500
@keyframes change {
0% {
width: 200px;
height: 100px;
}
20% {
width: 300px;
height: 300px;
}
100% {
width: 800px;
height: 500px;
}
}
.box {
width: 200px;
height: 100px;
background-color: pink;
animation: change 2s; /*时间为2s*/
}
<div class="box"></div>
animation属性
animation 动画名称 动画时长 速度曲线 延迟时间 重复次数 动画方向 执行完毕时状态
-
动画名称和动画时长必须有
-
取值不分先后顺序
-
如果有两个时间值,则第一个表示动画时长,第二个表示延迟时间
-
速度曲线:
-
linear
匀速 -
steps(n)
分步动画(分成n部),配合精灵图实现精灵动画 -
通常要不默认值,要不就用steps
-
-
延迟时间:延迟指定秒播放该动画
-
重复次数:
-
一个整数
n
,表示重复执行n次该动画,默认只播放一次 -
infinite
循环播放
-
-
动画方向:
-
alternate
动画先正向播放,再反向复原,一般配合infinite
联用
-
-
执行完毕时状态:不能与
infinite
一起用-
forwards
动画结束状态为@keyframes
中to
或100%
中的样式 -
默认为
backwards
,即停留在@keyframes
中from
或0%
中的样式
-
animation的这些属性也可进行拆分:
属性 | 作用 | 取值 |
---|---|---|
animation-name | 动画名称 | |
animation-duration | 动画时长 | 如1s
|
animation-delay | 延迟时间 | 如1s
|
animation-fill-mode | 动画执行完毕时状态 |
forwards 最后一帧状态,backwards 第一帧状态 |
animation-timing-function | 速度曲线 |
steps(数字) 逐帧动画 |
animation-iteration-count | 重复次数 |
infinite 无限循环,整数值指定循环次数 |
animation-direction | 动画执行方向 |
alternate 为反向 |
animation-play-state | 暂停动画 |
paused 暂停,通常配合:hover 使用,默认值为running 即开始播放动画 |
另一个简单的例子
.box {
width: 200px;
height: 100px;
background-color: pink;
animation: change_width 2s 1s infinite forwards;
/*延迟1s执行 无限循环 先正向后反向*/
}
.box:hover{
animation-play-state: paused;
/*鼠标放到div上时停止执行*/
}
<div class="box"></div>
如果想实现:初始情况下不播放,当鼠标放到div上后才播放,就需要写成
.box {
animation-play-state: paused;
/*初始状态不执行*/
}
.box:hover {
animation-play-state: running;
/*鼠标放到div上时开始执行*/
}
走马灯效果
多张图横向排列,从左向右滚动展示
->
准备工作
.border{
width: 600px;
height: 112px;
border:5px solid #000;
margin: 100px auto;
overflow: hidden; /*超出展示框部分隐藏*/
}
img{
width: 200px;
}
<div class="border">
<ul>
<li><img src="1" alt=""></li>
<li><img src="2" alt=""></li>
<li><img src="3" alt=""></li>
<li><img src="4" alt=""></li>
<li><img src="5" alt=""></li>
</ul>
</div>
此时动画结尾时,展示框内为空白。
无缝动画原理:复制开头图片到结尾位置,使第一次图片滚动到头后,显示框内展示开头的几张图片,之后再重新从头播放动画,这样动画的开头和结尾都显示的是相同图片,就可以无缝衔接:
↓
↓
↓
注意复制几张开头的图片到结尾位置取决于展示框宽度,这几张图片的累加宽度应==展示框宽度。
页面结构:
<div class="border">
<ul>
<li><img src="1" alt=""></li>
<li><img src="2" alt=""></li>
<li><img src="3" alt=""></li>
<li><img src="4" alt=""></li>
<li><img src="5" alt=""></li>
<!-- 填补展示框的空白 -->
<li><img src="1" alt=""></li>
<li><img src="2" alt=""></li>
<li><img src="3" alt=""></li>
</ul>
</div>
动画效果:
@keyframes move {
from {
transform: translate(0px);
/*初始位置不移动*/
}
to {
transform: translate(-1000px);
/*往左移5张图片的距离*/
}
}
.border ul {
display: flex; /*使图片横向排列*/
animation: move 6s infinite linear;
}
.border:hover ul{
animation-play-state: paused; /*鼠标移入展示框时暂停*/
}
逐帧动画
如时钟的秒针每秒才动一下,就需要使用逐帧动画。
animation-timing-function: steps(数字): 逐帧动画
其核心是配合CSS精灵图绘制精灵动画:
-
准备显示区域:盒子尺寸与一张精灵小图尺寸相同
-
定义动画:移动背景图
-
from{background-position: 0 0;}
-
to{background-position: -精灵图总宽度 0;}
其中精灵图总宽度=小图个数*小图宽度
-
-
使用动画:steps(N) N是精灵图小图个数
例:小人跑动的效果,使用的精灵图如下
测得小图的宽高为140px,一共12张小图
.border {
width: 140px;
height: 140px;
border: 5px solid #000;
margin: 100px auto;
overflow: hidden;
background-image: url(./精灵动画.png);
animation: run 1s steps(12) infinite;
}
@keyframes run {
from {
background-position: 0 0;
}
to {
background-position: -1680px 0;
}
}
<div class="border"></div>
多组动画
animation:动画1,动画2,...
可以让多个动画叠加,同时播放。
例:让上面的小人跑动,如图
在上面的基础上继续添加–
.border {
animation:
run 1s steps(12) infinite,
move 3s forwards linear
;
}
@keyframes move {
from{
transform: translate(0);
}
to{
transform: translate(800px); /*移动800px*/
}
}
进一步精简上面的代码,可以看到两个动画的from状态都是默认状态:
from{
transform: translate(0);
}
from {
background-position: 0 0;
}
这种动画开始状态与标签默认属性相同的情况,可以省略开始状态的代码。
完整CSS如下:
.border {
width: 140px;
height: 140px;
overflow: hidden;
background-image: url(./精灵动画.png);
animation:
run 1s steps(12) infinite,
move 3s forwards linear;
}
@keyframes move {
to {
transform: translate(800px); /*移动800px*/
}
}
@keyframes run {
to {
background-position: -1680px 0; /*表示精灵图应在的最终位置,即让最后一张图片展示*/
}
}