26

我有一些代码,它接受代表十六进制数字的字符串 - 实际上是十六进制颜色 - 并添加它们。例如,添加aaaaaa010101给出输出ababab
但是,我的方法似乎不必要地冗长和复杂:

var hexValue = "aaaaaa";
hexValue = "0x" + hexValue;
hexValue = parseInt(hexValue, 16);
hexValue = hexValue + 0x010101;
hexValue = hexValue.toString(16);
document.write(hexValue); // outputs 'ababab'

连接后的十六进制值仍然是字符串0x,所以我必须将其更改为数字,然后我可以添加,然后我必须将其更改十六进制格式!如果我要添加的数字是以十六进制字符串开头,或者如果您考虑到#在所有这些开始之前我正在从十六进制颜色中删除 ,则还有更多步骤。

当然,有一种更简单的方法可以进行如此简单的十六进制计算!为了清楚起见,我的意思并不是像把它全部放在一行上(parseInt("0x"+"aaaaaa",16)+0x010101).toString(16)或使用速记一样——我的意思是实际上做的操作更少。

有没有办法让javascript停止对其所有数学运算使用十进制并使用十六进制?还是有其他方法可以让 JS 更轻松地使用十六进制?

4

4 回答 4

37

不,没有办法告诉 JavaScript 语言默认使用十六进制整数格式而不是十进制。您的代码尽可能简洁,但请注意,当您将“parseInt”与基础一起使用时,您不需要预先添加“0x”基础指示符。

以下是我将如何解决您的问题:

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'

正如评论者所提到的,上述解决方案充满了问题,因此下面是一个功能,它可以进行正确的输入验证,并在检查溢出时分别添加颜色通道。

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
于 2012-06-13T21:32:48.360 回答
12

这个怎么样:

var hexValue = "aaaaaa";
hexValue = (parseInt(hexValue, 16) + 0x010101).toString(16);
document.writeln(hexValue); // outputs 'ababab'

如果使用 parseInt,则无需添加 0x 前缀。

于 2012-06-13T21:00:08.213 回答
7

我认为接受的答案是错误的。十六进制颜色表示不是线性的。但取而代之的是,给 R、G 和 B 提供了 3 组两个字符。

因此,您不能只添加一个整数并期望 RGB 正确添加。

For Example

n1 = '005500'; <--- green
n2 = '00ff00'; <--- brighter green

添加这些数字应该会产生更绿的绿色。无论如何,添加果岭应该增加 RED 来增加。但是通过做公认的答案正在做的事情,例如将整数视为一个数字,那么您将结转加起来大于f的数字,f + 1 = 10。

you get `015400` so by adding greens the RED increased .... WRONG

添加 005500 + 00ff00 应导致 = 00ff00。您不能将更多的绿色添加到最大绿色。

于 2018-02-20T23:59:34.633 回答
4

对于那些正在寻找一个可以在不超出单个元组范围的情况下添加和减去 HEX 颜色的函数的人,我在几分钟前编写了这个函数来做到这一点:

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;
}

您将基本颜色作为参数 1 传递,将更改作为参数 2 传递,然后根据您的意图将“添加”或“子”作为最后一个参数。

于 2020-02-13T21:26:15.020 回答