每次球碰到墙时,将球的颜色改变为随机的颜色

Changing the color of the ball to a random colour every time it hits the wall

本文关键字:颜色 改变 随机      更新时间:2023-09-26

我想改变点每次碰到墙的颜色。我看到一些解决方案,但我不知道为什么我的不起作用。

这是负责改变颜色的部分:

function chColor() {
    hex = Math.floor(Math.random() * 100000 + 1);
    color = '"' + "#" + hex + '"';
    color.toString();
    return color;
}

这里是不工作的小提琴:

https://jsfiddle.net/vpzd7ye6/

颜色过度

这个答案是方式过度,我打算丢弃它,但是,为什么不给那些可能需要它的人一个更好的随机颜色…<一口> (|: <我> D

当随机缝少时

选择一个随机的完全随机的颜色对我们人类来说,如果你想有一个明显的变化,吸引眼睛从一种颜色到另一种颜色,效果并不好。

问题是,许多可用的颜色值非常接近白色或黑色,而完全随机的颜色可能非常接近最后一个,使变化不可能被注意到。

简单随机颜色

首先,简单随机颜色从所有16,777,216种可能的颜色中选择一种完全随机的颜色。

function randColor(){
    return "#" + 
           (Math.floor(Math.random() * 0x1000000) + 0x1000000)
              .toString(16)
              .substr(1);
}

该函数的工作原理是找到一个随机的24位数字(0 - 0xFFFFFF与0 - 16777216相同)。因为数字没有前导零添加0x100000以下的所有随机值,当转换为十六进制时,将小于6位(CSS颜色值需要3或6位十六进制值),所以我添加0x1000000以确保数字> 0x100000并且始终有7位数字。由于第一个(最左边)数字是不需要的,我使用substr来删除它。然后添加了"#"和return。

函数Number.toString(radix)接受一个名为radix的实参,该实参指定要转换的数的进制。如果不提供,则默认为10(以10为基数是我们人类使用的)。十六进制颜色以16为基数,因此必须指定。toString基数参数可以是2(二进制)到36(使用字符0-9然后A-Z)之间的任何值

具有讽刺意味的是,我们人类倾向于发现不那么随机的序列比真正的随机序列更随机。许多音乐播放器使用这种类型的随机序列,当他们有播放设置为洗牌,以确保音轨不会在一行中播放两次或重复的音轨序列随机播放。

为了使随机颜色看起来更加随机和明显,您应该跟踪最后一个颜色返回,以便您可以确保您不接近该颜色。你还应该使用一种随意的颜色,远离白色和黑色。

var randColour = (function(){ // as singleton so closure can track last colour
    var lastHue = 0;
    const minChange = 360 / 3; // Hue distance from last random colour
    var lastVal = false; // for low high saturation and luminance
    const randomAmount = 360 / 3; // random hue range
    const minVal = 20; // how far from full black white to stay (percent)
    const minSat = 80; // how far from grey to stay (percent)
    return function(){
         var hueChange = Math.random() * randomAmount ;
         hueChange *= Math.random() < 0.5 ? -1 : 1; // randomly move forward or backward
         lastHue += 360 + hueChange + minChange;  // move away from last colour
         lastHue %= 360;  // ensure colour is in valid range
         var sat = (Math.random() * (100 - minSat)) + minSat; // get saturation (amount of colour)
         var val = (Math.random() * (50 - minVal * 2)) * 1.5; // get value (luminance)
         // switch between high and low and luminance
         lastVal = ! lastVal;
         if(lastVal){        
             val = minVal + val;
         } else {
             val = 100 - minVal - val;
         }

         return "hsl(" + lastHue.toFixed(0) + "," + sat.toFixed(0) + "%," + val.toFixed(0) + "%)";
     }
})(); // call singleton

这个函数返回一个随机的颜色,但确保饱和度和值保持在一个特定的范围内,并且色调从最后一个值至少在色轮周围的1/3处。它在低、低和高亮度值之间循环,使颜色变化尽可能清晰。闭包用于跟踪最后返回的颜色。函数返回随机颜色作为CSS hsl(hue, saturation, luminance)颜色字符串。

有两个常量控制颜色序列。minVal设置为20是远离全黑或全白的百分比。有效范围是0-~50,minSat设置为80是远离灰色的距离,以百分比表示。const minSat = 80;//距离灰色的距离(百分比)

比较变化

为了比较这两种方法,下面的演示使用两种方法并排显示一组随机颜色,然后每秒闪烁4次新的随机颜色。简单随意的颜色会时不时出现错过的变化。我让你来决定哪边是哪边。

var canvas = document.createElement("canvas");
canvas.width = 620;
canvas.height = 200;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
var randColour = (function(){ // as singleton so closure can track last colour
    var lastHue = 0;
    const minChange = 360 / 3; // min hue change
    var lastVal = false; // for low high saturation and luminance
    const randomAmount = 360 / 3; // amount of randomness
    const minVal = 20; // how far from full black white to stay (percent)
    const minSat = 80; // how far from grey to stay (percent)
    return function(){
         var hueChange = Math.random() * randomAmount ;
         hueChange *= Math.random() < 0.5 ? -1 : 1; // randomly move forward or backward
         lastHue += 360 + hueChange + minChange;  // move away from last colour
         lastHue %= 360;  // ensure colour is in valid range
         var sat = (Math.random() * (100 - minSat)) + minSat; // get saturation (amount of colour)
         var val = (Math.random() * (50 - minVal * 2)) * 1.5; // get value (luminance)
         // switch between high and low and luminance
         lastVal = ! lastVal;
         if(lastVal){        
             val = minVal + val;
         } else {
             val = 100 - minVal - val;
         }
            
         return "hsl(" + lastHue.toFixed(0) + "," + sat.toFixed(0) + "%," + val.toFixed(0) + "%)";
     }
})(); // call singleton
function randColor(){
    return "#" + 
           (Math.floor(Math.random() * 0x1000000) + 0x1000000)
              .toString(16)
              .substr(1);
}
const grid = 16; 
var gridX = 0;
var gridY = 0;
var bigSize = grid - (grid / 3 ) * 2;
const xStep = Math.floor((canvas.width - 12) / (grid * 2));
const yStep = Math.floor(canvas.height / grid);
var count = 0;
function drawRandomColour(){
     ctx.fillStyle = randColor(); // simple random colour
     ctx.fillRect(gridX * xStep, gridY * yStep, xStep, yStep);
     ctx.fillStyle = randColour(); // smart random colour
     ctx.fillRect(gridX * xStep + canvas.width / 2, gridY * yStep, xStep, yStep);
     if(count < grid * grid - 1){  // fill the grid
         gridX += 1;  // move to next grid
         if(gridX > grid-1){
             gridX = 0;
             gridY += 1;
             gridY %= grid;
         }
         count += 1;
         setTimeout(drawRandomColour,1); // quickly fill grid
         return; // done for now
     }
     // if grid is full pick a random grid loc and request the next random colour
     gridY = gridX = (grid / 3);
     setTimeout(centerChange,250); // every quarter second
     
 }
 function centerChange(){
     ctx.fillStyle = randColor(); // simple random colour
     ctx.fillRect(gridX * xStep, gridY * yStep, xStep * bigSize, yStep * bigSize);
     ctx.fillStyle = randColour(); // smart random colour
     ctx.fillRect(gridX * xStep + canvas.width / 2, gridY * yStep, xStep * bigSize, yStep * bigSize);
     setTimeout(centerChange,250); // every quarter second
 }
 drawRandomColour(); // start it up.

<

比较序列/strong>

这个演示只是将随机颜色绘制为随机值的序列。检查序列,看看你在一排中看到两种或两种以上难以区分的颜色的频率。你会发现左边的序列比右边的序列有更多的相似序列。

将demo展开到全页视图以查看两个序列

单击重新绘制序列。

var canvas = document.createElement("canvas");
canvas.width = 1240;
canvas.height = 800;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
var randColour = (function(){ // as singleton so closure can track last colour
    var lastHue = 0;
    const minChange = 360 / 3; // min hue change
    var lastVal = false; // for low high saturation and luminance
    const randomAmount = 360 / 3; // amount of randomness
    const minVal = 20; // how far from full black white to stay (percent)
    const minSat = 80; // how far from grey to stay (percent)
    return function(){
         var hueChange = Math.random() * randomAmount ;
         hueChange *= Math.random() < 0.5 ? -1 : 1; // randomly move forward or backward
         lastHue += 360 + hueChange + minChange;  // move away from last colour
         lastHue %= 360;  // ensure colour is in valid range
         var sat = (Math.random() * (100 - minSat)) + minSat; // get saturation (amount of colour)
         var val = (Math.random() * (50 - minVal * 2)) * 1.5; // get value (luminance)
         // switch between high and low and luminance
         lastVal = ! lastVal;
         if(lastVal){        
             val = minVal + val;
         } else {
             val = 100 - minVal - val;
         }
            
         return "hsl(" + lastHue.toFixed(0) + "," + sat.toFixed(0) + "%," + val.toFixed(0) + "%)";
     }
})(); // call singleton
function randColor(){
    return "#" + 
           (Math.floor(Math.random() * 0x1000000) + 0x1000000)
              .toString(16)
              .substr(1);
}
const grid = 32; 
var gridX = 0;
var gridY = 0;
const xStep = Math.floor((canvas.width - 12) / (grid * 2));
const yStep = Math.floor(canvas.height / grid);
var count = 0;
function drawRandomColour(){
     ctx.fillStyle = randColor(); // simple random colour
     ctx.fillRect(gridX * xStep, gridY * yStep, xStep, yStep);
     ctx.fillStyle = randColour(); // smart random colour
     ctx.fillRect(gridX * xStep + canvas.width / 2, gridY * yStep, xStep, yStep);
     if(count < grid * grid - 1){  // fill the grid
         gridX += 1;  // move to next grid
         if(gridX > grid-1){
             gridX = 0;
             gridY += 1;
             gridY %= grid;
         }
         count += 1;
         setTimeout(drawRandomColour,1); // quickly fill grid
         return; // done for now
     }
 }
 drawRandomColour(); // start it up.
 // redraw on click
 canvas.addEventListener("click",function(){
     if(count >= grid * grid - 1){
          gridX = gridY = count = 0;
          drawRandomColour();
     }else { 
          gridX = gridY = count = 0;
     }
 });

虽然第二个随机函数并不完美,但它可以不时地获得在上下文中看起来相似的颜色,这种情况比纯随机少得多。当用户注意到视觉变化很重要时,最好的方法是循环使用两种互补色(色相+ 180),其中一种具有高亮度,另一种具有低亮度。CSS hsl颜色字符串可以很容易地选择亮度和色调,当你想要随机的颜色给你更好的控制。

问题是将数字转换为十六进制颜色字符串。因此,您可以编写一个函数,将随机数转换为有效的十六进制颜色(请参阅该函数的功能):

function convertToColor(num){
    return '#' + ('00000' + (num | 0).toString(16)).substr(-6);
}

然后在chColor函数中使用它:

function chColor() {
    number = Math.floor(Math.random() * 100000 + 1);
    color = convertToColor(number);
    return color;
}

下面是工作示例链接:jsfiddle


也可以将函数重命名为getRandomColor:

function getRandomColor(){
    number = Math.floor(Math.random() * 100000 + 1);
    return convertToColor(number);
}

请查看更新后的提琴

我刚刚改变了你的chColor函数:

  function chColor() {
    color = "#" + ((1 << 24) * Math.random() | 0).toString(16);
    return color;
  }

我已经更新了小提琴。链接https://jsfiddle.net/vpzd7ye6/2/

我对您的更改颜色功能做了如下更改;

function chColor() {
        hex = Math.floor(Math.random() * 1000000) + 1;
        color = '' + '#' + hex + '';
        return color;
}