新的一年,给网站换了一个新的风格!
背景天空会根据时间变换颜色和风格,白天有☁️,晚上有✨和🌠。
在这里有全屏的版本。
一些有趣的技术细节
- 图片完全由程序生成,没有一点二进制文件
- 云是通过绘制3D球体渲染出来的
- 背景的棋盘抖动颜色是看《16bit的感动》学的(虽然动画改的剧情不好看)
- 晚上的星星和流星全是div
- 其他细节请看js源文件
- 最近可以预定天子的FUMO,感兴趣的快去下单吧!
网页内容终于不是在客户端处理的了!
- python脚本换成了node.js在Github上先编译好。
稍微详细一点的实现
背景天空
- 就是一堆div矩形!
- 还有根据剩余类填充颜色的棋盘格纹理(使用了canvas)!
云
当一堆球球层层叠叠堆在一起时,长得就像云了,像这样:

所以在javascript中,我们只要做一个基础的3D渲染,实现
- 通过正态分布随机原点和半径,创建几十个球体
- 指定摄像机方向,计算球体重叠
- 指定光线方向,计算球面的法向与光线的点积
- 根据点积大小使用不同抖色填充:从亮到暗:白色 → 加亮的天空色 → 加深的天空色
就好了。
当然,随机的参数需要试多几次才能找到一个比较好的。
星星
在随机位置一大堆白色方块div,注意位置与网格对齐,然后通过css动画就能一闪一闪啦。
草
这叫蒲苇吗,我不是很清楚,Google识图告诉我它叫蒲苇。不要紧的,画出来长得像什么我们曾经见过的植物就好 :)
这种草可以近似为一根竖的弯曲棒子和很多条长在上面的倾斜向上的弯曲棒子,那么就可以建立模型。
如果我们忽略长在上面的弯曲棒子的自重,那么我们在小学二年级的时候就学过 我物理不好没学过,但是AI告诉我,一根底端垂直细杆受自身重力影响弯曲时的形状是个抛物线
x=y2.
同样也是AI告诉我,末端固定的横向棒子的形状这么个复杂的四次多项式
y(x)=24EIq(x4−4Lx3+6L2x2)+kx.
该式描述了匀质悬臂梁在自重作用下的挠度曲线。其中杆长为 L ,抗弯刚度为 EI ,均布载荷集度 q=ρgA (其中 ρ 为材料密度, g 为重力加速度, A 为横截面积),固定端在 x=0 ,自由端在 x=L 。(我也不知道AI这说的对不对,但是最后画出来感觉挺对的)
那么我们只要使用这几个式子,稍加组合,添加一点随机数决定的参数就能画出来好看的草了。注意倾斜向上的枝干需要使用不同颜色绘多几次才有层次感。
像素二次元小人
先写了一个python脚本把png转为了js矩阵,然后再在canvas根据矩阵信息重新把图画出来。(为什么我要这么多此一举,而且文件体积还变大了)(但是这真的很酷)
变化的颜色
天空有自己的颜色字典,可以在代码中找到,然后插值就能得到全天不一样的颜色了。
场景中的其他颜色有自己光照颜色字典(也可以在代码中看到),插值,与原有颜色相乘,就能获得当前环境下的颜色啦。
更新:天空
之前是这样的

现在是这样的

更新:山与地面
使用分形算法生成山脉轮廓
- 从一条简单折线开始
- 细分过程:
- 计算当前线段的中点
- 将中点高度随机偏移(偏移量随迭代减少)
- 对左右两段重复上述过程
- 重复迭代直到达到所需细节水平
越远的山脉越小,颜色越淡
地面用的颜色和草是一样的,不过通过噪声扰动颜色混合权重,在条带交界处创建尽量自然的不规则过渡
基础颜色混合(线性插值)
Cmix=(1−w)⋅CA+w⋅CB
其中:
- CA 和 CB 是相邻条带的颜色向量
- w 是混合权重系数 (0≤w≤1)
权重扰动
wnoisy=clampwbase+噪声函数N(x,y)⋅Anoise,0,1
其中:
- wbase 是基础权重(线性过渡)
- N(x,y) 是坐标相关的噪声函数
- Anoise 是噪声强度系数
分形噪声函数
N(x,y)=∑k=0n−1pk1k=0∑n−1基础噪声Nsimple(2ksx,2ksy)⋅pk
其中:
- s 是噪声缩放因子
- p 是持久性系数 (0<p<1)
- n 是倍频程数量
- Nsimple 是基础噪声函数
三角函数噪声(随便取的值
Nsimple(x,y)=fract(sin(x⋅12.3737+y⋅78.114514)×424242.4242)
最终颜色计算
Cfinal=⎩⎨⎧CA(1−wnoisy)⋅CA+wnoisy⋅CBCB若 y<ystart若 ystart≤y≤yend若 y>yend