<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: #000;
}
/* 天空 */
#the-sky {
position: relative;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background-color: #000;
overflow: hidden;
}
/* 星星 - 容器 */
.star-container {
position: absolute;
/* 可以在 js 中随机生成星星大小,造成远近感 */
/* transform: scale(0.5); */
}
/* 星星 - 横 */
.star-hor {
position: absolute;
width: 30px;
height: 2px;
border-radius: 100%;
background: linear-gradient(
-45deg,
rgba(0, 0, 255, 0),
/* 星星颜色 */
#5f91ff,
rgba(0, 0, 255, 0)
);
transform: scale(0);
animation-name: shining;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
/* 动画时间,拆出来就是为了方便生成随机时间 */
animation-duration: 3.0s;
}
/* 星星 - 竖 */
.star-ver {
position: absolute;
top: -14px;
left: 14px;
width: 2px;
height: 30px;
border-radius: 100%;
background: linear-gradient(
-45deg,
rgba(0, 0, 255, 0),
/* 星星颜色 */
#5f91ff,
rgba(0, 0, 255, 0)
);
transform: scale(0);
animation-name: shining;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
/* 动画时间,拆出来就是为了方便生成随机时间 */
animation-duration: 3.0s;
}
/* 星星发光动画 */
@keyframes shining {
0% {
transform: scale(0);
}
50% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
/* 流星 - 容器 */
.meteor-container {
position: absolute;
}
/* 流星 - 主体 */
.meteor {
position: absolute;
width: 4px;
height: 4px;
border-radius: 50%;
background: #fff;
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.1),
0 0 0 8px rgba(255, 255, 255, 0.1),
0 0 20px rgba(255, 255, 255, 0.1);
/* 重复动画,现在按照每个流星每次不同位置的方式出现,这种重复位置出现的则先注释 */
/* animation-name: streaking;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-duration: 3.0s; */
}
/* 流星 - 尾巴 */
.meteor-tail {
position: absolute;
top: 50%;
width: 200px;
height: 1px;
background: linear-gradient(90deg, #fff, transparent);
transform: translateY(-50%);
}
/* 流星划过天空动画 */
/* @keyframes streaking {
0% {
opacity: 1;
transform: rotate(315deg) translateX(0);
}
70% {
opacity: 1;
}
100% {
opacity: 0;
transform: rotate(315deg) translateX(-1500px);
}
} */
</style>
</head>
<body>
<!-- 天空 -->
<div id="the-sky">
<!-- 星星(由 js 去创建)-->
<!-- 星星有个容器,方便控制每个星星大小,内部装有横竖条组装成十字形状的星星进行闪烁,不使用伪类是为了更好的给每个条添加动画,达到闪烁效果 -->
<!-- <div class="star-container" style="left: 100px; top: 100px;">
<div class="star-hor">
<div class="star-ver"></div>
</div>
</div> -->
<!-- 流星(由 js 去创建 -->
<!-- 流星有个容器,方便控制每个流星大小,内部装有流星与尾巴元素,不使用伪类是为了更好的给每个尾巴自由控制角度、长度、速度 -->
<!-- <div class="meteor-container" style="left: 50%; top: 50%;">
<div class="meteor">
<div class="meteor-tail"></div>
</div>
</div> -->
<!-- 背景音乐,触摸播放,可以删除 -->
<audio
id="music"
src="https://freetyst.nf.migu.cn/public/product9th/product46/2023/12/2514/2023%E5%B9%B412%E6%9C%8822%E6%97%A516%E7%82%B951%E5%88%86%E5%86%85%E5%AE%B9%E5%87%86%E5%85%A5%E5%8D%8E%E5%BC%BA%E8%87%B4%E8%BF%9C1%E9%A6%96115803/%E6%A0%87%E6%B8%85%E9%AB%98%E6%B8%85/MP3_128_16_Stero/63278105706140959.mp3?channelid=02&msisdn=6f8432c3-03ec-4c12-817b-163a1fda6104&Tim=1703570982946&Key=9bf5ce0f48e0c0f1"
loop
autoplay
></audio>
</div>
<script>
// 初始化指定星星数量
function initStars (num) {
// 获取当前天空元素
let thesky = document.getElementById('the-sky')
// 获取天空宽高
let w = thesky.clientWidth
let h = thesky.clientHeight
// 星星列表,方便更新位置
let stars = []
// 星星颜色
let colors = ['#fff', '#5f91ff']
// 循环创建
for (let i = 0; i < num; i++) {
// 星星坐标
let x = createRandomInteger(0, w)
// 顶部的星星不会被挡住,也可以设置为 0 ,但是有些星星会被挡掉半边
let y = createRandomInteger(15, h)
// 延迟闪烁,保证所有星星不是同时执行动画,产生交替闪烁的感觉
let delay = createRandomDecimal(0, 10) // i * 0.1
// 随机闪烁时间
let duration = createRandomDecimal(1.5, 6.0)
// 星星大小
let scale = Math.min(createRandomDecimal(0.1, 0.7), 1.0) // 1
// 星星颜色
let color = colors[createRandomInteger(0, colors.length)]
// 星星容器
const starContainer = document.createElement('div')
starContainer.setAttribute('class', 'star-container')
starContainer.setAttribute('style', `
left: ${x}px;
top: ${y}px;
transform: scale(${scale});
`)
// 星星横条
const starHor = document.createElement('div')
starHor.setAttribute('class', 'star-hor')
starHor.setAttribute('style', `
animation-delay: ${delay}s;
animation-duration: ${duration}s;
background: linear-gradient(
-45deg,
rgba(0, 0, 255, 0),
${color},
rgba(0, 0, 255, 0)
);
`)
// 星星竖条
const starVer = document.createElement('div')
starVer.setAttribute('class', 'star-ver')
starVer.setAttribute('style', `
animation-delay: ${delay}s;
animation-duration: ${duration}s;
background: linear-gradient(
-45deg,
rgba(0, 0, 255, 0),
${color},
rgba(0, 0, 255, 0)
)
`)
// 组装星星
starHor.appendChild(starVer)
starContainer.appendChild(starHor)
// 星星添加到天空
stars.push(starContainer)
thesky.append(starContainer)
}
// 监听窗口变化,更新星星位置
window.addEventListener('resize', () => {
// 获取天空宽高
let w = thesky.clientWidth
let h = thesky.clientHeight
// 循环创建
for (let i = 0; i < stars.length; i++) {
// 星星坐标
let x = createRandomInteger(0, w)
// 顶部的星星不会被挡住,也可以设置为 0 ,但是有些星星会被挡掉半边
let y = createRandomInteger(15, h)
// 修改位置
stars[i].style.top = `${y}px`
stars[i].style.left = `${x}px`
}
})
}
// 随机出现指定区间数量内的流星划过,间隔指定时间再次随机出现
function initMeteors (min, max) {
// 获取当前天空元素
let thesky = document.getElementById('the-sky')
// 流星颜色
let colors = ['#fff', '#5f91ff']
// 随机出现几条流星
let count = createRandomInteger(min, max)
// 开始随机出现
for (let i = 0; i < count; i++) {
// 获取天空宽高
let w = thesky.clientWidth
let h = thesky.clientHeight
// 流星坐标
let x = createRandomInteger(w * 0.1, w)
let y = createRandomInteger(-15, -10)
// 延迟出现时间
let delay = createRandomDecimal(0, 8)
// 划过天空时间
let duration = createRandomDecimal(10.0, 20.0)
// 流星大小
let scale = Math.min(createRandomDecimal(0.5, 1.0), 1.0)
// 流星颜色
let color = colors[createRandomInteger(0, colors.length)]
// 流星容器
const meteorContainer = document.createElement('div')
meteorContainer.setAttribute('class', 'meteor-container')
meteorContainer.setAttribute('style', `
left: ${x}px;
top: ${y}px;
transform: scale(${scale});
`)
// 流星主体
const meteor = document.createElement('div')
meteor.setAttribute('class', 'meteor')
meteor.setAttribute('style', `
background: ${color};
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.1),
0 0 0 8px rgba(255, 255, 255, 0.1),
0 0 20px rgba(255, 255, 255, 0.1);
opacity: 1;
transition: all ${duration}s;
transition-delay: ${delay}s;
transform: rotate(315deg) translateX(0);
`)
// 流星尾巴
const meteorTail = document.createElement('div')
meteorTail.setAttribute('class', 'meteor-tail')
meteorTail.setAttribute('style', `
background: linear-gradient(90deg, ${color}, transparent);
`)
// 组装流星
meteor.appendChild(meteorTail)
meteorContainer.appendChild(meteor)
// 流星添加到天空
thesky.append(meteorContainer)
// 流星动画,动画完成后移除
setTimeout(() => {
meteor.style.opacity = 0
meteor.style.transform = `rotate(315deg) translateX(-${Math.max(w, h)}px)`
// 移除当前流星
setTimeout(() => {
meteor.removeChild(meteorTail)
meteorContainer.removeChild(meteor)
thesky.removeChild(meteorContainer)
}, duration * 1000 + delay * 1000)
}, 0)
}
// 重复出现流星
setTimeout(() => {
initMeteors(min, max)
}, 2000)
}
// 在指定区间生成随机整数
function createRandomInteger (min, max) {
return Math.round(Math.random() * (max - min) + min)
}
// 在指定区间生成随机小数,保留两位小数,float 为浮动值,默认 0
function createRandomDecimal (min, max) {
return (Math.random() * (max - min) + min).toFixed(2)
}
// 调用(如果卡顿可以降低渲染数量)
initStars(1000)
initMeteors(3, 10)
// 触摸开始播放音乐
document.getElementById('the-sky').onclick = () => {
document.getElementById('music').play()
}
</script>
</body>
</html>
源码地址,最新调整会更新到这:DZMStarrySky!