{"id":14281,"url":"\/distributions\/14281\/click?bit=1&hash=ab757d18c623a4013353d71493ed166f5261785dc223f01a84b7b3412c030874","title":"\u041a\u0430\u043a \u0441\u0447\u0438\u0442\u0430\u044e\u0442 \u0442\u0435\u043c\u043f\u044b \u0440\u043e\u0441\u0442\u0430 \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u043a\u0438? ","buttonText":"","imageUuid":""}

Еще один конвертер цветов и как встроить его к себе на сайт за 5 минут

Эй, вы там! Да, вы, который думает, что написание цветового конвертера – это просто, как торт. Думаете, что достаточно скопировать пару строк кода и всё готово? Ну-ну, так же можно подумать, что банан – это всего лишь желтый фрукт. Но, когда вы начинаете копаться в этой теме, то понимаете, что это не такая уж и простая задача. Ведь как сделать конвертер привлекательным и удобным для использования? И самое главное, как не тратить кучу времени на создание этого чудо-устройства? Ответы на все эти вопросы вы найдете в данной статье, которая поможет вам не потеряться в этом цветном безумии!

И это ещё не всё! В данной статье я расскажу вам, как встроить уже готовый цветовой конвертер на свой сайт, минуя все трудности и препятствия на пути к его созданию.

Hex и rgb: шпаргалка для новичков

Давайте начнем с простого: что такое hex и rgb? Если вы уже в курсе, то можете пропустить эту часть, не засоряя свою голову лишней информацией.

Так вот, rgb и hex – это цветовые модели, которые используются для представления цвета в виде чисел. Они не единственные, но сегодня мы рассмотрим именно их.

Сами по себе эти 2 модели очень похожи: кодирование производится на базе 3 цветов: красного, зелёного и синего, что обусловлено особенностями восприятия цветов сетчаткой человеческого глаза. Каждый из базовых цветов кодируется числами от 0 до 255, где 0 – это черный, а 255 – это чистый базовый цвет.

В моделях rgb и hex любой цвет представляется сочетанием красного, зелёного и синего, причём в рамках своей системы координат. В rgb это обычно записывается как rgb(число, число, число), а в hex – в виде шестнадцатеричного значения #xxxxxx, где X – это число или буква от A до F.

Чтобы всё прояснилось, давайте рассмотрим пример. Представьте, что у нас есть фиалковый цвет. В rgb он записывается как rgb(172, 83, 157), что означает, что фиалковый можно получить сочетанием красного (на 172 из 255), зелёного (на 83 из 255) и синего (на 157 из 255) цветов. А в hex этот же цвет будет записываться как #ac539d, где ac при переводе из шестнадцатеричной системы равняется 172, 53 – 83, а 9d – 157.

Ну что, понятно? Тогда давайте перейдем к самому конвертеру.

Как закодировать летнее небо в цифры: разбираемся с конвертером

Начнём с описания интерфейса. Он предельно прост: в центре расположены 2 строки ввода: в первой отображается значение цвета в формате hex, во второй – в rgb, а в качестве фона служит сам кодируемый цвет. При изменении одного из полей для ввода второе автоматически изменяется и отображает введенный цвет в нужной кодировке.

Интерфейс конвертера

Вы сами можете перейти по ссылке (https://codepen.io/Alkirys/pen/ZEoPOQN) и немного поиграть с конвертером в codepen.

А теперь можно перейти к описанию кода. Начнём с главного – функции конвертации. Но прежде чем мы погрузимся в мир окталов и битов, давайте расслабимся и насладимся моментом. Закройте глаза и представьте себе летнее небо. Голубое, светлое, прекрасное. А теперь представьте, что вы можете закодировать это небо в цифры! Круто, правда?

Хорошо, откройте глаза и вернёмся к нашей программе.

const hexToRgb = (hexStr) => { const bigint = parseInt(hexColor.slice(1), 16); return { r: (bigint >> 16) & 255, g: (bigint >> 8) & 255, b: bigint & 255 }; };

Для того, чтобы конвертировать rgb в hex, сначала мы обрезаем символ “#”, а затем преобразуем полученное значение из 16-ричной системы счисления в 10-чную. После этого с помощью битовых сдвигов и операций логического умножения получаем искомые значения базовых цветов.

Возможно, сейчас вы чувствуете, как в вашей голове раздается звук барабанных тарелок, прямо как у Гомера Симпсона, однако не беспокойтесь, сейчас мы всё разберем по полочкам.

Чтобы стало понятнее, давайте возьмем для примера фиалковый цвет и представим, что мы работаем с ним как с двоичным числом. Значение hex в двоичной системе счисления представляет из себя число из 24 нулей и единиц, где за каждый из базовых цветов отвечают по 8 цифр:

Значение hex в двоичной системе счисления

Первые 8 – за значение красного цвета, вторые – за зелёный, и последние за синий. Все, что мы делаем – при помощи битовых сдвигов отсекаем 8 цифр из левой части численного значения hex, а при помощи логического умножения – из правой. И в результате этих нехитрых манипуляций изначальное число представляется нам в виде трех 8-битных значений, каждое из которых описывает его составляющие: красную, зелёную и синюю.

Теперь рассмотрим конвертацию из rgb в hex:

const rgbToHex = (r, g, b) => { return "#" + ((1 << 24) + (+r << 16) + (+g << 8) + +b).toString(16).slice(1); };

Перед вами функция конвертации цвета из rgb в hex и слово «магия» мало передаёт, правда? Но не переживайте, сейчас всё станет понятно)

Сразу оговорюсь: не пугайтесь знаков “+”, которые стоят перед буквами r, g и b. В JavaScript это всего лишь способ преобразования строки в число.

Итак, для конвертации из rgb в hex нам нужно из 3 значений, описывающих цвет в rgb получить одно в шестнадцатеричном виде. Для этого мы сначала создаем число размером 25 бит, сдвинув единицу на 24 бита влево. У вас может возникнуть вопрос: “У нас же есть 3 значения по 8 бит, то есть результат должен содержать 24 бита. Как же так? ” Дело тут в том, что единица в начале нам нужна только для удобства формирования результата и в конце мы от неё избавимся.

После этого мы при помощи сдвигов влево “заполняем” наше hex значение составляющими базовых цветов путем простого сложения. Число, отвечающее за красный цвет мы сдвигаем на 16 бит, то есть, добавляем 16 нулей к нему в конец и прибавляем к результату. Потом прибавляем число, описывающее составляющую зелёного цвета, сдвинутое на 8 бит и в конце концов прибавляем число для синего цвета.

Чтобы было проще всё понять, давайте вспомним школьную программу и представим все вышеописанные операции в виде сложения в столбик на примере хорошо нам знакомого фиалкового цвета:

Процесс конвертации из rgb в hex

Уже не так сложно, правда? Чтобы получить финальный результат осталось только конвертировать полученное значение в строку в 16-ричном виде и обрезать первый символ (ту самую единичку в 25 бите) .

Когда случайный цвет – это не случайность: как генератор цвета учитывает тему браузера

Теперь, после того, как мы разобрались с тем, как работают функции конвертации, рассмотрим, что ещё интересного есть в нашем конвертере. И первое, что бросается в глаза – то, что еще до того, как пользователь вводит свой цвет, поля для ввода не пустые: в них уже записаны некоторые значения. Ведь согласитесь, не очень интересно было бы смотреть на белый экран. Именно поэтому в начале работы конвертер сам генерирует случайный цвет и производит его конвертацию. Это происходит в следующей функции:

const randomColorByTheme = (isDarkTheme = false) => { let hexColor; let rgbColor; do { hexColor = Math.floor(Math.random() * 16777215).toString(16); if (hexColor.length < longHexSize - 1) { hexColor = "0".repeat(longHexSize - 1 - hexColor.length) + hexColor; } hexColor = "#" + hexColor; rgbColor = hexToRgb(hexColor); } while (isDarkTheme ? !isWhiter(rgbColor) : isWhiter(rgbColor)); return { hex: hexColor, rgb: rgbColor }; };

Но давайте разберемся, как этот скрипт работает. Сначала он генерирует случайное 16-ричное число, чтобы получить начальное значение hex. После этого добавляет символ “#” и нули к нему в начало, если число получилось слишком маленьким. Ведь валидное значение hex должно содержать в себе 6 цифр.

Но что еще интересно есть в этом коде? Первое – функция isWhiter() . Она определяет, является ли переданный в неё цвет светлым или тёмным, то есть определяет параметр светлоты цвета. А второе – переменная isDarkTheme, которая позволяет определить, использует ли пользователь тёмную тему браузера или нет. Все знают, что сейчас эра тёмных тем и эти две вещи позволяют генерировать случайные цвета в соответствии с темой браузера пользователя.

Итак, полная логика работы цикла такова: мы генерируем случайный цвет в формате hex и конвертируем его в rgb. После этого повторяем этот процесс до тех пор, пока сгенерированный цвет не будет соответствовать цвету темы браузера. Если пользователь использует тёмную тему, то и сгенерированный функцией цвет будет темным, а если светлую – светлым.

Тёмная или светлая сторона браузера: как определить цветовую тему

А теперь давайте поподробнее остановимся на функции isWhiter() и на том, как определяется тема браузера пользователя.

Итак, мы должны определить, является ли цвет светлым или тёмным. Это можно сделать с помощью параметра «светлота», который к сожалению отсутствует в hex и rgb. Но не беспокойтесь, для этого мы будем использовать специальную формулу:

const isWhiter = (rgb) => { return 1 - (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255 >= 0.5; };

На её основе мы можем определить, светлый или тёмный цвет был сгенерирован. Если светлота цвета фона больше или равна 0.5, то цвет светлый, иначе – тёмный.

Конечно, вам наверняка непонятно, откуда взялись все эти коэффициенты, но в рамках этой статьи я предлагаю не закапываться в теорию цвета и довериться вашему покорному слуге в том, что эта формула работает. В остальном же, я уверен, что даже ваша бабушка сможет понять этот код (если она знает, что такое RGB) .

А теперь давайте поговорим об определении темы на девайсе пользователя. И как же здорово, что мы живём в эпоху, когда браузеры сами умеют это делать! Мы можем легко узнать, включил ли пользователь тёмную тему с помощью медиавыражения "(prefers-color-scheme: dark)":

const preferDarkTheme = window.matchMedia("(prefers-color-scheme: dark)"); const randomColor = () => { return randomColorByTheme( preferDarkTheme.media !== "not all" && preferDarkTheme.matches ); };

Чтобы быть уверенными, что пользователь использует тёмную тему, мы должны получить значение этого медиавыражения и проверить, что оно не принимает значение «not all».

Избегаем проблем с читаемостью: как правильно генерировать цвет для шрифта

А вот ещё одна интересная фишка, которая может пригодиться при работе с цветами. Вы когда-нибудь сталкивались с тем, что при использовании определённых цветов на фоне, текст становится плохо читаемым? Например, белый текст на жёлтом фоне или жёлтый текст на белом фоне. Чтобы избежать подобных проблем, нужно задавать цвет для шрифта в зависимости от используемого фона.

Для того, чтобы реализовать такую фишку, необходимо воспользоваться css-переменными:

:root { --main-bg-color: white; --minor-bg-color: rgba(255, 255, 255, 0.5); --main-bg-color-invert: rgba(0, 0, 0, 0.65); }

В файле стилей мы создаём переменные, отвечающие за то, какой цвет будет использоваться для шрифта и затем присваиваем их в качестве значения цвета текста у поля ввода:

.content__input { color: var(--main-bg-color); }

Осталось только учесть, что во время работы пользователь будет вводить цвета сам и в процессе выполнения программы нужно изменять значение созданной нами css-переменной при смене значения цвета в полях ввода:

if (isWhiter(color.rgb)) { contentContainer.style.setProperty("--main-bg-color", "#ffffff"); } else { contentContainer.style.setProperty("--main-bg-color", "#000000"); }

В данном случае мы переопределяем значения переменных для элемента contentContainer. Как несложно догадаться по названию, это не само поле для ввода, а его родительский элемент. Однако, стили, которые мы применяем для родительского элемента будут наследоваться его потомками, поэтому всё и будет работать как надо.

Валидация: как не поссориться с конвертером

Давайте поговорим о валидации, но не будем делать этот разговор скучным и формальным, как на уроке математики. Давайте рассмотрим это как свидание с нашим конвертером и узнаем, как не поссориться с ним.

В конвертере валидируются оба поля для ввода. Для проверки hex значения используется специальное регулярное выражение, которое блокирует ввод всех символов, кроме чисел и букв a, b,c, d,e, f. По всем правилам записывается оно так: /[^\da-f]/gi.

Как вы могли заметить, символ “#” не входит в это выражение, но не переживайте, его наличие тоже проверяется, просто это делается отдельно. И так же отдельно проверяется длина значения в поле для hex. Она может быть или 4 символа или 7 в зависимости от того, используется пользователем сокращённая запись hex или полная.

Для проверки данных в поле rgb используются следующие регулярные выражения: /[^\d, ()rgb]/gi и /[^rgb]/gi

Первое – для проверки всей строки rgb. Оно исключает ввод каких-либо иных символов, кроме допустимых, а второе используется для проверки буквенной части значения поля rgb. Также дополнительно проверяется каждое из численных значений базовых цветов на соответствие требованию того, что оно находится в пределах от 0 до 255.

Таким образом, мы гарантируем, что пользователь вводит только корректные данные. Так что, чтобы не поссориться с конвертером не забывайте, что он тоже человекоподобный и вместо того, чтобы кричать на него, если он не работает так, как вы ожидаете, дайте ему немного времени и попробуйте еще раз.

Будьте добры к конвертеру и он будет добр к вам)

Как вставить наш конвертер на сайт за 5 минут: инструкция для не программистов

Итак, мы подошли к самой интересной части – встраиванию нашего конвертера на сайт. Если вы не уверены, с чего начать, не переживайте! Вам не нужно быть гением в программировании, чтобы встроить наш конвертер. Достаточно всего лишь скопировать код и вставить его на ваш сайт. Это похоже на то, как вы вставляете ключ в замочную скважину. И, надеюсь, вы уже это делали раньше)

Для начала вам нужно перейти по следующей ссылке: https://codepen.io/Alkirys/pen/ZEoPOQN. Здесь расположена версия конвертера для интеграции и его исходный код.

Для того, чтобы встроить конвертер вам нужно просто скопировать весь его код к себе на сайт и расположить часть с html в нужном месте на вашей веб-странице. При желании вы также можете изменить стили для того, чтобы они лучше сочетались с дизайном сайта, например, задать свой шрифт:

* { position: relative; box-sizing: border-box; /* your font may be here */ font-family: "Azeret Mono", monospace; }

Конвертер цветов – это как магия, которой никогда не перестаёшь удивляться. И надеюсь, что благодаря этой статье вы стали настоящими волшебниками цвета, поняли, как работает цветовой конвертер из hex в rgb, а также узнали, как легко можно встроить такой на свой собственный сайт.

А если вы хотите узнать больше об инструментах, которые мы создаём, загляните на наш сайт https://nanotools.app. Мы работаем над тем, чтобы сделать вашу жизнь проще и удобнее. До новых встреч!

0
6 комментариев
Написать комментарий...
Ияза Гара

Можно вопрос?
Зачем это всё?
Нет, все понятно что вы рассказали про конвертацию цветов, но какой практический смысл, особенно рандомного генератора?
Давайте уж статью про палитру и автогенератор тем, базовые цвета и так далее.

Ответить
Развернуть ветку
Nano Tools
Автор

Добрый день. Прежде всего эта статья ставит целью поделиться опытом, связанным с процессом конвертации и интересными особенностями вопроса, чтобы другие люди не изобретали велосипед.
А идея статьи про палитры действительно интересная, спасибо за наводку)

Ответить
Развернуть ветку
Ияза Гара

Да тут не нужны велосипеды. Берем chroma.js или что-то подобное, и не заморачивает голову лишней информацией.

Ответить
Развернуть ветку
Nano Tools
Автор

Конечно можно взять и готовое решение. Можно не усложнять и например написать сайт при помощи Wix. Но гибкости при таком подходе будет меньше. Да и никакого понимания того, как и что работает не появится. У всего есть свои плюсы и минусы

Ответить
Развернуть ветку
Ияза Гара

Какие-то детские рассуждения. Большинство разработчиков знают про цветовые модели, хотя бы приблизительно представляют, как из одной получить другую. Хотя искренне не понятно, зачем это, потому что задача достаточно узкая, браузеры и так понимают все форматы.
Все библиотеки написаны, поэтому велосипед изобретаете вы в данный момент. Кстати, почему же вы toString(16) используете? Почему не написали функцию для конвертации чисел из десятичного в шестнадцатеричный формат, для понимания ;)
Хотите поспорить про гибкость с chroma.js, серьезно? )
Что же до кода из codepen и рекомендации вставить его на себе сайт, то увы, идея такая себе по объективным причинам.

Ответить
Развернуть ветку
Nano Tools
Автор

Вы привели свои аргументы, я привёл свои, продолжать наш спор не вижу необходимости, спасибо что прочитали статью, с вами было интересно её обсудить

Ответить
Развернуть ветку
3 комментария
Раскрывать всегда