一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情。
我正在参加 码上掘金体验活动,详情:show出你的创意代码块
前言
前面的文章我用css画了五角星⭐️(用css画一个五角星), 以及用box-shadow实现了画月亮🌛(css3的box-shadow属性)
那么今天,结合五角星和月亮,在码上掘金画一幅明月高挂,星星会闪的星空。
效果展示
代码介绍
首先我们实现星空的背景,这里我们用黑色来代替
html,
body {
position: relative;
background-color: black;
height: 100%;
}
然后我们画一个月亮,具体可以在我的这篇文章css3的box-shadow属性可以看到,主要是使用box-shadow实现。
<style>
.moon {
position: relative;
left: 100px;
top: 100px;
width: 200px;
height: 200px;
border-radius: 50%;
box-shadow: 35px 0px 5px yellow inset;
}
</style>
<body>
<div class="moon"></div>
</body>
然后我们接着把星星加上,具体怎么画星星可以通过我这篇文章用css画一个五角星,之前画的是红色的大五角星,我要把星星变小点,然后换成白色的颜色。
.star {
position: absolute;
width: 0px;
height: 0px;
border-color: white transparent transparent transparent;
border-width: 4.49px 6.18px;
border-style: solid;
}
.star::before {
content: '';
display: block;
position: absolute;
left: -6.18px;
top: -4.49px;
border-color: white transparent transparent transparent;
border-width: 4.49px 6.18px;
border-style: solid;
transform: rotate(72deg);
transform-origin: 50% 22.5%;
}
.star::after {
content: '';
display: block;
position: absolute;
left: -6.18px;
top: -4.49px;
border-color: white transparent transparent transparent;
border-width: 4.49px 6.18px;
border-style: solid;
transform: rotate(-72deg);
transform-origin: 50% 22.5%;
}
但是天上的星星是满天的,这里我们可以用js遍历生成100个星星。
这里我使用createDocumentFragment,这个是生成文档碎片节点,它并不存在dom中,所以创建的div append到它里面,并不会引起页面的重新渲染(回流,重绘)。最后才把它append到body中,这样
只需要重绘一次。
const frag = document.createDocumentFragment()
for (let i = 0; i < 100; i++) {
const star = document.createElement('div')
star.classList.add('star')
frag.appendChild(star)
}
body.appendChild(frag)
然后星星的位置应该是随机的,所以我们也动态给他们加上随机位置。
获取body的宽度和高度,利用Math.random()来生成随机位置。
const body = document.querySelector('body')
const bodyWidth = body.clientWidth
const bodyHeight = body.clientHeight
const frag = document.createDocumentFragment()
for (let i = 0; i < 100; i++) {
const star = document.createElement('div')
star.classList.add('star')
star.style.left = `${Math.random() * bodyWidth}px`
star.style.top = `${Math.random() * bodyHeight}px`
frag.appendChild(star)
}
body.appendChild(frag)
注意⚠️:star的position要改成
absolute(绝对定位);
可以看到星空的轮廓已经出来了。
现实中星星是有大有小的,我们这里都是一样大小的星星,可以使用transform: scale和Math.random()来设置随机的大小。
star.style.transform = `scale(${Math.random() * 1.2})`
这个星空目前来看是静态的,要加点动画才行。
因为星星会闪的嘛,下面再把星星会闪的动画加上。
这里我使用的是css3动画animation/keyframes。 用opacity来模拟星星的显示或隐藏。
我之前也有篇文章讲过元素隐藏的几种方式,有兴趣可以看看
.star {
animation: twinkle 2s infinite;
}
@keyframes twinkle {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0;
}
}
但是这样实现的星星都是同时闪烁的,闪烁的时机应该加上随机的效果。我们继续用Math.random()函数,去设置星星动画延迟的随机时间。
在动态生成star元素的时候都加上。
star.style.animationDelay = `${Math.random()}s`
最终的效果是
总结
以上就是实现明月高挂,星星会闪的星空的整体效果。整体还是比较简单的。大家可以动手试试吧~
附上整体的代码:
<!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>star-sky</title>
<style>
html,
body {
position: relative;
background-color: black;
height: 100%;
}
.moon {
position: relative;
left: 100px;
top: 100px;
z-index: 1;
width: 200px;
height: 200px;
border-radius: 50%;
box-shadow: 35px 0px 5px yellow inset;
}
.star {
position: absolute;
width: 0px;
height: 0px;
border-color: white transparent transparent transparent;
border-width: 4.49px 6.18px;
border-style: solid;
animation: twinkle 2s infinite;
}
@keyframes twinkle {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0;
}
}
.star::before {
content: '';
display: block;
position: absolute;
left: -6.18px;
top: -4.49px;
border-color: white transparent transparent transparent;
border-width: 4.49px 6.18px;
border-style: solid;
transform: rotate(72deg);
transform-origin: 50% 22.5%;
}
.star::after {
content: '';
display: block;
position: absolute;
left: -6.18px;
top: -4.49px;
border-color: white transparent transparent transparent;
border-width: 4.49px 6.18px;
border-style: solid;
transform: rotate(-72deg);
transform-origin: 50% 22.5%;
}
</style>
</head>
<body>
<div class="moon"></div>
</body>
<script>
const body = document.querySelector('body')
const bodyWidth = body.clientWidth
const bodyHeight = body.clientHeight
const frag = document.createDocumentFragment()
for (let i = 0; i < 100; i++) {
const star = document.createElement('div')
star.classList.add('star')
star.style.left = `${Math.random() * bodyWidth}px`
star.style.top = `${Math.random() * bodyHeight}px`
star.style.transform = `scale(${Math.random() * 1.2})`
star.style.animationDelay = `${Math.random()}s`
frag.appendChild(star)
}
body.appendChild(frag)
</script>
</html>