As most of you know, I grew up as a programmer using Flash and ActionScript, and in the last few years have been much more into web programming, particularly with HTML’s Canvas. In general I do like Canvas a lot. It’s a different mindset than Flash, but I enjoy the challenge.
One thing that has consistently annoyed me, though, is using colors. In ActionScript, colors were 24-bit or 32-bit numbers. So they were easy to manipulate. Want RGB? 0xffcc00. Combine channels? red << 16 | green << 8 | blue. Extract a channel? red = color >> 16, green = color >> 8 & 0xff, blue = color & 0xff. Because everything is numbers, numbers, numbers, it’s super easy to create random colors, tween colors, generate colors based on any math formula, etc.
Then you get into HTML/CSS/JS/Canvas. It’s all strings. You can do named CSS color: “cornflowerblue” or hex values “#ffcc00” and you can even do rgb/rgba: “rgb(255,128,0)” or “rgb(255,128,0,0.5)”. It looks all about as easy as ActionScript until you actually try to do it. Those rgb numbers must be integers, so if you have red, green blue values that might be floating point numbers, its:
[php lang=”javaScript”]”rgb(” + Math.round(red) + “,” + Math.round(green) + “,” + Math.round(blue) + “)”;[/php]
GAH! You write that a few times and you want to kill someone.
So I’d usually write some kind of function that would deal with that.
[php lang=”javaScript”]function rgb(red, green, blue) {
return “rgb(” + Math.round(red) + “,” + Math.round(green) + “,” + Math.round(blue) + “)”;
}[/php]
This past week, I took it a bit further and made a little library that did that and added a bunch of other neat features as well. Introducing “clrs”:
https://github.com/bit101/clrs
Essentially, clrs is an object that has a bunch of methods on it. These return a color object. So you can say:
[php lang=”javaScript”]var myColor = clrs.rgb(255, 128, 0);[/php]
The color object is just an object, but its toString method returns an “rgba(…)” string concatenated as above. It turns out that if you use an object for anything that needs a color value, it will call that toString method and will get the string you set. Thus, you can use color objects anywhere you need a color value in JavaScript:
[php lang=”javascript”]document.body.style.backgroundColor = myColor;
context.fillStyle = myColor;[/php]
So now you can set colors with rgb values (floats or ints), rgba values, 24-bit numbers, strings of any kind, even hsv values. I threw in some random functions as well. Not functions that do random things, but functions that return random colors. You can even interpolate between two colors.
So that’s cool in itself, but there’s more. That color object has a bunch of other methods. So once you have a color, you can set or get any of its red, green, blue or alpha channels, or all at once. Any of the set methods are chainable, so you can say:
[php lang=”javascript”]myColor
.setRed(255)
.setGreen(128)
.setBlue(0);[/php]
Another neat feature is binding. you can bind a color to a particular property of an object, say fillColor of a context2d.
[php lang=”javascript”]myColor.bind(context, “fillStyle”);[/php]
Now, whenever you change anything about that color, by calling setRed, setGreen, setRGB, etc. it will automatically update the context’s fill color with the new color.
Anyway, it’s early code. It needs to be more extensively tested. I welcome all feedback and contributions. I’d like to make it require.js compatible at some point. Any other standardization / best practice issue you see, or any methods you would like to see added, let me know, or do a pull request.
You’re aware of the fact that you can use numbers to make colors just the same as in Flash, right?
var mycolor = 0xffffff;
// all the math you want
ctx.fillStyle = ‘#’ + mycolor.parseInt(16);
My bad, it is mycolor.toString(16);
Yeah, I’m aware that numbers have a toString method. I even know what the arguments are! 🙂
But, say you have red, green and blue values of, say, 255, 200, 50. You have to do something like:
ctx.fillStyle = “#” + (255 << 16 | 200 << 8 | 50).toString(16); In my mind, this is not a whole lot better than: ctx.fillStyle = "rgb(" + 255 + "," + 200 + "," + 50 + ")"; As opposed to: ctx.fillStyle = clrs.rgb(255, 200, 50);
But I guess you were referring to the part where I said Flash was easier because it was all numbers and you could do whatever you wanted with math and just assign that as a color. So, yeah, true, valid point. I just found myself very often writing the “rgb(” + … kind of code. Way too often. So this was my personal solution.
Granted, even in Flash it would be something like beginFill(255 << 16 | 200 << 8 | 50), which is still a pain and opens the door to similar color libraries in ActionScript, which do exist, and I've even written some for my own use back in the day.