Thursday, October 04, 2018

A Little Mid Flight Color Hacking

While I work with colors all the time while building apps, I still have questions. What's the best algorithm for fading between colors? Is there an optimal way to randomly select a color scheme? How can you programmatically decide what color text is legible on a given background?

I used one of the flights this last summer to build a small JavaScript library to let me investigate these questions. Because I was mid flight while building this code, it meant that I was programming this on my Galaxy S9+ phone without the benefit of the Internet. This library was less about building a production tool and more about fully understanding a topic.

While planning out the library, it occurred to me that I could get by with two core components: an abstract representation of colors and a classic 'fold' function. Implementing a representation would let me stop thinking of colors as hex sequences (#A23F40) and start thinking them as a cluster of red, green and blue values (say, 63% Red, 18% Green, 25% Blue). The fold function is also a no-brainer, as it lets you implement map, filter, for-each and countless other functions by cleverly providing a different function and init value.

In terms of implementation, given the graphical nature of the task, it seemed programming directly in JavaScript would be ideal. But that led me to one of my first challenges: how can I get the browser on my phone to effortlessly load a particular JS file?

A solution came to me in the form of the utilitarian, yet powerful, kWS web server. This app turns your phone into a web server, hosting the directory of your choice on the port of your choice. In my case, I configured the server to show /sdcard/Projects on port 8080:

With the server running, I created a simple bootstrap HTML file:

I was able to execute main.js by visiting: http://localhost:8080/color_hacking/. Thankfully, there's no caching, so every change requires only a simple browser reload to view it.

With the development strategy figured out, I went to work building my library. First off, I tackled the representation issue by implementing cpack and cunpack. This let me write code like so:

var bg = cunpack("#A23F40");
var inverted = { red: 1 - bg.red, green: 1 - bg.green, blue: 1 - bg.blue };
var hex = cpack(inverted);

cfold was even easier to write. This function takes in a start and end color, a number of steps to transition the colors, an initial value and function which is delivered each of the color steps. Here's an example of generating 100 different colors between #0000AA and #FFAA00:

var html = 
  cfold("#00 00 AA", "#FF AA 00", 100, "",
       (html, color) => {
        return html + "<div style='height: 3px; background-color: " + cpack(color) + "'></div>\n";
  });

You can find the complete source code for the library here.

This was a fun exercise. While I still have my questions from above, I've got a clearer understanding as to how I might solve them, and I've got a handy library to help. If nothing else, working with kWS has added a new tool to my mobile-development toolbox.

Here's some screenshots that were generating using my library:

No comments:

Post a Comment