본문 바로가기

Dev-FE

[CSS,JS] 동적 색상값(HEX) 얻기

디자이너 없이 작업할 경우 간혹 다양한 컬러값이 필요한 경우가 있다.  (토이프로젝트, 백오피스 데모 같은)
근무하는 동안에도 몇 번 활용했고, 토이프로젝트에서도 활용하게 되어 기록하고자 한다.

 

랜덤 색상 생성

#1. 랜덤 hex  생성의 기본 로직

hex를 생성하는 랜덤함수는 아래와 같다.

 

const hex = '#' + Math.round(Math.random() * 0xffffff).toString(16);

 

  • 무작위성 난수가 필요하므로 Math.random() 을 이용하여 0~1사이의 랜덤값 추출
  • 0xffffff 값 (수) 만큼 값을 곱하여 n개의 정수 추출
  • Math.round() 를 이용하여 소수점 제외
    • 난수로 얻은 값의 미세한 값변화를 필요로하지 않는다면 Math.ceil, Math.floor 모두 사용가능
  • .toString(16) 을 이용하여 추출된 정수를 16진법으로 변환
  • 추출된 16진법 값 앞에 '#' 을 붙여 css에서 사용하는 hex값으로 사용

다만, 위 코드만으로 hex 값을 완결하게 얻을 수 없다.

계산 된 값이 00인 경우 -> 0 으로 계산되기 때문에 자릿수가 부족한 경우가 발생한다.

아래는 chrome 개발자모드의 콘솔을 통해 테스트한 결과로 8번의 수행결과 중 2개의 값이 5자리의 난수가 발생한 것을 알 수 있다. (Math.floor, Math.ceil 모두 동일한 이슈가 발생했다.)

 

Math.random() 을 이용한 hex값 얻기

#2. 무결성 랜덤 hex 생성 로직

그래서 아래와 같은 방법으로 6자리 꽉꽉채운 hex값을 얻었다.

let hex = "#";
for (let c = 0; c < 6; c++) {
  hex += Math.round(Math.random() * 0xf).toString(16);
}

 

  • 무작위성 난수가 필요하므로 Math.random() 을 이용하여 0~1사이의 랜덤값 추출
  • 0xf 값 (수) 만큼 값을 곱하여 1개의 정수 추출
  • Math.round() 를 이용하여 소수점 제외
  • .toString(16) 을 이용하여 추출된 정수를 16진법으로 변환
  • 위 로직을 for loop 를 통해 6번 반복 수행
  • 추출된 16진법 값 앞에 '#' 을 붙여 css에서 사용하는 hex값으로 사용

이렇게 하면 누락없이 6자리의 hex 값을 얻을 수 있다.

이러한 로직을 이용하여 색상을 얻어 표출한 결과는 아래와 같다.

 

See the Pen Untitled by hee0 (@ryuheeyoung) on CodePen.

#3. hex to rgb

hex 값을 rgb 로 바꾼다면 아래와 같이 하면 된다.

 

const hex_num = '#c193c0'.split('#')[1];  // '#' 제거
let rgb = [];

for(let i = 0; i < hex.length; i+=2) {
  const color = hex.slice(i, i+2);
  rgb.push(parseInt(color, 16));
}

 

  • hex 값에서 '#' 을 제외한 16진법 문자열만 추출
  • slice() 를 이용하여 hex값을 두단위씩 잘라 숫자화 진행
  • parseInt(string, radix) 을 통해 문자열을 16진수로 변환

#4. rgb to hex

반대로 rgb 값을 hex 로 변환하려면 반대로 toString() 을 이용하면 된다.

 

const rgb_str = 'rgb(193, 147, 192)';
const rgb = rgb_str.match(/\d+/g);


// 방법#1. for loop 활용
let hex = '#';
for(let i = 0; i < rgb.length; i++) {
  hex += (+rgb[i]).toString(16);
}

// 또는

// 방법#2. reduce 활용
let hex = rgb.reduce((a, b) => {
  a += (+b).toString(16);
}, '#');

 

  • 'rgb(r,g,b)' 형의 문자열이라면 각각의 r,g,b 값을 추출
    • 본 예시에서는 정규식을 이용하여 숫자만 추출
  • (numberic).toString(16) 을 이용하여 16진법의 문자열로 변환

#5. 주의 사항

단, parseInt() 와 toString() 을 이용하여 변환 시, 자료형에 유의해야한다. (아래 그림 참고)