Hello,亲爱的宝子们?最近我一个前端架构师却临时顶替产品经理的工作,导致最近一周实在太忙了,都没有来得及更新文章。在这里想大家道歉了!也想厚颜无耻的问问大家想我了吗?(●'◡'●)
今天给大家带来一个非常简单,但是效果却相当炸裂的旋转图片视觉差特效。先看效果:
今天咱们就一起来写一下这个特效吧!O(∩_∩)O
一、网格布局
这样的案例,一眼就可以看出来是五个 div 元素包裹了五张不同的图片。直接写出来:
<div><img src="./img/1.jpg"></div>
<div><img src="./img/2.jpg"></div>
<div><img src="./img/3.jpg"></div>
<div><img src="./img/4.jpg"></div>
<div><img src="./img/5.jpg"></div>
这个时候,是没有任何样式效果的:
接下来,我们需要将这五个 div 元素控制成这样穿透性的排版:
简单分析一下,要实现这样的排版,首先需要做到三行三列:
这样的排版,使用 css 中的 Grid 布局(又叫网格布局)是最方便快捷的,于是我们给五个 div 元素添加一个容器,用于划分网格。
<section>
<div><img src="./assets/img/1.jpg"></div>
<div><img src="./assets/img/2.jpg"></div>
<div><img src="./assets/img/3.jpg"></div>
<div><img src="./assets/img/4.jpg"></div>
<div><img src="./assets/img/5.jpg"></div>
</section>
然后,在 css 中给容器设置三行三列的网格布局。
section {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
想了解更多关于 Grid 布局的知识,可以关注我们之后的文章。或者可以访问我男朋友多年前在慕课网录制的《Grid布局基础》。
为了更好的展示效果,我们使用固定定位把容器固定在屏幕中央,并设置相同的宽和高。
section {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
width: 500px;
height: 500px;
margin: auto;
}
通过 Chrome 浏览器的开发者工具,我们把五个 div 元素注释了之后,可以看到渲染之后的网格布局。
这样,我们已经实现了对容器的三行三列的网格布局,但是和我们需要的布局方式还有点点不同。
没错,我们需要类似于合并单元格一样的,存在行和列之间的穿透效果。这里就需要用到 Grid 布局中的网格区域。
grid-template-areas:
"topLeft topLeft topRight"
"bottomLeft center topRight"
"bottomLeft bottomRight bottomRight"
;
我们可以这样定义每一个网格区域,相同的值将会视为同一个区域。但是这样给网格区域命名,有点长了,于是简化一下:
grid-template-areas:
"TL TL TR"
"BL CE TR"
"BL BR BR"
;
这样,就可以在代码的视觉上也可以看出来网格区域的划分:
网格区域已经定义好了,接下来就应该让五个 div 元素来认领这五个网格区域了。
section {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-template-areas:
"TL TL TR"
"BL CE TR"
"BL BR BR"
;
width: 500px;
height: 500px;
margin: auto;
}
div {
overflow: hidden;
}
div:nth-child(1) { grid-area: TL; }
div:nth-child(2) { grid-area: TR; }
div:nth-child(3) { grid-area: BL; }
div:nth-child(4) { grid-area: CE; }
div:nth-child(5) { grid-area: BR; }
这里,我们设置了 div 的溢出为隐藏,这样里面的图片都会局限在对应的 div 范围里面。
基本上布局已经出来了。接下来,我们需要给每一个网格区域之间有一个空隙。
section {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-template-areas:
"TL TL TR"
"BL CE TR"
"BL BR BR"
;
gap: 10px;
width: 500px;
height: 500px;
margin: auto;
}
div {
border: 5px solid #696969;
overflow: hidden;
}
通过 gap 属性控制弹性盒模型的空隙,同时也给 div 一个 5px 的灰色边框,于是我们得到了想要的布局效果:
这里,我们再优化一下,让每一个 div 的图片都居中显示:
div {
display: flex;
justify-content: center;
align-items: center;
border: 5px solid #696969;
overflow: hidden;
}
看一下效果:
感觉,图片大小再控制一下就完美了:
div > img {
width: 100%;
}
由于我们的网格区域有长大于宽的矩形,也有长小于宽的矩形。如果设置图片的宽度为 100%,将会有部分网格区域中的图片不能填充满整个网格区域。
我这里就直接写成 300% 了。
div > img {
width: 300%;
}
这就得到了我们需要的效果:
于是,我们巧妙的使用 Grid 布局把五张图片做成了个性化的布局。
二、动画效果
布局已经完成,接下来我们就需要实现旋转的动画效果。
很明显,我们是需要让整个容器顺时针匀速旋转,于是我们先定义一个动画为旋转 360deg 的状态:
@keyframes rotation {
to {
transform: rotate(360deg);
}
}
然后,我们对整个容器调用该动画:
section {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-template-areas:
"TL TL TR"
"BL CE TR"
"BL BR BR"
;
gap: 10px;
width: 500px;
height: 500px;
margin: auto;
animation: rotation 10s linear infinite;
}
这里,我们还是一样设置了 infinite,让其动画可以不断重复。
录制一圈的 GIF 图片大小已经超过 5MB 了,所以我就只录制这一段了,望大家体谅。大家可以代码实现了之后看完整效果。
我们会发现,图片也跟着容器在旋转了。有什么办法让图片不跟着容器一起旋转呢?最简单的办法莫过于“相对运动”。
灵感来源于生活,编程的灵感亦如此。设想一下,当我们和朋友以相同的速度朝着同一个方向迈步向前走的时候,相对于朋友来说,我们就是静止的。同样的道理,如果我们和朋友同样以相同的速度朝着相反的方向迈步走的时候,相对于朋友来说,我们就是以两倍的速度在远离。
物理知识科普完成,回到案例中。现在容器是以顺时针在旋转,图片也跟着容器在顺时针旋转,所以图片相对于容器来说是静止的。但是相对于我们的浏览器窗口,图片和容器都是在顺时针旋转。这个时候,如果我们让图片以相同的角速度逆时针旋转,那么,图片相对于容器来说就是以两倍的角速度逆时针旋转,但是相对于我们的浏览器窗口来说,却刚好与容器的角速度相抵,所以是静止的。
div > img {
width: 300%;
animation: rotation 10s linear infinite reverse;
}
我们在图片中也调用旋转的动画,然后设置 reverse 值,让其动画反向执行,以达到图片逆时针旋转的效果。
至此,我们所需要的效果就已经达到了。
完整源码
还是一样,毫不吝啬的将完整的源代码共享出来。( ̄▽ ̄)"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>旋转中的视觉差效果 - CSS3</title>
<style type="text/css">
section {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-template-areas:
"TL TL TR"
"BL CE TR"
"BL BR BR"
;
gap: 10px;
width: 500px;
height: 500px;
margin: auto;
/* animation: rotation 10s linear infinite;*/
}
div {
display: flex;
justify-content: center;
align-items: center;
border: 5px solid #696969;
overflow: hidden;
}
div:nth-child(1) { grid-area: TL; }
div:nth-child(2) { grid-area: TR; }
div:nth-child(3) { grid-area: BL; }
div:nth-child(4) { grid-area: CE; }
div:nth-child(5) { grid-area: BR; }
div > img {
width: 100%;
/* animation: rotation 10s linear infinite reverse;*/
}
@keyframes rotation {
to {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<section>
<div><img src="./assets/img/1.jpg"></div>
<div><img src="./assets/img/2.jpg"></div>
<div><img src="./assets/img/3.jpg"></div>
<div><img src="./assets/img/4.jpg"></div>
<div><img src="./assets/img/5.jpg"></div>
</section>
</body>
</html>
另外,除了使用 reverse 控制动画反向执行,还可以使用 CSS4 中的变量实现。这里不做展开,附上完整的源代码供大家参考。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>旋转中的视觉差效果 - CSS4</title>
<style type="text/css">
section {
--deg: 360deg;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-template-areas:
"TL TL TR"
"BL CE TR"
"BL BR BR"
;
gap: 10px;
width: 500px;
height: 500px;
margin: auto;
animation: rotation 10s linear infinite;
}
div {
display: flex;
justify-content: center;
align-items: center;
border: 5px solid #696969;
overflow: hidden;
}
div:nth-child(1) { grid-area: TL; }
div:nth-child(2) { grid-area: TR; }
div:nth-child(3) { grid-area: BL; }
div:nth-child(4) { grid-area: CE; }
div:nth-child(5) { grid-area: BR; }
div > img {
--deg: -360deg;
width: 300%;
animation: rotation 10s linear infinite;
}
@keyframes rotation {
to {
transform: rotate(var(--deg));
}
}
</style>
</head>
<body>
<section>
<div><img src="./assets/img/1.jpg"></div>
<div><img src="./assets/img/2.jpg"></div>
<div><img src="./assets/img/3.jpg"></div>
<div><img src="./assets/img/4.jpg"></div>
<div><img src="./assets/img/5.jpg"></div>
</section>
</body>
</html>
↓
↓
↓
尽管共享了我男朋友讲的有关 Grid 布局的课程,但是也是几年前的课程了,如今又有了新的思路,我将会梳理完整的知识点后做系列视频课程分享给大家!让我们尽情期待吧!
关注“临界程序员”微信公众号,为您送上更多精彩内容!