打工人的无奈,公司要求每个人都要进行培训。为了完成它,上网找出好几个demo,都没有勾起我动手实现一波的欲望。日常浏览掘金时,偶然看到一篇【中秋】纯CSS实现日地月的公转,决定就是它了。
实现效果: 日地月公转 (codepen.io)
布局方面非常简单,使用三个div
分别表示日,地,月,另外再加div.contian
进行包裹
html<div class="contian">
<div class="sun"></div>
<div class="earth">
<div class="moon"></div>
</div>
</div>
body
天生自带margin:8px;
影响布局,去除即可
html,body
均为块级元素,独占一行,但高度不会占满窗口高度。我们需要让其撑满整个窗口,设置它们的高度为height:100vh;
csshtml,
body {
margin: 0;
padding: 0;
background-color: #2f3141;
height: 100vh;
}
我们需要将所有内容都相对浏览器窗口居中展示,居中方式有:flex,grid
布局,定位以及设置margin
等。
这里绘图说明下如何margin
居中:
给内容具体的宽高并设置margin-left:aute;margin-right:aute;
另外通过calc((100vh - 内容高度) / 2)
得到margin-top
的值。
当然使用margin
居中麻烦,这里我只提供一个思路。
日地月居中,我选择使用定位完成
body
是占满窗口的,我们以body
进行绝对定位。定位前需要给body
设置相对定位属性position: relative;
然后给div.contian
添加绝对定位属性position: absolute;
csshtml,
body {
margin: 0;
padding: 0;
background-color: #2f3141;
position: relative;
height: 100vh;
}
.contian {
position: absolute;
left: 50%;
top: 50%;
width: 500px;
height: 500px;
border: 1px solid #ccc;
transform: translate(-50%, -50%);
}
绝对定位时,top,left
值是以div.contian
左上角为准,所以当left:50%;right:50%
div.contian
并没有达到居中的效果,left,right
值页面需要减div.contian
自身宽高的值。
为了达到效果,我使用了 transform: translate(-50%, -50%);
让其以自身的宽高为准向X轴,Y轴,各移动-50%
。
设置transform
可以理解为创建了一个三维坐标如下图,不同的是Z轴是正对屏幕,面对屏幕前的您。这里对transform
不做过多文字描述
为了更直观的看到效果,我给div.contian
加了一个border
边框
同理,使div.sun
相对div.contian
绝对定位居中。设置border-radius:50%
绘制成圆形,backgroud
使用线性渐变 linear-gradient
填充;为了效果更佳,给div.sun
一定的外阴影
给div.sun
元素设置宽高,给外阴影 box-shadow: 0 0 8px 8px rgba(242, 120, 75, 0.2);
css.sun {
position: absolute;
border-radius: 50%;
height: 200px;
width: 200px;
left: 50%;
top: 50%;
background: linear-gradient(#fcd670, #f2784b);
transform: translate(-50%, -50%);
box-shadow: 0 0 8px 8px rgba(242, 120, 75, 0.2);
}
太阳效果如图:
地球会绕太阳进行运动,运动的轨道是一个圆形的,我们可以给div.earth
宽高设置与最外层div.contian
一致
为直观我也给div.earth
添加了一个border
属性
css.earth {
width: 500px;
height: 500px;
border-radius: 50%;
border:1px solid #f2784b;
}
这个圆边框将用于地球公转运动轨道
::before
实现行星行星都用一个圆进行模拟,同理使用 border-radius: 50%;
给背景渐变色。将地球定位至地球公转轨道正上文 也就是div.earth
的正上方
css.earth {
//...
position: relative;
}
.earth::before {
content: "";
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
width: 60px;
height: 60px;
background: linear-gradient(#19b5fe, #7befb2);
border-radius: 50%;
}
地球效果如图:
::after
实现行星尾巴行星尾巴使用border
模拟,设置::after
伪元素width:100%;heigth:100%;
,占满div.earth
给::after
伪元素border-top:px solid silver;border-left:22px solid transparent;
将div.earth
的border
去除,这个时候我们可以清楚的看到行星尾巴已经出来了
但行星尾巴并没有与地球交接在一起,这里可以通过设置transform
中的rotateZ
,让其绕Z轴逆时针旋转一定角度
此时,地球完成了,只差让其绕太阳旋转
给div.earth
元素添加animation
属性,定义动画关键帧keyframes
,让div.earth
一直Z轴是顺时针旋转
css.earth {
width: 500px;
height: 500px;
border-radius: 50%;
position: relative;
animation: rotate 20s linear infinite;
}
@keyframes rotate {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(360deg);
}
}
.earth::before {
content: "";
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
width: 60px;
height: 60px;
background: linear-gradient(#19b5fe, #7befb2);
border-radius: 50%;
}
.earth::after {
position: absolute;
content: "";
width: 100%;
height: 100%;
border-top: 2px solid silver;
border-right: 2px solid transparent;
border-radius: 50%;
transform: rotateZ(-52deg);
}
添加动画属性后效果:
html<div class="earth">
<div class="moon"></div>
</div>
html布局上,div.moon
被div.earth
包裹,所以我们依然通过定位,将div.moon
固定至地球公转轨道正上文 也就是div.earth
的正上方
月亮公转轨道圆应大于地球
css.moon {
position: absolute;
left: 50%;
top: 0;
width: 100px;
height: 100px;
border-radius: 50%;
border: 1px solid #19b5fe;
transform: translate(-50%, -50%);
}
为直观我给div.moon
添加了border
留下的就是使用div.moon
的伪元素模拟出月亮与月亮旋转的尾巴,思路与模拟实现地球相同
到此,文章不再添加文字描述思路
最后将不必要的border
删除,一个有手就会的日地月公转就完成了
完整代码不贴出来了,想要源码移步日地月公转 (codepen.io)
当然,还可以扩展实现3D效果的公转自转,有兴趣的小家伙可以实现下 实现行星公转自转 (codepen.io)
文章使用定位,transform
,animation
等css3属性,从0到1实现了日地月公转
本文作者:凌览
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!