JavaScript: because static backgrounds are boring

October 1, 2011

When I was designing this website, I had to make a difficult decision: what would I put in the background? A plain white background is quite boring, while a single color looks fine at first but then gets boring. An image may be a nice idea, but I'm not that much of a visual arts person. Ultimately, I thought of an idea that could put my knowledge of programming to use and make the website look unique: an alternating color background! (This was partially inspired by the various triple-LED based color changing lights around campus at GT). Now the question arises of how to implement this so that 1) there aren't jarring transitions from one color to another, 2) there aren't jarring transitions between different pages, 3) a color spectrum is cycled through evenly and smoothly, and more subtly, 4) the average absolute rate of change of any one color (of RGB) is not more or less than that of the other two. The first two are self-explanatory, but 3 and 4 merit more attention. 3 suggests that a whole spectrum of colors is eventually cycled through. This is an aesthetic preference, in that the actual script doesn't have to behave this way. It essentially means that the amount of time the user sees 'red'-shade colors is the same as 'blue'-shade and 'green'-shade. This can also be implemented fairly easily. The last one is the source of many problems: what it means is that the amount of time the user sees a certain shade in a single period is the same across the three shades. That is, if the amount of green changes every second, while the amount of blue changes only once every hour, there will be a lot of green variation but little blue variation, and this causes the perception that only the green shade is in fact being changed. This becomes an issue with three variables, and can be analyzed mathematically (as shown below).

Before going into a further description, though, I wanted to present some ideas for how I first considered implementing the background-changing script. In order to keep the background color consistent across different pages, I used a system based on the user's local clock to determine the background color. That way, the first two requirements are satisfied: the rate of change of the color can be synchronized to the time and made smooth, and when linking from one page to another the time read by the two pages will be almost identical so the color change will again be smooth. Both approaches need to essentially convert a one-dimensional input (time) into a three-dimensional output (RGB colors), while satisfying conditions 3 and 4 above. The only practical way I found to satisfy condition 4 and 1 was to split the time into a binary sequence, then alternate which powers of two of that sequence would be assigned to which color. This approach, as you may see, limits the color spectrum to only combinations where the sum of colors is 255. That is, FF0000 or EE1100 are reachable while FFFFFF or 000000 are not.

The time is converted into base 3, such that the least significant figure changes once in every desired time interval (that is, once per second if we want the color to change once per second). Starting from the least significant figure, the value of that figure will be either 0, 1, or 2. That corresponds to the colors, arbitrarily chosen, R, G, and B. We start out with each color valued at 0. Then the color that corresponds to the (0,1,2) if the time is added the power of two corresponding to that figure (the first one is 2^0 = 1). Continuing to the next higher significant figure, that color is given 2 more units, then the next one is given 4 more, and so on.

For instance, the time is 12345 seconds. In base 3, this is 121221020 (base converter: http://www.cleavebooks.co.uk/scol/calnumba.htm). Reading right-to-left, the least significant figure is the 0 on the right. This corresponds to Red, so Red now has 2^0=1 unit. The next figure is the 2, second-to-right, corresponding to blue. Blue now has 2^1=2 units. The next one is 0 again, meaning Red is given 2^2=4 units, for a total of 5. This continues until the 2^7=128 unit is assigned, because at that point it is possible for one color to have its maximum value of 255. Otherwise, the 255 units are split between the other colors, covering the entire possible sum-255 spectrum and satisfying condition 4. The javascript code for this approach is given below. This function should be called 10 times per second (with setInterval("changeConstFactor()",100);).

function changeConstFactor(){
sec=(new Date().valueOf()*0.01)|0;  
tr=tg=tb=0;
for(a=0;a<8;a++){
c=Math.floor(sec/(Math.pow(3,a))+a)%3;
if(c==0)
tr+=Math.pow(2,a);
if(c==1)
tg+=Math.pow(2,a);
if(c==2)
tb+=Math.pow(2,a);
}
document.getElementsByTagName("body")[0].style.backgroundColor = "#" + dec2hex(br) + dec2hex(bg) + dec2hex(bb);
}

function dec2hex(i){
return (i<16?'0':'')+i.toString(16);
}

There is still a problem with this approach, since when the 128-unit color changes, the change is very visible. This could be improved by a dynamically-determined color allocation, that is 0,1,2 do not necessarily correspond to R,G,B but depending on time. So if the next 128-unit color is to be Green, for instance, the moment before that all the colors below it should also be green. I am not sure if this problem is solvable, but it seems so. I however did not have enough time for it. I did carry out an analysis on the even rate of change idea. You can see it in the rate of change in multiple variables posting.

The background changed I ended up using does not cover the whole range, but rather switches between emphasizing one of the three colors, with smooth transitions. Additionally, the base color is determined by time of day, and is made to be dark at night and light at mid-day (again with smooth transitions). I don't know how many other sites are doing this, I for one have not seen any. Anyways, I hope you at least find this background interesting!