繁星似锦实现原理解析
本帖最后由 马黑黑 于 2022-1-21 19:51 编辑首先要有天空,我们先定义一下天空的样式,它是黑的,但不能黑的太彻底以免过于压抑,所以给它个略微透明的背景:
#sky {
margin: 10px auto;
width: 720px;
height: 460px;
background-color: rgba(0,0,0,0.85);
position: relative; /*定位总是需要的 */
}
我们用 <span> 标签来布置星星。span是行内标签,display 最好定义,block 和 inline-block 都可以:
#sky span {
position: absolute;
display: inline-block;
width: 3px;
height: 3px;
background: white;
opacity: 0.6; /* 透明度是让它们模糊 */
transform: rotate(45deg); /* 转一下像个菱形模拟星星 */
animation: splash var(--d) infinite;
/* 上一句调用动画,其中:
var(--d) 是CSS声明的变量:运动时长
*/
}
下面是动画,其实可以设置为更复杂一点:
@keyframes splash {
0%, 100% { opacity: 0.2; }
50% { opacity: 0.8; transform:scale(1.5) rotate(-45deg); }
}
月亮要有一个吧,让它是月牙的:
.moon {
position: absolute; /* 定位 */
width: 100px;
height: 100px;
border-radius: 50%;
box-shadow: 20px 20px 0 0 silver; /* 银色的月牙 */
z-index: 100; /* 星星只能在它背后 */
left: 70%;
}
以上,CSS样式写好了。我们要画几百甚至几千个星星,用CSS画要画到猴年马月!但我们要先懂得如果用CSS画,怎么画:
#sky span:nth-child(1){ left:25%; top:10%; --d: 3s; }
#sky span:nth-child(2){ left:30%; top:15%; --d: 2s; }
#sky span:nth-child(3){ left:40%; top:17%; --d: 5s; }
…………
#sky span:nth-child(600){ left:40%; top:17%; --k: 1s; }
这上面,定义每一个 span 标签基于定位和动画变量的样式,谁给我写600个看看!
JS好哥们这时候说:我来!
JS哥哥是这样写标签的:
str = '<span style="left:25%; top:10%; --d: 3s;"></span>';
document.getElementById('sky').innerHTML += str;
我看看。嗯,JS哥定义了一个 str 变量,用来装载 span 标签,然后通过读取 id 为 sky 的标签重新给它赋值,就是说 sky 标签里面的HTML代码重新写, += 的意思是在原本基础上加 str 变量的值。
可以,咦,囧哥,哦不,JS哥,你这不是只画了一个吗?我要600个星星!
JS个说:别急,看我的——
for (i=0; i<600; i++) {
str += '<span style="left:25%; top:10%; --d: 3s;"></span>';
}
document.getElementById('sky').innerHTML += str;
哦~~~,JS哥用一个 for 语句画了600个 span 标签。太厉害了,JS哥哥!
可是,咦,JS哥,你画的 span 标签是叠加在一起的耶,我要他随机分布在天空中!
JS个这才想起来要随机给星星定位、定闪烁时长,于是它忍住不笑,继续努力:
var str = "";
for (i=0; i<600; i++) {
str += '<span style="left: ' + Math.ceil(Math.random()*100) + '%; top: ' + Math.ceil(Math.random()*100) + '%; --d:' + Math.ceil(Math.random()*10+0.5) + 's;"></span>';
}
document.getElementById('sky').innerHTML += str;
这回,JS哥哥用了数学方法,给星星 xy坐标、运动时长分派随机数值,其中,高宽在0%-100%之间随机分配,运动时长在0.5-10.5秒之间随机分配。
下面是HTML代码,它应该放在 CSS 和 JS 之间:
<div id="sky">
<div class="moon"></div>
</div>
就酱。演示效果(多加了音乐):【新提醒】繁星似锦 - 动画音画 - 花潮论坛 - Powered by Discuz! (huachaowang.com)
原帖完整代码:
<style>
#sky {
margin: 10px auto;
width: 720px;
height: 460px;
background-color: rgba(0,0,0,0.85);
position: relative;
}
#sky:hover .wyyfram { display:block; }
.moon {
position: absolute;
width: 100px;
height: 100px;
border-radius: 50%;
box-shadow: 20px 20px 0 0 silver;
z-index: 100;
left: 70%;
}
.wyyfram { position: relative; top: 400px; display: none; opacity: 0.5; }
#sky span {
position: absolute;
display: inline-block;
width: 3px;
height: 3px;
background: white;
opacity: 0.6;
transform: rotate(45deg);
animation: splash var(--d) infinite;
}
@keyframes splash {
0%, 100% { opacity: 0.2; }
50% { opacity: 0.8; transform:scale(1.5) rotate(-45deg); }
}
</style>
<div id="sky">
<div class="moon"></div>
<iframe class="wyyfram" frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86 src="https://music.163.com/outchain/player?type=2&id=410042763&auto=1&height=66"></iframe>
</div>
<script>
var str = "";
for (i=0; i<600; i++) {
str += '<span style="left: ' + Math.ceil(Math.random()*100) + '%; top: ' + Math.ceil(Math.random()*100) + '%; --d:' + Math.ceil(Math.random()*10+0.5) + 's;"></span>';
}
document.getElementById('sky').innerHTML += str;
</script>
黑黑很强大,直接语句制作特效{:4_178:} 这个比较复杂,好多没接触过的,需要好好看看了。 小辣椒 发表于 2022-1-21 21:11
黑黑很强大,直接语句制作特效
这个是很基本的 红影 发表于 2022-1-21 21:16
这个比较复杂,好多没接触过的,需要好好看看了。
CSS部分不复杂,先弄懂这个部分。
JS也就是用了一个 for 语句,常规语言必要的,然后就是它来写 HTML 代码带 style 语句,也算简单,关键是CSS的原理。 马黑黑 发表于 2022-1-21 21:22
CSS部分不复杂,先弄懂这个部分。
JS也就是用了一个 for 语句,常规语言必要的,然后就是它来写 HTML...
那就先说css,月亮就没看懂,看着像做个圆呀,咋加个阴影就成月牙了呢{:4_173:} 红影 发表于 2022-1-21 22:10
那就先说css,月亮就没看懂,看着像做个圆呀,咋加个阴影就成月牙了呢
月亮大概就是这组代码产生的效果:
.moon {
position: absolute;
width: 100px;
height: 100px;
border-radius: 50%;
box-shadow: 20px 20px 0 0 silver;
z-index: 100;
left: 70%;
}
定位、高宽、圆角都看懂,关键是红色那句,利用元素的盒子阴影巧妙设置,就是它和边框圆形设置以及继承来的背景色共同产生了月牙效果(下楼给出一个独立的效果,一看就能明白)。倒数第二句是为了保证星星不浮于它之上,数字越大它就越不容易被其他元素覆盖(除非有另外的元素设置了比它更大的值并与他有重叠部分)。
<style>
.月牙 {
position: absolute;
width: 100px;
height: 100px;
border-radius: 50%;
box-shadow: 20px 20px 0 0 silver;
z-index: 100;
left: 50%;
background:red;
}
</style>
<div class="月牙"></div>
看9楼,如果红色部分设置为透明或和父容器的背景色一样的颜色,我们就只能看到阴影的部分,那一部分就是月牙。是不是很巧妙?
@红影 <div class="月牙" style="background: transparent;"></div>
11楼,代码如下:
<div class="月牙" style="background: transparent;"></div>
这里,已将 div 的背景色设置为透明 马黑黑 发表于 2022-1-21 23:35
月亮大概就是这组代码产生的效果:
.moon {
位置那句看懂了,没懂的事月牙效果。看楼下明白了,原来是巧用颜色弄成的,前面没明白画圆的命令怎么弄出来的月牙,现在懂了。若不是背景色将圆的那部分变成“不见”,将是楼下那种效果。
这法子真巧妙{:4_199:} 马黑黑 发表于 2022-1-21 23:40
11楼,代码如下:
哈,这个是另一个思路了,原来有这么多方法可以做出月牙来{:4_187:} 马黑黑 发表于 2022-1-21 23:38
看9楼,如果红色部分设置为透明或和父容器的背景色一样的颜色,我们就只能看到阴影的部分,那一部分就是月 ...
嗯嗯,设置透明或者设置成跟父容器一样颜色,都会出现月牙。{:5_116:} 红影 发表于 2022-1-22 15:11
嗯嗯,设置透明或者设置成跟父容器一样颜色,都会出现月牙。
先领会,后动手,然后自己改变月牙的大小,甚至上弦月和下弦月都能做 红影 发表于 2022-1-22 15:10
哈,这个是另一个思路了,原来有这么多方法可以做出月牙来
想象力加充分利用自己掌握的知识和能力,能做很多事情 红影 发表于 2022-1-22 15:08
位置那句看懂了,没懂的事月牙效果。看楼下明白了,原来是巧用颜色弄成的,前面没明白画圆的命令怎么弄出 ...
弄懂了你也能做,然后举一反三,做更多的事情 马黑黑 发表于 2022-1-22 15:16
弄懂了你也能做,然后举一反三,做更多的事情
我不行,常规的都做不出来,这么巧妙的更做不出新的了,跟着做原样的还磕磕绊绊呢{:4_173:} 马黑黑 发表于 2022-1-22 15:15
想象力加充分利用自己掌握的知识和能力,能做很多事情
我现在还没掌握呢,等学会了才有可能呢。