HTML5JavaScriptООП

Выбор цветов на JavaScript или попросту «ColorPicker»

Мне очень приятно видеть рост числа уникальных посетителей моего блога, а потому я изо всех сил стараюсь затрагивать полезные и интересные темы. Как некоторые из Вас могли увидеть из предыдущего поста, я обзавелся аккаунтом в сети GitHub, и теперь всем будет удобнее брать исходники моего кода и следить за его развитием.

В сегодняшней статье будет много букв, примерно столько же кода и такая занимательная вещь, как HTML5. Речь пойдет о «велосипеде», который есть в любом уважающе себя js-фреймворке и в то же время является отличным примером работы со связкой HTML5+JS. Это утилита выбора цвета и получения информации и нем в народе известная под именем colorpicker

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


Демо-пример

Демо-пример

С чего же начать в разработке данного модуля? Давайте попробуем построить модель приложения. За основу возьмем цветовую модель HSV. Она состоит из:

  1. Выбора цвета на шкале Hue — оттенок цвета (это шкала цветов справа)
  2. Насыщенность цвета Saturation и его яркость — Value (квадрат с двумя градиентами по центру)

Шкалу Hue мы будем генерировать автоматически. До выхода HTML5 нам пришлось бы звать на помощь сторонние средства, но пятая версия языка разметки имеет в своем арсенале тэг <canvas>, который создает область для рисования, доступную для специализированных JavaScript-методов.

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

Алгоритм будет таков:

  1. По умолчанию мы выбираем красный цвет
  2. При перемещении по шкале Hue мы высчитываем положение курсора внутри шкалы, конвертируем его в RGB, изменяем подложку у SV-блока
  3. При перемещении внутри SV-блока также высчитываем положение курсора по осям (S — ось абсцисс, V — ординат) и вносим коррекции в полученный цвет, не меняя базовую подложку у SV-блока

Приступим!

Будем стремиться к простоте, а значит сделаем так, чтобы скрипт вызывался минимальным количеством кода. В html мы заводим div, в который будет подгружаться colorpicker (id=»picker_append»), а в базовом JS вызовем метод

colorpicker.get("picker_append");

Наш модуль будет подчиняться паттерну Singleton (Одиночка), т.е. на одной странице будем генерировать один colorpicker.

Сам модуль будет объектом Colorpicker, который имеет три метода — init (построение), get(вывод на страницу), destroy(уничтожение). С get и destroy все предельно ясно, за исключением того, что в методе get мы проверяем наличие на странице объекта Colorpicker. Конечно, это все легко обойти, но для красоты и эффектности очень полезно =)

Сразу же я подключу модуль Drag’n’Drop для корректной и удобной работы с положением курсора. Он «вшит» в код скрипта в самом его начале.

Подробно я опишу метод init. Внутри него будет три переменных-объекта : picker, hue и tones (сам механизм целиком, шкала цветов H и шкала оттенков SV соответственно). Далее мы создаем на странице DOM-элементы, необходимые для работы colorpicker-а.

Для объекта picker пишем метод init, внутри которого мы задаем параметры инициализации инструментов и производим их собственно инициализацию.

picker = {
        Y : 100,
        X : 100,
        init: function(){
            var params = {
                height: 256,
                width: 30,
                show_block: "show_block",
                tones_block: "picker",
                hue: app_div
            };
            var t_params = {
                show_block: "picker",
                marker: "circle"
            };

            hue.init(params);
            tones.init(t_params);

            picker.show_block = document.getElementById("show_block");
        }

    };

Сразу же появляются два метода init для объектов hue и tones, которые должны быть описаны. Начнем с hue.

Объявляем объект layer внутри hue, для которого есть метод create, внутри которого есть метод gradient. Тут самое интересное!

Мы определяем тип canvas — 2d.

var cont = layer.getContext("2d");

Далее мы создаем объект градиента внутри canvas.

var grad = cont.createLinearGradient(width/2,height,width/2,0);
var cols = [[255,0,0],[255,255,0],[0,255,0],[0,255,255],[0,0,255],[255,0,255],[255,255,255]];

Cols — это массив границ цветов, внутри которых будут организовываться переходы. Три элемента в каждом вложенном массиве — это значения по каждому из каналов : red, green и blue. Обходим в цикле этот массив и генерируем дополнительный граничный цвет для градиента при помощи метода addColorStop.

	for(var i=0; i<=6; i++)
        {
            color = 'rgb('+cols[i][0]+','+cols[i][1]+','+cols[i][2]+')';
            grad.addColorStop(i*1/6, color);
        }

    cont.fillStyle = grad;
    cont.fillRect(0,0,width,height);

Два последних метода заполняют полученным градиентом указанный DOM.

Также стоит рассмотреть метод hue2rgb.conv, который преобразует положение на всех трех шкалах (HSV) в цвета форматов HEX (шестнадцатеричный) и RGB.

Поскольку шкала SV по определению предоставляет нам квадрат 100 на 100, а DIV, в котором может содержаться элемент выбора, может оказаться больше или меньше, нам необходимо определить шаг выбора. Все просто - делим перемещение курсора на 100 =) . Расчитаем отклонение цвета на SV от Hue. В зависимости от него вычисляем каждую из трех составляющих RGB и возвращаем полученное значение.

Метод getHex позволяет нам преобразовать полученное значение RGB в HEX-формат. RGB поступает в виде массива из трех элементов ([R,G,B]), после чего значение каждого из них конвертируется в шестнадцатеричный формат. Для того, что соблюсти соответствие с графическими программами, в случае, если значание канала представляет собой значение из одной цифры, то мы её дублируем (т.о. если мы на выходе конвертации получили значение канала f, то в значении цвета будет ff).

Переменная-объект tones представляет собой SV-область выбора. Внутри нее генерируется маркер-кружок, который графически демонстрирует текущий выбранный оттенок. Шаг курсора также расчитывается делением на 100.

Метод cPos отслеживает положение курсора внутри SV-области, конвертирует его в цвет и присваивает значения результирующим полям.

Остальное - обработчики событий. Думаю, не нужно их подробно описывать, иначе зачем мы все здесь собрались?

В планах на улучшение : добавить возможность ручного ввода цвета в поля и, как следствие, обратной конвертации; копирование HEX-цвета в буфер обмена. Если же у кого-то из Вас возникнет желание сделать это самостоятельно, то я с удовольствием предоставляю ссылку на мой репозиторий в GitHub

За сим все! Безошибочного Вам кода!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *