Math.random() 应用举例
我们多次谈及,Math.random() 能产生 0-1 的随机浮点数,得 0 的概率极低,永远不会得整数 1。利用 Math.random(),我们能做的事情很多。举个栗子:让子元素随机出现在父元素之内。
完成上面命题,需要理解几个其他几个相关知识和算法:
其一,获取元素的宽与高。可以使用 元素.offsetWidth 和 元素.offsetHeight ,这是 JS 获取元素宽、高的方法之一,得到的是元素最终定型的宽、高尺寸,纯数值不带单位;
其二,元素的 position 配套设置。父元素设为 relative(相对定位),子元素设为 absolute(绝对定位),这样,子元素以父元素的坐标系为参照,受到父元素坐标系的约束;
其三,使用 left 和 top 定位子元素。left: 0; 表示子元素的左边缘与父元素的左边缘线相贴合,top: 0; 表示子元素的上边缘与父元素的上边缘相贴合,两个值都为 0 则子元素就在父元素的左上角(缺省默认);
其三,算法。当子元素的 left 值大于等于父元素的宽度、top 值大于等于父元素的高度,子元素已经不在父元素的范围里,所以,我们要考虑的一个问题是计算随机取值范围,子元素的 left 值不能大于 父元素宽度-子元素宽度,top 值不能大于 父元素高度-子元素高度。
OK,现在我们来编写一个函数,用来计算子元素的随机定位值,即 left 和 top 两个值。
let setPos = (pa,son) => {
let x = Math.random() * (pa.offsetWidth - son.offsetWidth),
y = Math.random() * (pa.offsetHeight - son.offsetHeight);
return {x,y};
};
setPos 函数需要两个参数,参数一是 pa,父元素标识,参数二是 son,子元素标识。函数中,定义了 x 和 y 变量,分别算出对应子元素的 left 和 top 随机纯数值。x 的赋值计算,用 随机数×(父元素宽度-子元素宽度),y 的赋值计算,用 随机数×(父元素高度-子元素高度),然后以对象方式返回{x,y}值。
下来就是调用函数。假设我们有一个父元素 id="mydiv",子元素 id="ball",则随机设置 ball 的 left 和 top 位置,按如下方法获得:
let pos = setPos(mydiv,ball); /* 声明一个变量用于装载函数 setPos 的返回值 */
ball.style.left= pos.x + 'px'; /* 通过 style 设置 ball 的 left 值 */
ball.style.top= pos.y + 'px'; /* 通过 style 设置 ball 的 top 值 */
楼下是一个示例:小球默认在父元素的左上角,点击它,它会随机移动到另一个地方。
<style>
#mydiv {
margin: 20px auto;
width: 500px;
height: 260px;
border: 1px solid gray;
position: relative;
}
#ball {
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
border-radius: 50%;
background: purple;
transition: left 1.5s, top 1s;
cursor: pointer;
}
</style>
<div id="mydiv">
<div id="ball"></div>
</div>
<script>
let setPos = (pa,son) => {
let x = Math.random() * (pa.offsetWidth - son.offsetWidth),
y = Math.random() * (pa.offsetHeight - son.offsetHeight);
return {x, y};
};
ball.onclick = () => {
let pos = setPos(mydiv,ball);
ball.style.cssText += `
left: ${pos.x}px;
top: ${pos.y}px;
`;
}
</script>
二楼效果的代码
<style>
#mydiv {
margin: 20px auto;
width: 500px;
height: 260px;
border: 1px solid gray;
position: relative;
}
#ball {
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
border-radius: 50%;
background: purple;
transition: left 1.5s, top 1s;
cursor: pointer;
}
</style>
<div id="mydiv">
<div id="ball"></div>
</div>
<script>
let setPos = (pa,son) => {
let x = Math.random() * (pa.offsetWidth - son.offsetWidth),
y = Math.random() * (pa.offsetHeight - son.offsetHeight);
return {x, y};
};
ball.onclick = () => {
let pos = setPos(mydiv,ball);
ball.style.cssText += `
left: ${pos.x}px;
top: ${pos.y}px;
`;
}
</script>
一个思考题:
小球从 a 点 移动到 b 点,如果距离较长,会明显看出小球的行进路线是弧线。为什么? 又进行理论创新了,黑科技之。{:4_173:} 马黑黑 发表于 2023-7-13 13:09
一个思考题:
小球从 a 点 移动到 b 点,如果距离较长,会明显看出小球的行进路线是弧线。为什么?
transition: left 1.5s, top 1s;
这里不同方向设了不同速度,一边快一边慢,就走不直了。。如果设相同的速度,就猫步很直了{:4_173:} let setPos = (pa,son) => {
let x = Math.random() * (pa.offsetWidth - son.offsetWidth),
y = Math.random() * (pa.offsetHeight - son.offsetHeight);
随机系数小于1,保证出不了父元素的框框。。
随机系数极小的可能等于1,意味着小球只有极小的可能碰到边缘。
随机系数更更小的可能同时取到1,意味着小球永远不可能到右下角。。。
小球运动范围完美框起来。。
这个随机浮点数超级厉害。。 使用Math.random()好,这个值在0-1之间的浮点数,乘以宽和高,所以永远不可能超出边框了。可以省却之前的判断语句了{:4_199:} 马黑黑 发表于 2023-7-13 13:09
一个思考题:
小球从 a 点 移动到 b 点,如果距离较长,会明显看出小球的行进路线是弧线。为什么?
不知道啊,是因为有 - son.offsetWidth这个数据在的缘故么? 红影 发表于 2023-7-13 16:08
使用Math.random()好,这个值在0-1之间的浮点数,乘以宽和高,所以永远不可能超出边框了。可以省却之前的判 ...
算法要细看了 樵歌 发表于 2023-7-13 13:55
又进行理论创新了,黑科技之。
{:4_190:} 红影 发表于 2023-7-13 16:08
不知道啊,是因为有 - son.offsetWidth这个数据在的缘故么?
不是 南无月 发表于 2023-7-13 14:47
transition: left 1.5s, top 1s;
这里不同方向设了不同速度,一边快一边慢,就走不直了。。如果设相同的 ...
正解{:4_190:} 南无月 发表于 2023-7-13 14:53
let setPos = (pa,son) => {
let x = Math.random() * (pa.offsetWidth - son.offsetWidth),
...
Math.random() 得到的值 介于 0 - 0.999.... 之间,记住,永远不会得 1 马黑黑 发表于 2023-7-13 20:30
算法要细看了
这个算法特别好。{:4_187:} 马黑黑 发表于 2023-7-13 20:31
不是
嗯嗯,看到月儿的标准答案了。 红影 发表于 2023-7-13 21:21
嗯嗯,看到月儿的标准答案了。
{:4_190:} 红影 发表于 2023-7-13 21:20
这个算法特别好。
算法这里是单一的,要学会灵活使用 马黑黑 发表于 2023-7-13 22:04
算法这里是单一的,要学会灵活使用
是的,这个非常有用。