为啥我的粒子会漂移? (又名是 Math.random() 坏了还是我的算法?)
Posted
技术标签:
【中文标题】为啥我的粒子会漂移? (又名是 Math.random() 坏了还是我的算法?)【英文标题】:Why are my particles drifting? ( aka Is Math.random() broken or is it my algorithm? )为什么我的粒子会漂移? (又名是 Math.random() 坏了还是我的算法?) 【发布时间】:2011-04-21 13:37:44 【问题描述】:我使用 javascript 粗略地模拟了粒子的布朗运动,但由于某种原因,我不明白我的粒子正在向上和向左漂移。
算法非常简单。每个粒子都是一个div
,我只需在每轮div
的top
和left
位置中添加或减去一个随机数。
我稍微阅读了Math.random()
,并尝试使用一个函数返回从min
到max
的随机数:
// Returns a random integer between min and max
// Using Math.round() will give you a non-uniform distribution!
function ran(min, max)
return Math.floor(Math.random() * (max - min + 1)) + min;
这是粒子运动的函数:
var x, y, $elie, pos, nowX, nowY, i, $that;
function moveIt()
$("div.spec").each(function(i, v)
x = ran(-5, 5);
y = ran(-5, 5);
$elie = $(v);
pos = $elie.position();
nowX = pos.left;
nowY = pos.top;
// The min and abs are to keep the particles within a box
// The drift occurs even if I remove min and abs
$elie.css("left", Math.min(Math.abs(nowX + x), 515));
$elie.css("top", Math.min(Math.abs(nowY + y), 515));
);
下面是粒子最初是如何设置的,setInterval
开始了。
$(function()
$("body").append("<div/>").attr("id","box");
$elie = $("<div/>").attr("class","spec");
// Note that math random is inclussive for 0 and exclussive for Max
for (i = 0; i < 25; ++i)
$that = $elie.clone();
$that.css("top", ran(0, 495));
$that.css("left", ran(0, 495));
$("#box").append($that);
timer = setInterval(moveIt, 60);
$("input").toggle(function()
clearInterval(timer);
this.value = " Start ";
, function()
timer = setInterval(moveIt, 60);
this.value = " Stop ";
);
);
我的问题是使用上面的min
和max
(-5, 5
),所有粒子都非常快速地向上和向左漂移。
jsFiddle example of drift (-5, 5)
Example of drift even with the removal of .min()
and .abs()
.
为了解决这个问题,我必须使用 min
和 max
的 -1, 5
。
jsFiddle example of no drift (-1, 5)
这是div
的CSS所有粒子都包含在:
#box
width:500px;
height:500px;
border:2px #000 solid;
position: relative;
这是每个粒子的默认 CSS:
div.spec
width:5px;
height:5px;
background-color:#00DDAA;
position:absolute;
发生了什么事?为什么-5
和5
的最小值和最大值会导致向上和向左漂移?
随机函数ran()
的测试似乎没有显示出如此持久的负漂移。
jsFiddle example of testing ran()
ran()
函数取自 the MDC Math.random() page。
【问题讨论】:
【参考方案1】:你的错误是使用
pos = $elie.position();
而不是
pos = $elie.offset();
如果将它们添加到父 div,这不会有什么不同,但是您的元素没有正确添加到父 div,它们被直接附加到文档正文中。所以你的另一个错误是:
$("body").append("<div/>").attr("id","box");
如果您希望 div 的 id 为“box”,则该行应为:
$box = $("<div/>").attr("id","box");
$("body").append($box)
否则你实际上是在给“body”一个“box”的id
编辑:
追加 div 的最有效方法如下(如 this post 所述):
$(document.createElement('div')).appendTo('body').attr('id', 'box')
【讨论】:
感谢 Herman,向 DOM 添加元素的各种方式的速度测试来自 [this answer](***.com/questions/327047/…)。 --------------- PS:我正在编辑我的评论,不小心删除了那段代码,然后编辑评论的时间到期了。 这是这个的最终版本(在 IE 中不太好)-fiddle.jshell.net/PppZ3/show/light-我认为这需要另一种解决方案...研究 [Raphael] (raphaeljs.com)【参考方案2】:不要使用.position()
,而是尝试.offset()
。看起来像it works。
Position.
Offset。
之所以如此,是因为您在 CSS 中设置了绝对的 'left
' 和 'top
' 值。相反,你可以使用这个Example:
$elie.css("margin-left", nowX + x);
$elie.css("margin-top", nowY + y);
【讨论】:
.offset()
似乎确实解决了这个问题。我的粒子包含在父 div
中,所以我认为 .position()
也可以。为什么它不起作用?
这是因为您的 css 设置器设置了一个绝对的“左”和“上”,而不是相对于父级的一个。相反,使用'margin-left'。查看我的编辑。
实际上,父级div
有一个relative
位置,粒子在父级内有一个absolute
位置。这个问题似乎是父母的id
的问题。
啊,有趣。听起来解决根本问题是最好的方法。以上是关于为啥我的粒子会漂移? (又名是 Math.random() 坏了还是我的算法?)的主要内容,如果未能解决你的问题,请参考以下文章