马黑黑 发表于 2023-7-13 13:06

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 值 */

楼下是一个示例:小球默认在父元素的左上角,点击它,它会随机移动到另一个地方。

马黑黑 发表于 2023-7-13 13:06

<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>

马黑黑 发表于 2023-7-13 13:08

二楼效果的代码
<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>

马黑黑 发表于 2023-7-13 13:09

一个思考题:

小球从 a 点 移动到 b 点,如果距离较长,会明显看出小球的行进路线是弧线。为什么?

樵歌 发表于 2023-7-13 13:55

又进行理论创新了,黑科技之。{:4_173:}

南无月 发表于 2023-7-13 14:47

马黑黑 发表于 2023-7-13 13:09
一个思考题:

小球从 a 点 移动到 b 点,如果距离较长,会明显看出小球的行进路线是弧线。为什么?

transition: left 1.5s, top 1s;
这里不同方向设了不同速度,一边快一边慢,就走不直了。。如果设相同的速度,就猫步很直了{:4_173:}

南无月 发表于 2023-7-13 14:53

let setPos = (pa,son) => {
    let x = Math.random() * (pa.offsetWidth - son.offsetWidth),
      y = Math.random() * (pa.offsetHeight - son.offsetHeight);
随机系数小于1,保证出不了父元素的框框。。
随机系数极小的可能等于1,意味着小球只有极小的可能碰到边缘。
随机系数更更小的可能同时取到1,意味着小球永远不可能到右下角。。。
小球运动范围完美框起来。。
这个随机浮点数超级厉害。。

红影 发表于 2023-7-13 16:08

使用Math.random()好,这个值在0-1之间的浮点数,乘以宽和高,所以永远不可能超出边框了。可以省却之前的判断语句了{:4_199:}

红影 发表于 2023-7-13 16:08

马黑黑 发表于 2023-7-13 13:09
一个思考题:

小球从 a 点 移动到 b 点,如果距离较长,会明显看出小球的行进路线是弧线。为什么?

不知道啊,是因为有 - son.offsetWidth这个数据在的缘故么?

马黑黑 发表于 2023-7-13 20:30

红影 发表于 2023-7-13 16:08
使用Math.random()好,这个值在0-1之间的浮点数,乘以宽和高,所以永远不可能超出边框了。可以省却之前的判 ...

算法要细看了

马黑黑 发表于 2023-7-13 20:31

樵歌 发表于 2023-7-13 13:55
又进行理论创新了,黑科技之。

{:4_190:}

马黑黑 发表于 2023-7-13 20:31

红影 发表于 2023-7-13 16:08
不知道啊,是因为有 - son.offsetWidth这个数据在的缘故么?

不是

马黑黑 发表于 2023-7-13 20:31

南无月 发表于 2023-7-13 14:47
transition: left 1.5s, top 1s;
这里不同方向设了不同速度,一边快一边慢,就走不直了。。如果设相同的 ...

正解{:4_190:}

马黑黑 发表于 2023-7-13 20:33

南无月 发表于 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:49

红影 发表于 2023-7-13 21:20

马黑黑 发表于 2023-7-13 20:30
算法要细看了

这个算法特别好。{:4_187:}

红影 发表于 2023-7-13 21:21

马黑黑 发表于 2023-7-13 20:31
不是

嗯嗯,看到月儿的标准答案了。

马黑黑 发表于 2023-7-13 22:03

红影 发表于 2023-7-13 21:21
嗯嗯,看到月儿的标准答案了。

{:4_190:}

马黑黑 发表于 2023-7-13 22:04

红影 发表于 2023-7-13 21:20
这个算法特别好。

算法这里是单一的,要学会灵活使用

红影 发表于 2023-7-13 22:05

马黑黑 发表于 2023-7-13 22:04
算法这里是单一的,要学会灵活使用

是的,这个非常有用。
页: [1] 2 3
查看完整版本: Math.random() 应用举例