Я знаю что в сети много подобных скриптов на разный вкус и цвет. Но мне захотелось написать свой с нуля и первое что я сделал полез в Гугл искать алгоритм создания(сolor picker). В итоге я был разочарован так как не нашел нечего кроме готовых скриптов, наверно поэтому после того как я разобрался и написал свой color picker, я решил поделится своим опытом в его написание.
Так как я пишу на чистом js без библиотек (не считая той которую я пишу сам:)) в данном посте будет только хардкор чистый javascript.
Что нужно знать что бы написать cp (сокращенно color picker):
- Основы Drag'n'Drop
- Немного разбираться в Canvas (на нем будет рисоваться шкала оттенков Hue)
1.CSS & html
<div class="picker" id="primary_block" >
<div id="line">
<div id="arrows">
<div class="left_arrow"></div>
<div class="right_arrow"></div>
</div>
</div>
<div id="block_picker">
<img src="img/bgGradient.png" class="bk_img"><div id="circle"></div>
</div>
</div>
Думаю комментарии тут не нужны структура простейшая.
Теперь css
.right_arrow {
width:0;
height:0;
left:23px;
position:absolute;
border-bottom:6px solid transparent;
border-left:10px solid transparent;
border-top:6px solid transparent;
border-right:10px solid black;
}//левая стрелка почти аналогично
.circle {
width:8px;
height:8px;
border:1px solid black;
border-radius:50%;
position:absolute;
left:0;
top:0;
cursor: default;
-moz-user-select: none;
-khtml-user-select: none;
user-select: none;
-webkit-user-select: none;
}
Это конечно не весь css код но больше нечего интересного нет (только позиционирование элементов ).
2.Javascript
Ну а теперь приступим к самому интересному, к Javascript.
Для начала нужно закончить структуру (т.е от рисовать шкалу Hue), и делать я буду это на canvas (для уменьшения количества изображений).
gradient: function(canva,w,h){
/*
canva- объект canvas
h - высота шкалы
w- ширина
*/
var context, gradient, hue;
context = canva.getContext("2d");
gradient = context.createLinearGradient(w/2,h,w/2,0);
hue = [[255,0,0],[255,255,0],[0,255,0],[0,255,255],[0,0,255],[255,0,255],[255,0,0]];
//цвета на шкале hue в rgb
for (var i=0; i <= 6;i++){
color = 'rgb('+hue[i][0]+','+hue[i][1]+','+hue[i][2]+')';
gradient.addColorStop(i*1/6, color);
};
context.fillStyle = gradient;
context.fillRect(0,0, w ,h);
}
Посмотреть и «потрогать» то что получилось можно здесь. Дальше пойдет тривиальное навешивание событий (поэтому этот код я пропущу).
Теперь разберем какую цветовую модель мы будем использовать, это будет HSV
HSV — цветовая модель, в которой координатами цвета являются:
Hue — цветовой тон, (например, красный, зелёный или сине-голубой). Варьируется в пределах 0—360°, однако иногда приводится к диапазону 0—100 или 0—1.
Saturation — насыщенность. Варьируется в пределах 0—100 или 0—1. Чем больше этот параметр, тем «чище» цвет, поэтому этот параметр иногда называют чистотой цвета. А чем ближе этот параметр к нулю, тем ближе цвет к нейтральному серому.
Value (значение цвета) или Brightness — яркость. Также задаётся в пределах 0—100 и 0—1.
как реализовать это на нашем cp наглядно показано ниже(рис 1)
Шкала Hue у нас есть, нам добавить изменение Saturation и Value (значение цвета).
Так как значение S и V у нас 0-100, может возникнуть вопрос:
что делать если ширина и высота блока больше 100?
-
var px_X = elem.clientWidth / 100;
/*
в переменной px у нас значение пикселя. Пример:
ширина блока 180
180/100 , при смещение на 1 пиксель наше значение должно увеличиваться на 1,8;
*/
var S = left / px_X;// в переменной left текущие смещение "круга" (div c id = "circle")относительно родителя
Math.round(S);//и не забываем округлять
При смещение «круга» отслеживаем изменения S и V (для визуального эффекта изменения цвета изменяем фон под картинкой(картинка полу прозрачная)).
Но для того что бы изменить фон на нужно конвертировать из HSV в RGB, сильно расписасывать этот этап я не буду так как тут есть формула и если ее сравнить с кодом ниже все будет понятно.
hsv_rgb: function (H,S,V){
var f , p, q , t, lH;
S /=100;
V /=100;
lH = Math.floor(H / 60);
f = H/60 - lH;
p = V * (1 - S);
q = V *(1 - S*f);
t = V* (1 - (1-f)* S);
switch (lH){
case 0: R = V; G = t; B = p; break;
case 1: R = q; G = V; B = p; break;
case 2: R = p; G = V; B = t; break;
case 3: R = p; G = q; B = V; break;
case 4: R = t; G = p; B = V; break;
case 5: R = V; G = p; B = q; break;
}
return [parseInt(R*255), parseInt(G*255), parseInt(B*255)];
}
писал сам так как то что находил в сети работало не корректно.
Надеюсь основные знания для создания cp я в этом посте дал, поэтому на этом я закончу потому что увеличивать функционал можно долго добавляю конвертацию в разные цветовые форматы…
3. Подведем Итоги
Вот что у меня получилось демо.
В этом посте старался объяснить как создать cp, не углубляясь сильно в код так как не видел в этом смысла в Drag`n`Drop нечего сложного нет!
Спасибо за внимание с вами был CyBer_UA и это мой первый пост о javascript (надеюсь не последний).
П.с код в итоговом примере кривоват (писался давно), просто только сейчас дошли руки написать этот пост.
Автор: cyber_ua