color system

잔잔바리한접시·2022년 11월 8일
0

react

목록 보기
10/12
post-thumbnail

super easy

개인 프로젝트 super easy는 자주 쓰는 디자인 리소스를 저장하고, 어디서든 복사 붙여넣기하여 편리하게 사용할 수 있는 웹 사이트입니다.

저장된 컴포넌트를 클릭하여 css 스타일링 코드를 클립보드에 복사할 수 있습니다. 오늘은 Colours 탭에 기능을 개선한 부분에 대해 기록해보려 합니다.

Colours 기능


Colours 기능은 간단합니다. 사용자가 원하는 색상을 추가하면 추가된 색상의 brightness를 조절하여 variation을 출력해주는 기능입니다.

가령 프로젝트의 primary-color#aa1231로 정했다고 예를 들면,

해당 컬러를 등록하여 등록된 컬러의 variation을 아래와 같이 보여줍니다.

불편한 점

사용자가 등록한 원본의 컬러는 Hex Code로 잘 출력이 됩니다. 다른 variation들은 원본 값에 filter: brightness();를 추가하여 출력합니다. 그런데 사용자는 원본 값을 제외한 variation의 컬러 Hex code를 알 수 없습니다. 해당 컬러 팔레트를 클릭하여 클립보드에 복사하면 아래와 같은 값이 복사됩니다.

color: #aa1231;
filter: brightness(1.2);

사용자는 원하는 색상을 사용할 순 있지만 그 색상의 Hex code는 알 방법이 없습니다. 게다가 color를 두가지 속성으로 제어하기 때문에 코드의 가독성도 떨어질 것으로 예상했습니다.

그래서 color에 brightness를 더하여 새로운 Hex code를 반환하는 기능을 만들기로 계획했습니다!

개선 방법

아이디어

image processing algorithm에서 착안하였습니다. 방법은 아래와 같습니다.

colour = GetPixelColour(x, y)
newRed   = Truncate(Red(colour)   + brightness)
newGreen = Truncate(Green(colour) + brightness)
newBlue  = Truncate(Blue(colour)  + brightness)
PutPixelColour(x, y) = RGB(newRed, newGreen, newBlue)

위 방법은 RGB 표현법을 기반으로 하고 있습니다. 주의 깊게 봐야하는 것은 brightness입니다. RGB 값에 brightness를 더해서 새로운 RGB 값을 반환하는 방식입니다. 그렇다면 brightness는 0 ~ 255 값을 가질 것으로 예상할 수 있습니다.

Hex to RGB

Super easy로 돌아오겠습니다. Super easy에서는 사용자에게 RGB 값이 아닌 Hex 값을 받고 있습니다. 받은 Hex값을 RGB로 변환하는 것이 첫 단계입니다. 코드는 아래와 같습니다.

const tmp = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);

정규식을 사용하여 RGB 코드를 반환합니다.

여기서 주의할 점은 hex코드는 #000처럼 3자리로 만들어 질 수 있지만, 위 정규식은 #000000과 같이 6자리의 hex code만 반환 가능하기 때문에 세자리의 hex code 입력을 방지하였습니다.

add brightness

이후 변환함수 전문입니다.

export const addBrightness = (hex, brightness) => {
  const tmp = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);

  const result = {
    r:
      Math.trunc(parseInt(tmp[1], 16) * brightness) > 255
        ? 255
        : Math.trunc(parseInt(tmp[1], 16) * brightness) < 0
        ? 0
        : Math.trunc(parseInt(tmp[1], 16) * brightness),
    g:
      Math.trunc(parseInt(tmp[2], 16) * brightness) > 255
        ? 255
        : Math.trunc(parseInt(tmp[2], 16) * brightness) < 0
        ? 0
        : Math.trunc(parseInt(tmp[2], 16) * brightness),
    b:
      Math.trunc(parseInt(tmp[3], 16) * brightness) > 255
        ? 255
        : Math.trunc(parseInt(tmp[3], 16) * brightness) < 0
        ? 0
        : Math.trunc(parseInt(tmp[3], 16) * brightness),
  };
  return rgbToHex(result.r, result.g, result.b);
};

추출한 RGB를 이용하여 새로운 RGB 값을 만들어내는 과정입니다. 여기서 주의 깊게 봐야하는 부분은 brightness입니다. css에서는 brightness를 0 ~ 255의 정수 값이 아닌 퍼센트 값으로 계산합니다.

따라서 image processing algorithms의 계산과는 다르게 여기선 brighness를 곱하여 계산합니다. RGB의 값은 0 ~ 255이기 때문에 예외처리도 해주었습니다. Math.trunc는 소수점을 제거하고 정수부분만 반환하는 함수입니다.

마지막으로 rgbToHex는 아래와 같습니다.

const componentToHex = (color) => {
  const hex = color.toString(16);
  return hex.length === 1 ? "0" + hex : hex;
};

export const rgbToHex = (r, g, b) => {
  return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
};

addBrightness 함수의 반환값을 사용하여 variation에 모두 hex code로 라벨링이 가능해졌습니다.

확인 과정

반환된 새로운 hex code가 의도한대로 잘 나왔는지 확인을 위해 adobe XD를 이용했습니다.

컬러가 미세하게 다른 것이 느껴지시나요?

밝은 색상 뿐 아니라 어두운 색상에서도 미세히 차이를 보이고 있습니다.

스포이드 기능을 사용하여 원본 색상을 복사하면 위와 같이 다른 hex code를 같은 색으로 인지합니다.

하지만 걱정하지 않아도 됩니다. 웹에서는 sRGB color space를 사용하는 반면에 design software에서는 raw color space를 사용하기 때문에 생기는 문제입니다.

쉽게 말해 웹에서의 #ff1c4e는 xd에서의 #ea3b53과 같은 색상입니다.

개선 후

이제 사용자가 color를 지정하여 등록하면 variation을 hex code로 나타낼 수 있습니다. 또한 원하는 color palette를 클릭하여 hex code를 클립보드에 복사할 수 있게 되었습니다.

0개의 댓글