我有一个元素,我正在用计时器改变它的颜色:
r = 0.05;
delta = 0.05;
function changecol(){
if (r < 0.05 || r > 0.95) delta = delta * (-1);
r += delta;
col = '#'+(Math.floor(r*255)).toString(16)+(Math.floor(r*255)).toString(16)+(Math.floor(r*255)).toString(16);
svg_elem.style.fill = col;
setTimeout("changecol()", 50);
}
因此颜色从白色变为黑色并返回,r*255
将其保持在00和FF之间,一切顺利,但当它变为黑色时,它会闪烁到白色并开始基本上升。我在计算中错过了一些错误吗?
这是一个带有演示的jFiddle:https://jsfiddle.net/b4f58bz2/
答案 0 :(得分:2)
我在你的jsfiddle上运行了一个console.debug,我发现(Math.floor(r*255)).toString(16)
当它闪烁时的结果是&#39; C&#39;在十六进制中,就在&#39; 0&#39;之前。问题在于,当翻译成css颜色时,#ccc
等于#cccccc
,这是一种非常浅的颜色,而不是一种深色。如果长度小于2,则必须使用前导0填充(Math.floor(r*255)).toString(16)
的结果,如:
color = (Math.floor(r*255)).toString(16);
if (color.length < 2) {
color = "0" + color;
}
然后只做:
col = '#' + color + color + color;
我希望这能让你走上正轨。
答案 1 :(得分:1)
这需要一点点。
问题是你转换为toString(16),你没有考虑你的十六进制代码太短的可能性。
R = hex.length == 1 ? "0" + hex : hex;
请参阅:
r = 0.05;
delta = 0.05;
function changecol() {
if (r < 0.05 || r > 0.95) delta = delta * (-1);
r += delta;
hex = (Math.floor(r * 255)).toString(16);
R = hex.length == 1 ? "0" + hex : hex;
col = '#' + R + R + R;
document.getElementById('test').style.backgroundColor = col;
setTimeout("changecol()", 300);
}
document.addEventListener('DOMContentLoaded', changecol, false);
<div id="test">
ADFASDF
</div>
<div id="test1">
ADFASDF
</div>
答案 2 :(得分:1)
另一张海报已经提到了编码小值时的错误,因此#0C0C0C
编码为#CCC
,实际上代表#CCCCCC
。
除此之外,你的代码还有一些不好的做法。
首先:使用局部变量!有些可能是“需要的”全球性的,但col
例如没有任何理由可以全球化。那只是环境污染。
下一步:将函数传递给setTimeout,而不是必须解析的字符串。
setTimeout(changecol, 50);
它更快,更清洁,可以封装,可以缩小,......只有好处。
然后,通过一个小技巧,你可以重写你的颜色编码更好:
var c = 255 * r;
var col = "#" + (0x1000000 | c << 16 | c << 8 | c).toString(16).substr(1);
0x1000000是填充,因此值总是超过6位,然后是三个颜色通道(r,g,b)。
此值转换为十六进制值,填充前面有一个1,然后由substr(1)删除。因此,我们总是有6个十六进制数字,每个颜色通道2个,不用担心前导零和东西。
位操作也会删除c
可能包含的所有小数位。
并且不要使用body-onload来启动这个东西。如果你真的需要,使用jQuery($(changecol))或搜索DOMContentLoaded实现,...或者只是将脚本放在正文的末尾,因此知道在解析完所有html之后执行该脚本,并且建造了dom。
但是imo。我们可以做得更好。我们可以将这个东西作为时间的函数,而不是递增和递减值,并给它一个5%的填充,这样你就不会越过边界,...
var startTime = Date.now();
var speed = 255 / 1000; //255 shades of gray / 1000ms
//this means every 2 seconds this animation completes
//a full cycle from black to white to black again.
//or you slow the speed down to `2*255 / 30000` for example
//1cycle per 30seconds
function changecol(){
//first we calculate the passed time since the start (in ms)
//and then we multiply it by the speed by wich the value should change
//the amount of color-steps per ms
var t = (Date.now() - startTime) * speed;
//now we get the fraction of 256 wich defines the shade
/*
var c = Math.floor(t % 256);
*/
//since we're dealing with powers of 2 we can use a bit-mask to extract just
//the last 8 bit of the value and do basically the same, including the Math.floor()
var c = t & 0xFF;
//every other interval we have to change the direction, so that we fade back from white to black
//and don't start over from 0 to 255 (black to white)
/*
var interval = Math.floor(t / 256); //get the interval
if(interval % 2 === 1) //check wether it's odd
c = 255 - c; //revert the direction
*/
//but again we can do easyer by simply checking the 9th bit.
//if it's a 1, this is an odd interval. the 9th bit equals 0x100 (256).
if(t & 0x100) //mask only the 9th bit. returns either 256 (wich is true) or 0 (false)
c = 0xFF - c; //revert the direction
var col = "#" + (0x1000000 | c << 16 | c << 8 | c).toString(16).substr(1);
test.style.color = col;
//using animation-frames to stay in sync with the rest of animation in the browser.
requestAnimationFrame(changecol);
}
changecol(); //start this thing, don't use body-onload
答案 3 :(得分:1)
要从黑色变为白色,您可以简单地使用HSL的亮度部分,其饱和度为0%,将其作为颜色参数:
用setTimeout()
替换requestAnimationFrame()
也可以使动画更顺畅,因为它会同步到监视器vblank更新。通过将delta减少到大约一半来弥补。
var l = 5;
var delta = 2.5;
(function changecol() {
if (l < 5 || l > 95) delta = -delta;
l += delta;
d.style.backgroundColor = "hsl(0,0%," + l + "%)";
requestAnimationFrame(changecol);
})();
<div id=d>Ping-pong fade</div>
答案 4 :(得分:0)
你可以做这样的事情,这样你就不必尝试找出正确的十六进制代码。
var whatColor = true;
fadeColor = function() {
var color = whatColor ? 'white' : 'black';
$('svg circle').css({fill: color});
whatColor = !whatColor;
setTimeout(function() {
fadeColor();
}, 1000);
}
fadeColor();
svg circle {
-webkit-transition: fill 1s;
transition: fill 1s;
fill: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg class="mySVG" height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" />
</svg>