使用javascript指定随机拾取的颜色

使用javascript指定随机拾取的颜色,javascript,jquery,css,performance,math,Javascript,Jquery,Css,Performance,Math,我的页面中有一个网格,我想通过javascript填充200个元素。填充.grid元素的实际代码如下: $(function () { var $gd = $(".grid"); var blocks=""; for(i=0; i < 200; i++){ blocks += '<div class="block"></div>'; } $gd.append(blocks); }); $(函数(){ var$gd=$(“.grid”)

我的页面中有一个网格,我想通过javascript填充200个元素。填充
.grid
元素的实际代码如下:

$(function () {
  var $gd = $(".grid");

  var blocks="";
  for(i=0; i < 200; i++){
    blocks += '<div class="block"></div>';
  }
  $gd.append(blocks);
});
$(函数(){
var$gd=$(“.grid”);
var blocks=“”;
对于(i=0;i<200;i++){
区块+='';
}
$gd.追加(块);
});
我现在要做的是给每个元素指定一个从列表中随机选取的颜色。让我们说红,蓝,黄,绿(意料之外的嗯?)。我希望这些值尽可能是随机的,同时也要避免重复拾取两次相同的颜色(为了清楚起见,可以选择红蓝红绿蓝等等,
红红绿黄

也许这在随机过程中会有所帮助,但我不知道如何实现上面提到的非两次相邻规则(如果可以应用的话)

实现这一结果的最佳方式是什么?我还想知道我是否可以对每个
.block
应用一个渐变,而不是一个平面的十六进制颜色;我想更好的方法是为CSS中映射的每个元素分配一个随机类,比如渐变等等

如果以上脚本可以优化性能,我非常感谢您的建议

其他信息:

  • 我正在使用jQuery
  • 网格由每行20个元素组成,共10行
  • 颜色应该是4,但可以提高到5-7,如果可以的话,可以添加一些中性灰色调
这里有一支笔可供试验

额外功能要求:如上所述,我想避免重复相邻的颜色。是否有可能避免这种“上上下下”的情况?我想要完全避免这种情况是非常困难的,但如果有人能找到解决办法,那就太棒了! 类似这样的情况,其中“nope”标记的元素被阻止,而“yep”标记的对角线被允许:

$(function () {
  var colors = ["red","blue","green","yellow"];
  var $gd = $(".grid");
  var previousColor;
  var blocks="";
  for(i=0; i < 200; i++){
    var color = "";
    while(color === previousColor) {
        color= colors [Math.floor(Math.random()*colors .length)];
    }
    blocks += '<div class="block" style="color:' + color + '"></div>';
    previousColor = color;
  }
  $gd.append(blocks);
});
$(函数(){
变量颜色=[“红色”、“蓝色”、“绿色”、“黄色”];
var$gd=$(“.grid”);
var-previousColor;
var blocks=“”;
对于(i=0;i<200;i++){
var color=“”;
while(颜色===以前的颜色){
颜色=颜色[Math.floor(Math.random()*colors.length)];
}
区块+='';
先前的颜色=颜色;
}
$gd.追加(块);
});

首先,我要使用类来表示颜色:

CSS:

下面是javascript:

$(document).ready(function() {
  var colors = ["red","blue","green","yellow"];
  var $gd = $(".grid");
  var previousColor;
  var previousRow;
  var rowSize = 10;
  while(rowSize--) previousRow.push("none");
  var blocks = "";
  for(i=0; i < 200; i++){
    var color = colors [Math.floor(Math.random()*colors .length)];
    while((color == previousColor) || (color == previousRow[i%rowSize])) {
        color = colors [Math.floor(Math.random()*colors .length)];
    }
    blocks += '<div class="block ' + color + '"></div>';
    previousColor = color;
    previousRow[i%rowSize] = color;
  }
  $gd.append(blocks);
});
$(文档).ready(函数(){
变量颜色=[“红色”、“蓝色”、“绿色”、“黄色”];
var$gd=$(“.grid”);
var-previousColor;
var-previousRow;
var rowSize=10;
while(rowSize--)previousRow.push(“无”);
var blocks=“”;
对于(i=0;i<200;i++){
var color=colors[Math.floor(Math.random()*colors.length)];
while((color==previousColor)| |(color==previousRow[i%rowSize])){
颜色=颜色[Math.floor(Math.random()*colors.length)];
}
区块+='';
先前的颜色=颜色;
上一行[i%行大小]=颜色;
}
$gd.追加(块);
});
我从一个类似于MikeB的代码开始,但添加了一个row元素,这样我们就知道当前块上方的内容了。

我想介绍的第一件事是过滤索引函数

给定一个数组:

var options = ['red', 'green', 'blue', 'purple', 'yellow']; // never less than 3!
和一个过滤器:

function filterFunc(val) { 
   var taken = { 'red': 1,  'blue': 1 };
   return taken[val] ? 0 : 1;
} 
我们可以从过滤器允许的值(=1)中获取第n项(这不是一种快速的方法,但在出现性能约束之前…):

然后,我们可以为
网格[rows][cols]
中的单元格选择随机颜色:

function randomColourNotUpOrLeft(grid, row, col, options, ignoreColour) {
  var takenlist = [];
  if(row > 0 && grid[row-1][col] != ignoreColour) {
    takenlist.push(grid[row-1][col]);
  }
  if(col > 0 && grid[row][col-1] != ignoreColour) {
    takenlist.push(grid[row][col-1]);
  }
  var filt = genFilterFunc(takenlist);
  var randomIndex = Math.floor(Math.random()*(options.length-takenlist.length));
  var randomColour = filteredIndex(options, filt, randomIndex);
  return randomColour;
}
请注意,此处使用的随机索引取决于过滤掉的颜色数量;如果剩下4个,我们可以得到0-3,但如果只剩下2个,它必须是0-1,以此类推。当相邻单元格的颜色相同和/或我们靠近边界时,选择哪种颜色的约束较少。最后填写一个网格:

function fillGridSpeckled(grid, options, nullColour) {
  for(var row=0; row<grid.length; ++row) {
    for(var col=0; col<grid[row].length; ++col) {
      grid[row][col] = randomColourNotUpOrLeft(grid,row,col,options,nullColour);
    }
  }
}
函数FillGridSpoked(网格、选项、NullColor){

对于(var row=0;row这不是一个完美的解决方案,因为它不会阻止垂直重复的颜色,但它可能是一个很好的起点。
while
语句确实是一个很好的观点,尽管它会产生奇怪的结果,因为它会在每个颜色之后留下一个空白元素。我稍微编辑了YOUR代码,以使用
background
关于
color
。不用担心垂直颜色,这是一个额外的功能要求,拥有它会很棒,但不是真正的强制性!我会用小提琴更新我的问题以用于实验谢谢你的意愿,结果确实是我想要得到的!不过我有一个问题:你为什么使用
canvas
来绘制元素?我知道这确实是最合适的方法,但我更喜欢在我的页面中添加一堆旧的注入式
div
s,以获得更好的浏览器支持,并可以为每个元素分配一个类,以便我可以通过CSS映射它们的样式。是否可以用这种方式更改您的代码?您还可以简单地告诉我,
filteredIndex
函数中(;
是什么意思?特别是我不明白圆括号后面的分号是什么意思,对不起,我还是javascript的新手(对“darn n00b”的委婉说法):P)慢慢地更好地掌握你的代码,我理解
canvas
是什么意思(我猜)创建一个没有垂直重复的布局是必要的。在这种情况下,你认为用渐变而不是平淡的颜色填充正方形的可能性是什么?我有点担心用渐变和笔划绘制200~正方形的性能。或者这根本不是问题吗?@Gruber:对不起,刚刚看到这些评论。你不知道“不必使用画布;我不太了解jquery,所以只需更改绘制到画布的代码,改为通过jquery在代码中设置颜色,至少是为了测试颜色。@Gruber:for(;
是因为
for
构造需要括号内的三个语句:init、test和incremen。”
function genFilterFunc(takenValues) {
   var takenLookup = {};
   for(var i=0; i < takenValues.length; ++i) {
      takenLookup[takenValues[i]] = 1;
   }
   var filterFunc = function(val) {
     return takenLookup[val] ? 0 : 1;
   };
   return filterFunc;
}
function randomColourNotUpOrLeft(grid, row, col, options, ignoreColour) {
  var takenlist = [];
  if(row > 0 && grid[row-1][col] != ignoreColour) {
    takenlist.push(grid[row-1][col]);
  }
  if(col > 0 && grid[row][col-1] != ignoreColour) {
    takenlist.push(grid[row][col-1]);
  }
  var filt = genFilterFunc(takenlist);
  var randomIndex = Math.floor(Math.random()*(options.length-takenlist.length));
  var randomColour = filteredIndex(options, filt, randomIndex);
  return randomColour;
}
function fillGridSpeckled(grid, options, nullColour) {
  for(var row=0; row<grid.length; ++row) {
    for(var col=0; col<grid[row].length; ++col) {
      grid[row][col] = randomColourNotUpOrLeft(grid,row,col,options,nullColour);
    }
  }
}