Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Canvas 2D fillStyle有时不更新颜色_Javascript_Canvas - Fatal编程技术网

Javascript Canvas 2D fillStyle有时不更新颜色

Javascript Canvas 2D fillStyle有时不更新颜色,javascript,canvas,Javascript,Canvas,我正在学习画布,有一个练习:每次球碰到墙壁时,尝试将球的颜色更改为随机颜色 在抽签之前,我检查球是否在墙内。如果它碰到球,首先我生成一个随机的十六进制值颜色,然后我用这个颜色画球 但它只是有时起作用。我已经记录了ctx对象的fillStyle属性,但有时它不会将值更改为新颜色 /*对画布的引用*/ var canvas=document.getElementByIdmyCanvas; var ctx=canvas.getContext2d; /*起球位置*/ 设x=canvas.width/2

我正在学习画布,有一个练习:每次球碰到墙壁时,尝试将球的颜色更改为随机颜色

在抽签之前,我检查球是否在墙内。如果它碰到球,首先我生成一个随机的十六进制值颜色,然后我用这个颜色画球

但它只是有时起作用。我已经记录了ctx对象的fillStyle属性,但有时它不会将值更改为新颜色

/*对画布的引用*/ var canvas=document.getElementByIdmyCanvas; var ctx=canvas.getContext2d; /*起球位置*/ 设x=canvas.width/2; 设y=canvas.height-30; /*移动球*/ 设dx=2; 设dy=-2; /*球尺寸*/ 设球半径=10; /*球颜色*/ 设ballColor=0095DD; /*抽签*/ 功能挂钩{ ctx.beginPath; ctx.arcx,y,ballRadius,0,Math.PI*2; ctx.fillStyle=球色; ctx.fill; ctx.closePath; x+=dx; y+=dy; } /*更新画布*/ 函数图{ ctx.clearRect0,0,canvas.width,canvas.height; 弹跳; 牵引杆; } /** *如果球出了边界, *将方向改为相反方向 */ 函数反弹{ ifx+dxcanvas.width-ballRadius{ dx=-dx; 随机颜色; } ify+dycanvas.height-ballRadius{ dy=-dy; 随机颜色; } } /*将球的颜色更改为随机十六进制值*/ 函数随机颜色{ 常量hexColor=[]; 常量字母=['A','B','C','D','E','F']; forlet数字=0;数字<6;数字++{ 设值=Math.floorMath.random*16; ifvalue>9{ 值=字母[值-9]; } hexColor.pushvalue; } ballColor=hexColor.join; } setIntervaldraw,10; html{ 框大小:边框框; } *,*::之前,*::之后{ 框大小:继承; 填充:0; 保证金:0; } 画布{ 背景:eee; 显示:块; 保证金:0自动; } 2D突破游戏
您的代码工作正常,每次球反弹时都会调用函数randomColor,但在颜色生成逻辑中,您可能会得到无效值,例如,A或AB,您可以轻松修复这些值,将*16更改为*15,并修复这些值

但也要注意,有时你的随机颜色与前一个非常接近,所以看起来它没有改变,但事实上它确实改变了,这是我相信我们大多数时候看到的

你可以想出一个智能随机函数,记住最后2或3种颜色,并防止下一种颜色与这些颜色相似。有关如何比较颜色的更多详细信息,请参阅此问题的答案:

在这里,我更改了随机颜色的逻辑,以包括色差逻辑,现在下一种颜色将真正显示与前一种颜色的对比度

var canvas=document.getElementByIdmyCanvas; var ctx=canvas.getContext2d; ctx.font=粗体30px快递新; 设x=y=40 设dx=dy=2; 设球半径=40; 设ballColor=0095DD; /*将球的颜色更改为随机十六进制值*/ 函数{ 常量hexColor=[]; 常量字母=['A','B','C','D','E','F']; forlet数字=0;数字<6;数字++{ 设值=Math.floorMath.random*15; ifvalue>9{ 值=字母[值-9]; } hexColor.pushvalue; } 如果colorDifballColor,则hexColor.join>50 ballColor=hexColor.join; 其他的 随机颜色; } 函数colorDifcolor1,color2{ 如果color1==color2,则返回0; 函数squaredDeltav1,v2{ 返回Math.powv1-v2,2; } 函数hexToRgbhex{ var result=/^?[a-f\d]{2}[a-f\d]{2}[a-f\d]{2}$/i.exechex; 返回结果{ r:parseIntresult[1],16, g:parseIntresult[2],16, b:parseIntresult[3],16 }:null; } var总和=0; var c1=六角体颜色1; var c2=六角体色2; 总和+=平方德尔塔克1.r,c2.r; 总和+=平方德尔塔克1.g,c2.g; sum+=平方deltac1.b,c2.b; var转换指数=19.5075; 返回Math.sqrtsum/conversionIndex; }; 功能挂钩{ ctx.beginPath; ctx.fillTextballColor,10,50; ctx.fillStyle=球色; ctx.arcx,y,ballRadius,0,Math.PI*2; ctx.fill; x+=dx;y+=dy; } 函数图{ ctx.clearRect0,0,canvas.width,canvas.height; 弹跳; 牵引杆; } 函数反弹{ ifx+dxcanvas.width-ballRadius{ dx=-dx;随机颜色; } ify+dycanvas.height-ballRadius{ dy=-dy;随机颜色; } } setIntervaldraw,10; *,*::在{margin:0;}之前,*::之后
您的代码工作正常,每次球反弹时都会调用函数randomColor,但在颜色生成逻辑中,您可能会得到无效值,例如,A或AB,您可以轻松修复这些值,将*16更改为*15,并修复这些值

但也要注意,有时你的随机颜色是非常非常clos 与前一个相比,它看起来没有改变,但事实上它确实改变了,这是我相信我们大多数时候看到的

你可以想出一个智能随机函数,记住最后2或3种颜色,并防止下一种颜色与这些颜色相似。有关如何比较颜色的更多详细信息,请参阅此问题的答案:

在这里,我更改了随机颜色的逻辑,以包括色差逻辑,现在下一种颜色将真正显示与前一种颜色的对比度

var canvas=document.getElementByIdmyCanvas; var ctx=canvas.getContext2d; ctx.font=粗体30px快递新; 设x=y=40 设dx=dy=2; 设球半径=40; 设ballColor=0095DD; /*将球的颜色更改为随机十六进制值*/ 函数{ 常量hexColor=[]; 常量字母=['A','B','C','D','E','F']; forlet数字=0;数字<6;数字++{ 设值=Math.floorMath.random*15; ifvalue>9{ 值=字母[值-9]; } hexColor.pushvalue; } 如果colorDifballColor,则hexColor.join>50 ballColor=hexColor.join; 其他的 随机颜色; } 函数colorDifcolor1,color2{ 如果color1==color2,则返回0; 函数squaredDeltav1,v2{ 返回Math.powv1-v2,2; } 函数hexToRgbhex{ var result=/^?[a-f\d]{2}[a-f\d]{2}[a-f\d]{2}$/i.exechex; 返回结果{ r:parseIntresult[1],16, g:parseIntresult[2],16, b:parseIntresult[3],16 }:null; } var总和=0; var c1=六角体颜色1; var c2=六角体色2; 总和+=平方德尔塔克1.r,c2.r; 总和+=平方德尔塔克1.g,c2.g; sum+=平方deltac1.b,c2.b; var转换指数=19.5075; 返回Math.sqrtsum/conversionIndex; }; 功能挂钩{ ctx.beginPath; ctx.fillTextballColor,10,50; ctx.fillStyle=球色; ctx.arcx,y,ballRadius,0,Math.PI*2; ctx.fill; x+=dx;y+=dy; } 函数图{ ctx.clearRect0,0,canvas.width,canvas.height; 弹跳; 牵引杆; } 函数反弹{ ifx+dxcanvas.width-ballRadius{ dx=-dx;随机颜色; } ify+dycanvas.height-ballRadius{ dy=-dy;随机颜色; } } setIntervaldraw,10; *,*::在{margin:0;}之前,*::之后
问题出在行value=letters[value-9];。这应该是value=字母[value-10]

这是因为您需要的映射是:

10 -> A (letters[0])
11 -> B (letters[1])
12 -> C (letters[2])
13 -> D (letters[3])
14 -> E (letters[4])
15 -> F (letters[5])

所以你需要减去10而不是9。

问题在于行值=字母[value-9];。这应该是value=字母[value-10]

这是因为您需要的映射是:

10 -> A (letters[0])
11 -> B (letters[1])
12 -> C (letters[2])
13 -> D (letters[3])
14 -> E (letters[4])
15 -> F (letters[5])

所以你需要减去10而不是9。

随机颜色生成可以简化很多:函数randomColor{ballColor=+Math.floorMath.random*0x1000000.toString16.padStart6,'0';}输入错误:你的随机生成器生成无效结果4-5个十六进制。。。因为数组的索引为0,15-9=>6,所以字母[6]未定义。但既然您似乎使用ES6,请使用@Patrick的解决方案,更干净更好。@Kaido您能详细说明一下无效的结果吗,我确实可以从中得到有效的结果。@HelderSepu强制值为a15@KaiidoYe将导致值设置为undefined,连接将输出3856之类的内容,可能不是预期的行为,但这不会导致任何错误。。。我看到的唯一问题是跳入一种与前一种颜色非常相似的颜色。随机颜色生成可以简化很多:函数randomColor{ballColor=+Math.floorMath.random*0x1000000.toString16.padStart6,“0”;}键入:随机生成器生成无效结果4-5个十六进制。。。因为数组的索引为0,15-9=>6,所以字母[6]未定义。但既然您似乎使用ES6,请使用@Patrick的解决方案,更干净更好。@Kaido您能详细说明一下无效的结果吗,我确实可以从中得到有效的结果。@HelderSepu强制值为a15@KaiidoYe将导致值设置为undefined,连接将输出3856之类的内容,可能不是预期的行为,但这不会导致任何错误。。。我看到的唯一问题是跳入一种与前一种颜色非常相似的颜色