今天看《CSS揭秘》,学到了一个有趣的知识点:怎么实现伪随机?
觉得既有趣,又有启发,这里记录分享一下。
问你个问题,什么叫随机呢?
我们可以从相反的角度来思考,先回答什么叫不随机。
不随机就是有一定规律可循,比如下图中的颜色出现就是有规律的:
从图上可以看出红绿蓝这三种颜色,每隔六次就整体重复一遍。
上图是我使用 CSS 实现并截图的。这里仔细看一下源码:
div:nth-child(n){
background: red;
}
div:nth-child(2n+1){
background: green;
}
div:nth-child(3n+2){
background: blue;
}
因为 1、2、3的最小公倍数是 6,所以颜色分布规律的周期是 6。
这里要强调的我们说的颜色整体分布规律,是不考虑 CSS 层叠机制带来的影响。
比如如下的代码:
div:nth-child(2n){
background: red;
}
div:nth-child(n){
background: green;
}
div:nth-child(3n+1){
background: blue;
}
产生如下的颜色分布:
但我们仍然可以说它的周期是 6,哪怕这里很特殊,其最小周期是 3。
原理
如何让颜色分布不太有规律呢?
不太有规律,就是随机的概念。
也就是说,你看着图像,却一时半会找不到有啥规律。
如果只限定这三种颜色(这个前提很重要),一个可行办法是让最小公倍数大一些,比如说 35。
因为我们目前的 div 总共才 24 个。而整体重复周期为 35 的话,那么这 24 个颜色其效果必然就很像随机了。当然也只是“像”而已,所以是伪随机。
35 的因子是 5、7。其中 5 和 7 都是素数。
素数是很好的选择,因为是素数的整数倍,比如 5n 和 7n 在 35 之内基本没有冲突的。
同时 5n+a 与 7n+b 发生冲突的次数也会尽可能的少。进而如果 a 与 b 也都是素数的话,冲突会更少。比如 5n+3 与 7n+5 只有在 33 处冲突。
比如这种颜色分布:
其代码是:
div:nth-child(n){
background: red;
}
div:nth-child(5n+1){
background: green;
}
div:nth-child(7n+4)
{
background: blue;
}
当然,上述效果中,默认颜色红色太多。主要原因是每种颜色的周期内,我们只应用了一次。这里可以相应增加频次:
div:nth-child(n){
background: red;
}
div:nth-child(5n+1),
div:nth-child(5n+4){
background: green;
}
div:nth-child(7n+4),
div:nth-child(7n+6)
{
background: blue;
}
产生的效果如下:
以上效果是限定在 3 种颜色之内的随机方案。
如果允许增加其他的颜色的话,这里我们可以增加其他素数因子即可。
应用
这种伪随机还有其他应用吗?
《CSS揭秘》中有两个例子。
1.伪随机背景
css 中可以使用线性渐变实现条纹,比如:
background: repeating-linear-gradient(90deg,
red, red 15px,
green 0, green 30px,
blue 0, blue 45px);
效果是:
也可以使用多重背景来实现:background:
linear-gradient(90deg, red 15px, transparent 0),
linear-gradient(90deg, green 30px, transparent 0),
linear-gradient(90deg, blue 45px, transparent 0);
background-size: 45px 100%;
接下来我们让颜色出现随机些,设置背景大小为素数版的:
background-size: 41px 100%, 61px 100%, 83px 100%;
效果如下,其中默认背景颜色是白色。
同时也可进一步设置颜色宽度:
background:
linear-gradient(90deg, red 11px, transparent 0),
linear-gradient(90deg, green 23px, transparent 0),
linear-gradient(90deg, blue 41px, transparent 0);
background-size: 41px 100%, 61px 100%, 83px 100%;
具体请看其在线例子。
2 动画组合
我们知道动画属性 animation 与 background 属性一样,也支持多套值。
而在同一个元素上应用多套动画,我们也可让其整体周期更大些,进而每一帧的状态都是随机的组合。
比如:
animation: 1s spin, .7s radius, 1.1s color, 1.3s width;
具体请看其在线例子。
蝉原则
通过素数增加随机性的这种方法,书中管它叫蝉原则。
百度了一下,张鑫旭老师也介绍了:《“蝉原则”与CSS3随机多背景随机圆角等效果》。
大体说来,之所以叫“蝉”原则,是因为人家蝉的生命周期(主要还是爆发周期)是那种 13 或 17年的。周期又大,又是素数。这样就能与其天敌的周期尽可能相避开(周期是一年的话,就没法避开了?)。
最后列一下其他有用的资料。