Working with hex strings and hex values more easily in Javascript

I am taking strings which represent hexadecimal numbers (actually, hex colors) and adding them. So, adding aaaaaa + 010101 = ababab. 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, 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 as well, or if you take into consideration that I am removing the # from the hex color before all this starts.

Surely there's a way to do this with less steps! (And I don't mean just putting it all on one line (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 Javascript work with Hex more easily?

Answers:

Answer

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'
Answer

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.

Answer

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.

Answer

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.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.