Как проверить, является ли строка допустимым шестнадцатеричным представлением цвета?

120

Например:

AA33FF = допустимый шестнадцатеричный цвет

Z34FF9 = неверный шестнадцатеричный цвет (в нем есть Z)

AA33FF11 = неверный шестнадцатеричный цвет (есть лишние символы)

Alex
источник
10
в зависимости от контекста последний может быть допустимым цветом, если он включает альфа-канал в AARRGGBBформате.
Дж. Холмс

Ответы:

283
/^#[0-9A-F]{6}$/i.test('#AABBCC')

Чтобы уточнить:

^ ->соответствует началу
# ->хеша
[0-9A-F] ->любое целое число от 0 до 9 и любая буква от A до F
{6} ->предыдущая группа появляется ровно 6 раз
$ ->соответствует концу
i ->игнорировать регистр

Если вам нужна поддержка трехзначных HEX-кодов, используйте следующее:

/^#([0-9A-F]{3}){1,2}$/i.test('#ABC')

Единственная разница здесь в том, что

 [0-9A-F]{6}

заменяется на

([0-9A-F]{3}){1,2}

Это означает, что вместо совпадения ровно 6 символов он будет соответствовать ровно 3 символам, но 1 или 2 раза. Разрешить ABCи AABBCC, но неABCD

Ройи Намир
источник
18
По определению это правильно, но коды длиной 3 годны и для интерпретации браузером. color: #f00;также будет интерпретироваться как красный (# ff0000).
Smamatti
13
или другая форма:/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test("#f00")
Дж. Холмс
8
Я бы тоже добавил /^#([0-9a-f]{3}){1,2}$/iв смесь.
MasterAM 01
1
@AndresSepar /^#[0-9A-F]{3,6}$/i.test('#aabb')также проходит, но #aabbне является допустимым шестнадцатеричным цветом.
Роман Бойко
3
var isOk = /^#(([A-Fa-f0-9 ]{6}|[A-Fa-f0-9–{3})$/i.test('#aabbcc ') @RomanBoiko, это правильно! Спасибо!
Андрес Сепар
32

// regular function
function isHexColor (hex) {
  return typeof hex === 'string'
      && hex.length === 6
      && !isNaN(Number('0x' + hex))
}

// or as arrow function (ES6+)
isHexColor = hex => typeof hex === 'string' && hex.length === 6 && !isNaN(Number('0x' + hex))

console.log(isHexColor('AABBCC'))   // true
console.log(isHexColor('AABBCC11')) // false
console.log(isHexColor('XXBBCC'))   // false
console.log(isHexColor('AAXXCC'))   // false

Этот ответ обычно выдавал ложные срабатывания, потому что вместо Number('0x' + hex)него он использовал parseInt(hex, 16).
parseInt()будет анализировать от начала строки до тех пор, пока не достигнет символа, не включенного в radix ( 16). Это означает, что он может анализировать такие строки, как «AAXXCC», потому что он начинается с «AA».

Number(), с другой стороны, будет выполняться синтаксический анализ только в том случае, если вся строка соответствует основанию системы счисления. Теперь Number()не принимает параметр radix, но, к счастью, вы можете префикс числовых литералов, чтобы получить число в других радиусах.

Вот таблица для пояснения:

╭─────────────┬────────────┬────────┬───────────────────╮
 Radix        Characters  Prefix  Will output 27    
╞═════════════╪════════════╪════════╪═══════════════════╡
 Binary       0-1         0b      Number('0b11011') 
 Octal        0-7         0o      Number('0o33')    
 Decimal      0-9         -       -                 
 Hexadecimal  0-9A-F      0x      Number('0x1b')    
╰─────────────┴────────────┴────────┴───────────────────╯
fflorent
источник
6
+1 bcs намного лучше читать и быстрее понимать, чем регулярное выражение
Крис
10
@Chris 'потому что' также гораздо лучше читать и быстрее понимать, чем 'bcs' ;-)
Крис
1
@Chris: я так привык к bcs, для меня это не имеет значения. в любом случае мой комментарий был сделан как комплимент, так что будь счастлив.
Крис
12
Это неверно: parseInt ('abcZab', 16) выведет число и пройдет тест
Сальвадор Дали
1
@fflorent Потому что parseIntбудет принимать "abcZab", находить "Z"недопустимое (для системы счисления 16) и игнорировать это и все, что после него. Затем он берет начало "abc"и преобразует его в 2748(что также является результатом parseInt("abcZab", 16)доказательства того, что логика происходит). Как следует из названия, parseInt анализирует строку. Точно так же, как если бы вы разбирали число с единицами измерения с основанием 10 parseInt("10px", 10), вы бы получили 10. Вы можете увидеть его описание здесь: es5.github.io/#x15.1.2.2 (шаг 11)
Ян,
8

Это может быть сложной проблемой. После нескольких попыток я нашел довольно чистое решение. Позвольте браузеру делать всю работу за вас.

Шаг 1. Создайте div с параметром «Нет» для стиля границы. Div может быть расположен за экраном или это может быть любой div на вашей странице, который не использует границы.

Шаг 2: Установите цвет границы на пустую строку. Код может выглядеть примерно так:

e=document.getElementbyId('mydiv');
e.style.borderColor="";

Шаг 3: Установите цвет границы на цвет, в котором вы не уверены.

e.style.borderColor=testcol;

Шаг 4. Проверьте, действительно ли изменился цвет. Если testcol недействителен, никаких изменений не произойдет.

col2=e.style.borderColor;
if(col2.length==0) {alert("Bad Color!");}

Шаг 5: Очистите себя, вернув цвет к пустой строке.

e.style.borderColor="";

Див:

<div id="mydiv" style="border-style:none; position:absolute; left:-9999px; top:-9999px;"></div>

Теперь функция JavaScript:

function GoodColor(color)
{
   var color2="";
   var result=true;
   var e=document.getElementById('mydiv');
   e.style.borderColor="";
   e.style.borderColor=color;
   color2=e.style.borderColor;
   if (color2.length==0){result=false;}
   e.style.borderColor="";
   return result;
}

В этом случае функция возвращает истинный / ложный ответ на вопрос, другой вариант - вернуть действительное значение цвета. Ваше исходное значение цвета, значение из borderColor или пустая строка вместо недопустимых цветов.

Терри Протеро
источник
ИМО, это совсем не чистое решение
Густ ван де Валь
5

Если вы пытаетесь использовать его в HTML, попробуйте использовать этот шаблон напрямую:

 pattern="^#+([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$"

лайк

<input id="hex" type="text" pattern="^#+([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$" />

Это даст подтверждение на соответствие запрошенному формату.

Мохит Дхаван
источник
2
function validColor(color){
  var $div = $("<div>");
  $div.css("border", "1px solid "+color);
  return ($div.css("border-color")!="")
}

https://gist.github.com/dustinpoissant/22ce25c9e536bb2c5a2a363601ba261c

Примечание: для этого требуется jQuery

Это работает для ВСЕХ типов цвета, а не только для шестнадцатеричных значений. Он также не добавляет ненужные элементы в дерево DOM.

Дастин Пуассан
источник
Красиво, просто и очень хорошо работает. Лично я добавил if (hexString.indexOf ('#') == -1) {return false; } для проверки хэша в качестве элементарной проверки того, что цвет был шестнадцатеричным значением
365SplendidSuns
1

Если вам нужна функция, которая сообщает вам, допустим ли цвет, вы также можете попросить ее дать вам что-то полезное - вычисленные значения этого цвета - и вернуть null, если это недопустимый цвет. Вот мой удар по совместимой (Chrome54 и MSIE11) функции для получения значений RGBA «цвета» в любом из форматов - будь то «зеленый», «#FFF», «# 89abcd» или «rgb». (0,0,128) 'или' rgba (0, 128, 255, 0,5) '.

/* getRGBA:
  Get the RGBA values of a color.
  If input is not a color, returns NULL, else returns an array of 4 values:
   red (0-255), green (0-255), blue (0-255), alpha (0-1)
*/
function getRGBA(value) {
  // get/create a 0 pixel element at the end of the document, to use to test properties against the client browser
  var e = document.getElementById('test_style_element');
  if (e == null) {
    e = document.createElement('span');
    e.id = 'test_style_element';
    e.style.width = 0;
    e.style.height = 0;
    e.style.borderWidth = 0;
    document.body.appendChild(e);
  }

  // use the browser to get the computed value of the input
  e.style.borderColor = '';
  e.style.borderColor = value;
  if (e.style.borderColor == '') return null;
  var computedStyle = window.getComputedStyle(e);
  var c
  if (typeof computedStyle.borderBottomColor != 'undefined') {
    // as always, MSIE has to make life difficult
    c = window.getComputedStyle(e).borderBottomColor;
  } else {
    c = window.getComputedStyle(e).borderColor;
  }
  var numbersAndCommas = c.replace(new RegExp('[^0-9.,]+','g'),'');
  var values = numbersAndCommas.split(',');
  for (var i = 0; i < values.length; i++)
    values[i] = Number(values[i]);
  if (values.length == 3) values.push(1);
  return values;
}
Счеты
источник
0

Добавьте проверку длины, чтобы убедиться, что вы не получите ложное срабатывание

function isValidHex(testNum){
  let validHex = false;
  let numLength = testNum.length;
  let parsedNum = parseInt(testNum, 16);
  if(!isNan(parsedNum) && parsedNum.length===numLength){
     validHex = true;
  }
  return validHex;

}

ротато поти
источник