Jak sprawdzić, czy ciąg jest prawidłową reprezentacją koloru szesnastkowego?

120

Na przykład:

AA33FF = prawidłowy kolor szesnastkowy

Z34FF9 = nieprawidłowy kolor szesnastkowy (zawiera Z)

AA33FF11 = nieprawidłowy kolor szesnastkowy (zawiera dodatkowe znaki)

Alex
źródło
10
w zależności od kontekstu, ostatni może być prawidłowym kolorem, jeśli zawiera alfę w AARRGGBBformacie.
J. Holmes,

Odpowiedzi:

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

Opracować:

^ ->dopasowywanie rozpoczynające
# ->się od skrótu
[0-9A-F] ->dowolna liczba całkowita od 0 do 9 i dowolna litera od A do F
{6} ->poprzednia grupa występuje dokładnie 6 razy
$ ->dopasuj koniec
i ->zignoruj wielkość liter

Jeśli potrzebujesz obsługi 3-znakowych kodów HEX, użyj następujących:

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

Jedyna różnica polega na tym

 [0-9A-F]{6}

jest zastępowany przez

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

Oznacza to, że zamiast dopasować dokładnie 6 znaków, dopasuje dokładnie 3 znaki, ale 1 lub 2 razy. Pozwalając ABCi AABBCC, ale nieABCD

Royi Namir
źródło
18
Z definicji jest to poprawne, ale kody o długości 3 są również ważne do interpretacji przeglądarki. color: #f00;zostanie również zinterpretowany jako czerwony (# ff0000).
Smamatti
13
lub w innej formie:/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test("#f00")
J. Holmes
8
Dodałbym również /^#([0-9a-f]{3}){1,2}$/ido miksu.
MasterAM
1
@AndresSepar /^#[0-9A-F]{3,6}$/i.test('#aabb')również przechodzi, ale #aabbnie jest prawidłowym kolorem szesnastkowym.
Roman Boiko
3
var isOk = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/i.test('#aabbcc '); @RomanBoiko to prawda! Dzięki!
Andres Separ,
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

Ta odpowiedź generowała fałszywe alarmy, ponieważ zamiast Number('0x' + hex)tego używała parseInt(hex, 16).
parseInt()będzie analizować od początku ciągu, aż osiągnie znak, który nie jest zawarty w funkcji radix ( 16). Oznacza to, że może analizować łańcuchy, takie jak „AAXXCC”, ponieważ zaczyna się od „AA”.

Number()z drugiej strony, będzie analizować tylko wtedy, gdy cały ciąg pasuje do podstawy. Teraz Number()nie ma parametru radix, ale na szczęście możesz prefiksować literały liczbowe, aby uzyskać liczbę w innych promieniach.

Oto tabela dla wyjaśnienia:

╭─────────────┬────────────┬────────┬───────────────────╮
 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
źródło
6
+1 bcs znacznie lepsze do czytania i szybsze do zrozumienia niż wyrażenie regularne
Chris,
10
@Chris 'ponieważ' jest również znacznie lepsze do czytania i szybsze do zrozumienia niż 'bcs' ;-)
Chris
1
@Chris: Tak bardzo przyzwyczaiłem się do „bcs” dla mnie nie robi różnicy. w każdym razie mój komentarz miał być komplementem, więc bądź szczęśliwy.
Chris
12
To jest złe: parseInt ('abcZab', 16) wyświetli numer i przejdzie test
Salvador Dali
1
@fflorent Ponieważ parseIntweźmie "abcZab", znajdź "Z"to, co jest nieprawidłowe (dla radix 16) i zignoruj ​​to i wszystko po nim. Następnie bierze początek "abc"i konwertuje go na 2748(co jest również wynikiem parseInt("abcZab", 16)udowadniania, że ​​taka logika się dzieje). Jak sama nazwa wskazuje, parseInt analizuje ciąg. Tak jak gdybyś parsował liczbę z jednostkami o podstawie 10, tak jak parseInt("10px", 10), dostaniesz 10. Możesz zobaczyć to opisane tutaj: es5.github.io/#x15.1.2.2 (krok 11)
Ian
8

To może być skomplikowany problem. Po kilku próbach wymyśliłem dość czyste rozwiązanie. Pozwól przeglądarce wykonać pracę za Ciebie.

Krok 1: utwórz element div ze stylem obramowania ustawionym na brak. Element DIV może znajdować się poza ekranem lub może to być dowolny element DIV na Twojej stronie, który nie ma obramowań.

Krok 2: Ustaw kolor obramowania na pusty ciąg. Kod może wyglądać mniej więcej tak:

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

Krok 3: Ustaw kolor obramowania na kolor, którego nie jesteś pewien.

e.style.borderColor=testcol;

Krok 4: Sprawdź, czy kolor rzeczywiście się zmienił. Jeśli testcol jest nieprawidłowy, nie nastąpi żadna zmiana.

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

Krok 5: Oczyść się po sobie, ustawiając kolor z powrotem na pusty ciąg.

e.style.borderColor="";

Div:

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

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

W tym przypadku funkcja zwraca prawdziwą / fałszywą odpowiedź na pytanie, inną opcją jest zwrócenie prawidłowej wartości koloru. Oryginalna wartość koloru, wartość z borderColor lub pusty ciąg zamiast nieprawidłowych kolorów.

Terry Prothero
źródło
IMO, to wcale nie jest czyste rozwiązanie
Gust van de Wal
5

Jeśli próbujesz użyć go w HTML Spróbuj użyć tego wzorca bezpośrednio:

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

lubić

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

Potwierdzi zgodność z żądanym formatem.

Mohit Dhawan
źródło
2
function validColor(color){
  var $div = $("<div>");
  $div.css("border", "1px solid "+color);
  return ($div.css("border-color")!="")
}

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

Uwaga: wymaga to jQuery

Działa to dla WSZYSTKICH typów kolorów, a nie tylko wartości szesnastkowych. To też ma nie dołączyć zbędnych elementów do drzewa DOM.

Dustin Poissant
źródło
Ładny i łatwy i działa bardzo dobrze. Osobiście dodałem if (hexString.indexOf ('#') == -1) {return false; } aby sprawdzić hash jako elementarną kontrolę, czy kolor był wartością szesnastkową
365SplendidSuns
1

Jeśli potrzebujesz funkcji, która powie ci, czy kolor jest prawidłowy, równie dobrze możesz mieć coś użytecznego - obliczone wartości tego koloru - i zwrócić wartość null, jeśli nie jest to prawidłowy kolor. Oto moja próba znalezienia zgodnej funkcji (Chrome54 i MSIE11), aby uzyskać wartości RGBA „koloru” w dowolnym formacie - czy to „zielony”, „#FFF”, „# 89abcd” lub „rgb” (0,0,128) ”lub„ 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;
}
Liczydło
źródło
0

Dodaj kontrolę długości, aby upewnić się, że nie otrzymasz fałszywie dodatniego wyniku

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;

}

Rotato Poti
źródło