【问题标题】:Insert randomly but never next to each other随机插入,但从不相邻
【发布时间】:2014-07-21 22:38:33
【问题描述】:

基于Insert a div in a random location in a list of divs -- 我正在尝试将一些猫照片随机插入到非猫照片的 div 中:

http://jsfiddle.net/frank_o/QXdL3/21/

但是有没有办法防止猫按顺序出现在彼此旁边?它们应该分散开来。

JS:

var insertionTemplate = $('.template').find('.image').html(),
    insertionTargetChildren = $('.main').find('.image'),
    insertionFrequency = 3;

var random;
for (var i = 0; i < insertionFrequency; i++) {
    random = Math.floor(Math.random() * insertionTargetChildren.length) + 0;
    insertionTargetChildren.eq(random).append(insertionTemplate);
}

HTML:

<div class="template" style="display: none;">
    <div class="image">
        <img src="http://placekitten.com/75/150" />
    </div>
</div>
<div class="main">
    <div class="image">
        <img src="http://lorempixel.com/75/150" />
    </div>

    <!-- ... -->

</div>

【问题讨论】:

  • 按顺序彼此相邻出现,还是在边距/填充/间距方面彼此相邻?
  • @j08691 感谢您指出这一点!依次。更新的问题。
  • 看起来你在demo中使用了一些插件,不要忘记在你的问题中提到它,如果它有一些对应的标签,也要标记它。
  • 您知道您并没有真正插入模板,而只是将图像与另一个随机图像粘贴在一起?
  • @KingKing 该插件无关紧要,但我已将其从演示中删除。

标签: javascript jquery html random


【解决方案1】:

在您的循环中,您可以检查生成的数字是否等于生成的最后一个数字 +-1

演示http://jsfiddle.net/QXdL3/22/

for (var i = 0; i < insertionFrequency; i++) {
    random = Math.floor(Math.random() * insertionTargetChildren.length) + 0;

    if (random != excludeNumA && random != excludeNumB) {
       insertionTargetChildren.eq(random).append(insertionTemplate);
    }
    excludeNumA = random + 1;
    excludeNumB = random - 1;
}

【讨论】:

  • 谢谢,但是@adeneo 刚刚指出了一个问题。我应该在尝试解决这个问题时关闭它吗?
【解决方案2】:

我已经解决了这些问题并检查了下一个或上一个元素是否是猫。

var target    = $('.main').find('.image'),
    frequency = 3,
    element   = $();

for (var i = 0; i < frequency; i++) {
    (function getElems() {
        element   = target.eq( Math.floor(Math.random() * target.length) );
        var next  = element.next(),
            prev  = element.prev(),
            all   = element.add(next, prev);

        if (element.hasClass('cat') || next.hasClass('cat') || prev.hasClass('cat')) getElems();
    }());

    var template  = $('.template div').clone(true);
    element.before(template);
}

FIDDLE

【讨论】:

  • @MarkBoulder - 进行了一些更改,头等检查无法正常工作,但现在应该。
  • 有点好奇,为什么var template 不能在其他变量中?
  • 另外,下面是 Patrick Gundersen 的示例,特别是:“这更有效,因为您只需要检查要插入的精确对象,而不是检查每个图像”——我们应该添加对我们来说是这样的吗?
  • 至于效率,您可以在循环外对整个列表进行替换,这将使其更快,并且可能比下面 Patrick Gunderson 的答案快很多。我添加了一些计时器来查看逻辑和插入需要多长时间,这里 -> jsfiddle.net/QXdL3/30 和这里 jsfiddle.net/kf2zU/2,我的解决方案似乎是快三倍。
  • 更进一步并将其粘贴在 jsperf 中表明 Gundersons 解决方案非常慢,它太慢了,我想我一定是在 jsperf 中做错了什么,但我可以发现任何错误,所以我猜猜它的效率非常低 -> jsperf.com/for-loop-vs-gundersens-while
【解决方案3】:

您可以像上面的答案一样对列表进行快照,但这会更有效率,因为您只需要检查要插入的精确对象,而不是检查每张图像。

添加 2 个步骤。第一个应该打乱图像数组,以便它们每次都以不同的顺序排列。第二个应该在另一个列表中创建一个插入点数组。如果您不希望猫图像彼此相邻,请确保您的插入点列表至少间隔 2。

您还应该为您的模板使用&lt;script type="text/template"&gt; 标签。

http://jsfiddle.net/kf2zU/1/

HTML

<script id="cat-template" type="text/template">
    <div class="image">
        <img src="http://placekitten.com/75/150" />
    </div>
</script>
<script id="img-template" type="text/template">
    <div class="image">
        <img src="http://lorempixel.com/75/150" />
    </div>
</script>
<div class="main">
</div>

JS

var catTemplate = $("#cat-template").html();
var imgTemplate = $("#img-template").html();

//place images into .main
var $main = $(".main");
var numImages = 50;
for (var i = 0; i<numImages; i++){
    $main.append($(imgTemplate));
}

//make a list of cat images for example
var numCatImages = 50;
var cats = [];
for (i = 0; i < numCatImages; i++){
    cats.push($(catTemplate));
}

//shuffle the cat list so they appear in random order
cats = _.shuffle(cats);

//create a list of insertion points
var insertionPoints = [];
var insertionIndex = 0;
var minSpacing = 2;
var maxSpacing = 8;
var spacingRange = maxSpacing - minSpacing;
while(insertionIndex < numImages){
    insertionIndex += Math.floor(Math.random() * spacingRange) + minSpacing;
    insertionPoints.push(insertionIndex);
}

//place cat images at the insertion points
//it's important to start from the end and work your way forward so the previous insertions don't mess with subsequent insertion points
//so we reverse the array of insertion points

insertionPoints = insertionPoints.reverse();
var catIndex = 0;
_.each(insertionPoints, function(insertionIndex, i){
    $main.children().eq(insertionIndex).after(cats[catIndex++]);
});

【讨论】:

  • 哇,这真的很酷。我不知道脚本模板标签!但是@adeneo 的回答是不是简单多了?
  • @adeneo 的解决方案更简单,但效率要低得多。我的解决方案最大限度地减少了插入猫所需的步骤,而 adeneo 要求您在每次迭代时检查多个元素的多个属性。对于小列表,这可能是微不足道的,但对于大列表,我的解决方案将快几个数量级。我的解决方案也是可调的,因此您可以更好地控制间距。
  • 这对代码效率来说是一个很好的教训。谢谢。我真的很感激。。
  • 我可能会将此标记为正确,除非在我的情况下猫本身不需要洗牌,并且 Lorempixel 图像是预先存在的服务器端图像。希望有一天我可以给你买啤酒!
猜你喜欢
  • 1970-01-01
  • 2010-11-21
  • 2016-04-07
  • 1970-01-01
  • 1970-01-01
  • 2011-11-01
  • 1970-01-01
  • 2013-04-13
  • 2022-10-04
相关资源
最近更新 更多