Working with hex strings and hex values more easily in Javascript
Solution 1
No, there is no way to tell the JavaScript language to use hex integer format instead of decimal by default. Your code is about as concise as it gets but note that you do not need to prepend the "0x" base indicator when you use "parseInt" with a base.
Here is how I would approach your problem:
function addHexColor(c1, c2) {
var hexStr = (parseInt(c1, 16) + parseInt(c2, 16)).toString(16);
while (hexStr.length < 6) { hexStr = '0' + hexStr; } // Zero pad.
return hexStr;
}
addHexColor('aaaaaa', '010101'); // => 'ababab'
addHexColor('010101', '010101'); // => '020202'
As mentioned by a commenter, the above solution is chock full of problems, so below is a function that does proper input validation and adds color channels separately while checking for overflow.
function addHexColor2(c1, c2) {
const octetsRegex = /^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i
const m1 = c1.match(octetsRegex)
const m2 = c2.match(octetsRegex)
if (!m1 || !m2) {
throw new Error(`invalid hex color triplet(s): ${c1} / ${c2}`)
}
return [1, 2, 3].map(i => {
const sum = parseInt(m1[i], 16) + parseInt(m2[i], 16)
if (sum > 0xff) {
throw new Error(`octet ${i} overflow: ${m1[i]}+${m2[i]}=${sum.toString(16)}`)
}
return sum.toString(16).padStart(2, '0')
}).join('')
}
addHexColor2('aaaaaa', 'bogus!') // => Error: invalid hex color triplet(s): aaaaaa / bogus!
addHexColor2('aaaaaa', '606060') // => Error: octet 1 overflow: aa+60=10a
Solution 2
How about this:
var hexValue = "aaaaaa";
hexValue = (parseInt(hexValue, 16) + 0x010101).toString(16);
document.writeln(hexValue); // outputs 'ababab'
There is no need to add the 0x prefix if you use parseInt.
Solution 3
I think accepted answer is wrong. Hexadecimal color representation is not a linear. But instead, 3 sets of two characters are given to R, G & B.
So you can't just add a whole number and expect to RGB to add up correctly.
For Example
n1 = '005500'; <--- green
n2 = '00ff00'; <--- brighter green
Adding these numbers should result in a greener green. In no way, adding greens should increase RED to increase. but by doing what accepted answer is doing, as in just treat whole number as one number then you'd carry over for numbers adding upto greater than f, f+1 = 10.
you get `015400` so by adding greens the RED increased .... WRONG
adding 005500 + 00ff00 should result in, = 00ff00. You can't add more green to max green.
Solution 4
For folks looking for a function that can add and subtract HEX colors without going out of bounds on an individual tuple, I wrote this function a few minutes ago to do just that:
export function shiftColor(base, change, direction) {
const colorRegEx = /^\#?[A-Fa-f0-9]{6}$/;
// Missing parameter(s)
if (!base || !change) {
return '000000';
}
// Invalid parameter(s)
if (!base.match(colorRegEx) || !change.match(colorRegEx)) {
return '000000';
}
// Remove any '#'s
base = base.replace(/\#/g, '');
change = change.replace(/\#/g, '');
// Build new color
let newColor = '';
for (let i = 0; i < 3; i++) {
const basePiece = parseInt(base.substring(i * 2, i * 2 + 2), 16);
const changePiece = parseInt(change.substring(i * 2, i * 2 + 2), 16);
let newPiece = '';
if (direction === 'add') {
newPiece = (basePiece + changePiece);
newPiece = newPiece > 255 ? 255 : newPiece;
}
if (direction === 'sub') {
newPiece = (basePiece - changePiece);
newPiece = newPiece < 0 ? 0 : newPiece;
}
newPiece = newPiece.toString(16);
newPiece = newPiece.length < 2 ? '0' + newPiece : newPiece;
newColor += newPiece;
}
return newColor;
}
You pass your base color as parameter 1, your change as parameter 2, and then 'add' or 'sub' as the last parameter depending on your intent.
Related videos on Youtube
brentonstrine
I like doing things manually. But I'm finally picking up on how incredibly useful all these new tools are.
Updated on March 03, 2022Comments
-
brentonstrine about 2 years
I have some code which takes strings representing hexadecimal numbers - hex colors, actually - and adds them. For example, adding
aaaaaa
and010101
gives the outputababab
.
However, my method seems unnecessarily long and complicated:var hexValue = "aaaaaa"; hexValue = "0x" + hexValue; hexValue = parseInt(hexValue, 16); hexValue = hexValue + 0x010101; hexValue = hexValue.toString(16); document.write(hexValue); // outputs 'ababab'
The hex value is still a string after concatenating
0x
, so then I have to change it to a number, then I can add, and then I have to change it back into hex format! There are even more steps if the number I'm adding to it is a hexadecimal string to begin with, or if you take into consideration that I am removing the#
from the hex color before all this starts.Surely there's a simpler way to do such simple hexadecimal calculations! And just to be clear, I don't mean just putting it all on one line like
(parseInt("0x"+"aaaaaa",16)+0x010101).toString(16)
or using shorthand - I mean actually doing less operations.Is there some way to get javascript to stop using decimal for all of its mathematical operations and use hex instead? Or is there some other method of making JS work with hex more easily?
-
Ansel Halliburton almost 12 years"get Javascript to stop using decimal for all of its mathematical operations and use hex instead" - No-no. JS uses neither. It's actually binary. You are talking about strings here.
-
-
Bob over 7 yearsThis is very neat. What happens if you add 0x010101 to 0xFFFFFF ? Or 0x000100 to 0x00FF00 - you're going to get some weird results because there are actually three octet pairs here and they should be summed separately with limits >00<FF and then concatenated back together.
-
Alacritas almost 4 yearsEverything you say is true, but I think this is more of a comment than an answer, since you don't actually provide an answer to the question. If you provide a solution here -- to do it correctly, as you describe -- then it should even be the accepted answer. As it is I will downvote this...and will gladly change it if you either move this to a comment or answer the question.
-
Alacritas almost 4 yearsThis should be the accepted answer, it actually provides a working solution.