Javascript 创建具有不同颜色比例的双色画布

Javascript 创建具有不同颜色比例的双色画布,javascript,arrays,canvas,pixel,Javascript,Arrays,Canvas,Pixel,我想使用javascript创建一个由两种颜色(例如橙色和蓝色)的128x128像素组成的图像。像素应该是随机排列的,我希望能够改变两种颜色的比例(例如,陈述类似“0.4橙色”的东西,以获得40%的橙色和60%的蓝色像素) 应该是这样的: if (Math.random() <= percentage){ setPixel(color1); } else { setPixel(color2); } 我在这里找到了一个脚本,可以创建一个具有随机像素颜色的画布,并对其进行了修改,使

我想使用javascript创建一个由两种颜色(例如橙色和蓝色)的128x128像素组成的图像。像素应该是随机排列的,我希望能够改变两种颜色的比例(例如,陈述类似“0.4橙色”的东西,以获得40%的橙色和60%的蓝色像素)

应该是这样的:

if (Math.random() <= percentage){
  setPixel(color1);
} else {
  setPixel(color2);
}

我在这里找到了一个脚本,可以创建一个具有随机像素颜色的画布,并对其进行了修改,使其只显示橙色。基本上,我要做的是创建“if语句”,将颜色值分配给像素。我想创建一个数组,使用在1和128*128之间随机抽取的propotion_orange*128*128唯一元素。然后,对于每个像素值,检查其是否在该数组中,如果是,则为其指定橙色,否则为蓝色。作为JS的新手,我在创建这样一个数组时遇到了麻烦。我希望我能以一种可以理解的方式陈述我的问题

这是我为随机像素颜色找到的脚本,我对其进行了修改,使其只显示橙色:

var canvas=document.createElement('canvas');
canvas.width=canvas.height=128;
var ctx=canvas.getContext('2d');
var imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
对于(变量i=0;idocument.body.appendChild(画布)您可以为画布上的像素数创建颜色数组。对于每个像素,可以指定保存该像素应采用的rgba值的rgba数组。最初,可以使用40%橙色rgba阵列和60%蓝色rgba阵列填充颜色阵列。然后,你可以洗牌这个数组,得到随机分布的颜色。最后,可以在每个像素上循环,并使用颜色数组中的关联值设置其颜色

见下例:

const canvas=document.createElement('canvas');
canvas.width=canvas.height=128;
const ctx=canvas.getContext('2d');
const imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
document.body.appendChild(画布);
//发件人:https://stackoverflow.com/a/6274381/5648954
函数洗牌(a){
对于(设i=a.length-1;i>0;i--){
常数j=数学楼层(数学随机()*(i+1));
[a[i],a[j]=[a[j],a[i]];
}
返回a;
}
函数generateColors(){
常数randomColorsArr=[];
常量颜色={
橙色:[255,128,0255],
蓝色:[0,0,255,255]
}
//对于每个像素,向randomColorsArr添加rgba阵列
for(设i=0;idisplayPx()
如果您想要一个粗略的分布,您只需在If条件下使用
Math.random()
,如下所示:

if (Math.random() <= percentage){
  setPixel(color1);
} else {
  setPixel(color2);
}

新的


为了好玩,这里有一个版本(使用不精确概率)可能会尽可能地提高效率,尽管使用32位ABGR常量可能会牺牲可移植性:

const canvas = document.createElement('canvas');
canvas.width = canvas.height = 128;
const ctx = c.getContext('2d');
const imgData = ctx.createImageData(c.width, c.height);
const data = imgData.data;
const buf = data.buffer;
const u32 = new Uint32Array(buf);

for (let i = 0; i < u32.length; ++i) {
    u32[i] = Math.random() < 0.4 ? 0xff0080ff : 0xffff0000;
}    
ctx.putImageData(imgData, 0, 0);
const canvas=document.createElement('canvas');
canvas.width=canvas.height=128;
const ctx=c.getContext('2d');
常量imgData=ctx.createImageData(c.宽度,c.高度);
常量数据=imgData.data;
const buf=data.buffer;
常数u32=新的UINT32阵列(buf);
对于(设i=0;i
在OP的128x128分辨率下,在剩余CPU负载的情况下,每帧可以轻松刷新整个画布一次。演示在

洗牌到位 一些答案建议使用Fisher-Yates算法创建像素的随机分布,这是迄今为止获得一组固定值(本例中为像素)的随机均匀分布的最佳方法

然而,这两种答案都产生了非常糟糕的实现,即重复像素(使用比需要更多的RAM,因此需要额外的CPU周期),并且都将像素处理为每个通道,而不是作为离散项(占用更多的CPU周期)

使用从
ctx.getImageData
获取的图像数据来保持数组的无序排列。它还提供了一种将CSS颜色值转换为像素数据的方便方法

洗牌现有图像 下面的洗牌功能将混合任何画布,保留所有颜色。使用32位类型化数组,您可以在一次操作中移动整个像素

function shuffleCanvas(ctx) {
    const imgData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
    const p32 = new Uint32Array(imgData.data.buffer); // get 32 bit pixel data
    var i = p32.length, idx;
    while (i--) {
        const b = p32[i];
        p32[i] = p32[idx = Math.random() * (i + 1) | 0];
        p32[idx] = b;
    }
    ctx.putImageData(imgData, 0, 0); // put shuffled pixels back to canvas
}
演示 这个演示增加了一些功能。函数
fillRatioAndShffle
为每种颜色在画布上绘制1个像素,然后使用像素数据作为Uint32来设置颜色比率,并使用标准洗牌算法(Fisher-Yates)洗牌像素阵列

使用滑块更改颜色比例

const ctx=canvas.getContext(“2d”);
无功电流比;
填充率和填充率(ctx,“黑色”、“红色”,0.4);
ratioSlide.addEventListener(“输入”,()=>{
const ratio=比值lide.value/100;
如果(比率!==currentRatio){fillRatioAndShffle(ctx,“黑色”,“红色”,比率)}
});    
函数fillratio和shffle(ctx、可乐、可乐、比率){
当前比率=比率;
ctx.fillStyle=colA;
ctx.fillRect(0,0,1,1);
ctx.fillStyle=colB;
ctx.fillRect(1,0,1,1);
常量imgData=ctx.getImageData(0