Ещё один Color Picker
Вложений: 1
Вот хочу поделиться с вами небольшим плагином для jQuery. Т.к. не нашел ничего подобного из аналогов, написал сам. Может кому и пригодиться.
Отличия от остальных в том, что не используется графика и цвет можно выбирать только из спектра (т.е. без смешивания каналов). Если кому не нужна полная палитра - очень пригодиться. Демка лежит во вложении, так же выложу код сюда, чтобы можно было не качать.
(function($){
var settings = { // Настройки по умолчанию
// Свойства, передаваемые плагину (не обязательные):
width:100, // Ширина линии спектра
height:20, // Высота линии спектра
colorSize:1, // Ширина одного цвета
setColor: null, // Установка начального цвета для спектра
marker: null, // Селектор или DOM-элемент маркера
onMouseDown: null, // Обработчик события при mousedown
onMouseMove: null, // Обработчик события при mousemove
onMouseUp: null, // Обработчик события при mouseup
// Свойства, доступные в обработчиках события через this
colors: [], // Массив всех сгенерированных цветов.
dom: null // DOM-элемент линии спектра
};
var handlers = (function(){ // Обработчики событий линии спектра
var opt; // Опции спектра
function getColor(evt){ // Получение цвета
if(evt.pageX < opt.dom.offsetLeft){
return opt.colors[0];
} else {
return opt.colors[Math.floor((evt.pageX - opt.dom.offsetLeft) / opt.colorSize) * opt.colorSize - opt.colorSize] || opt.colors[opt.colors.length - 1];
}
}
function setMarkerPosition(evt){ // Установка позиции маркера
if(opt.marker){
var mWidth = opt.marker.offsetWidth / 2,
oLeft = opt.dom.offsetLeft,
oRight = opt.dom.offsetWidth + oLeft - mWidth,
newPosition = evt.pageX - mWidth;
if(newPosition < oLeft - mWidth){
opt.marker.style.left = oLeft - mWidth + 'px';
} else if(newPosition > oRight){
opt.marker.style.left = oRight + 'px';
} else {
opt.marker.style.left = newPosition + 'px';
}
}
}
return {
onMouseDown: function(evt, data){ // Нажатие на спектр
evt = data || evt;
opt = evt.data;
if(!evt.pageX){
evt.pageX = evt.target.offsetLeft + opt.dom.offsetLeft + evt.target.offsetWidth;
}
setMarkerPosition(evt);
if($.isFunction(opt.onMouseDown)){
opt.onMouseDown(getColor(evt));
}
$(document).bind('mousemove', handlers.onMouseMove).bind('mouseup', handlers.onMouseUp);
return false;
},
onMouseMove: function(evt){ // Драг маркера
setMarkerPosition(evt);
if(opt.onMouseMove){
opt.onMouseMove(getColor(evt));
}
return false;
},
onMouseUp: function(evt){ // Остановка драга маркера
setMarkerPosition(evt);
if(opt.onMouseUp && evt.pageX){
opt.onMouseUp(getColor(evt));
}
$(document).unbind('mousemove', handlers.onMouseMove).unbind('mouseup', handlers.onMouseUp);
return false;
}
}
})();
function markerEvent(evt){ // Обработчик события маркера
$(evt.data.dom).trigger('mousedown', evt);
return false;
}
$.fn.extend({
colorPicker: function(opt){ // colorPicker - имя плагина
var dom = this[0]; // this[0] = линия спектра
// Применение настроек
var domWidth = dom.offsetWidth;
var domHeight = dom.offsetHeight;
if(typeof opt.width != 'number' && domWidth > 0){
opt.width = domWidth;
}
if(typeof opt.height != 'number' && domHeight > 0){
opt.height = domHeight;
}
opt = $.extend(settings, opt);
opt.dom = dom;
opt.marker = $(opt.marker)[0];
// Необходимые стили для спектра
dom.style.cssText = 'display: block; ' +
'lihe-height: ' + opt.height + 'px; ' +
'width: ' + opt.width + 'px; ' +
'height: ' + opt.height + 'px; ' +
'position: relative;' +
'overflow: hidden';
// Инициализация маркера
if(opt.marker){
opt.marker.style.position = 'absolute';
opt.marker.style.display = 'block';
opt.marker.style.top = dom.offsetTop + (opt.height / 2) - (opt.marker.offsetHeight / 2) + 'px';
$(opt.marker).bind('mousedown', opt, markerEvent);
}
// Установка обработчика линии спектра
this.bind('mousedown', opt, handlers.onMouseDown);
// Генерация цветов спектра
var colors = [];
var colorLength = opt.width / 6;
for(var i = 0, l = Math.ceil(colorLength / opt.colorSize); i < l; i++){
var tmpColor = Math.ceil((i * opt.colorSize) * 255 / colorLength).toString(16);
colors.push((i == l-1) ? 'ff' : (tmpColor.length == 1) ? '0' + tmpColor : tmpColor);
}
var rgb = {
r: colors.slice(0).reverse(),
g: colors.slice(0),
b: colors.slice(0)
},
colorsIndex = {
r : 0,
g : 0,
b : 0
},
channels = ['g', 'r', 'b'],
channelIndex = 0,
fragment = document.createDocumentFragment(),
setColor;
for(i = 0, l = opt.width / opt.colorSize; i < l; i++){
var chanel = channels[channelIndex];
if(colorsIndex[chanel] == colors.length-1){
rgb[chanel].reverse();
colorsIndex[chanel] = 0;
channelIndex++;
if(channelIndex == channels.length){
channelIndex = 0;
}
} else {
colorsIndex[chanel]++;
}
var newDiv = document.createElement('div'),
newColor = '#' + rgb.r[colorsIndex.r] + rgb.g[colorsIndex.g] + rgb.b[colorsIndex.b];
opt.colors[i * opt.colorSize] = newColor;
newDiv.style.cssText = 'background-color: ' + newColor + '; ' +
'float: left; ' +
'width: '+ opt.colorSize +'px; ' +
'height: '+ opt.height +'px; ';
newDiv.appendChild(document.createTextNode(' '));
fragment.appendChild(newDiv);
if(newColor == opt.setColor){
setColor = newDiv;
}
}
dom.appendChild(fragment);
// Установка начального положения маркера
$(setColor || dom.firstChild).trigger('mousedown').trigger('mouseup');
}
});
})(jQuery);
Ваши предложения и комментарии. |
Вложений: 1
А если CSS-градиенты попробовать использовать?
В Fx как-то так: <div style="width: 200px; height: 40px; background: -moz-linear-gradient(left, red, yellow, cyan, blue, magenta);"></div> |
Цитата:
Т.е. ты предлагаешь в обработчиках события вычислять цвет по формуле? Тут важно написать правильную формулу:) Да и не факт что для IE эта формула подойдет... А для других браузеров есть что-то подобное? Зелёный забыл:) |
А, кста нельзя будет задавать ширину цвета... По-моему не плохой эффект получается:)
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
А еще градиент можно нарисовать на Canvas или при помощи SVG/VML :) Gradients |
В данном случае это будет просто излишний кроссбраузерный онанизм.
Подобный градиент в пнг ничего не весит вообще.) |
Цитата:
Цитата:
|
Цитата:
|
Цитата:
Цитата:
|
svg,vml,canvas,-gradient - это всё нифига не кроссбраузерно.
Рисовать дивами - в данном конкретном случае можно, но более детально - во-первых тормоза, а во вторых куча мусорного кода. |
Цитата:
Цитата:
|
По поводу CSS градиентов.
Opera - не поддерживает. Нужно использовать Canvas+JavaScript. Firefox - с версии 3.6 (Январь 2010г. - совсем свежая). IE - нужно создавать 6 блоков и заливать их цветами, т.к. их мегафильтры умеют генерить градиент только из 2 цветов. К тому же последний нужно позиционировать скриптом. Safari - всё ок. Думаю оно того не стоит:) Уж лучше на SVG. Но тут опять же кроссбраузерный геморрой. Пока вариант на дивах выигрывает, есль не хочется тонну кода для такой простой вещи. Кому интересно, вот код. Без оперы.
<style type="text/css">
html, body{
margin:0;
padding:0;
}
.colorPicker{
background-image: -moz-linear-gradient(left, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
background: -webkit-gradient(linear, left top, right top, from(#FF0000), to(#FF0800), color-stop(.1666,#FFFF00),color-stop(.333,#00FF00),color-stop(.5,#00FFFF),color-stop(.666,#0000FF),color-stop(.833,#FF00FF));
overflow:hidden;
position:relative;
height: 20px;
display:block;
margin:0;
padding:0;
}
.colorPicker .colorItem{
display:block;
float:left;
width:16.66%;
height:20px;
}
.colorItem.color1{
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffff0000, endColorstr=#ffffff00, GradientType=1)";
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffff0000, endColorstr=#ffffff00, GradientType=1);
}
.colorItem.color2{
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffffff00, endColorstr=#ff00ff00, GradientType=1)";
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffffff00, endColorstr=#ff00ff00, GradientType=1);
}
.colorItem.color3{
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff00ff00, endColorstr=#ff00ffff, GradientType=1)";
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff00ff00, endColorstr=#ff00ffff, GradientType=1);
}
.colorItem.color4{
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff00ffff, endColorstr=#ff0000ff, GradientType=1)";
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff00ffff, endColorstr=#ff0000ff, GradientType=1);
}
.colorItem.color5{
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff0000ff, endColorstr=#ffff00ff, GradientType=1)";
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff0000ff, endColorstr=#ffff00ff, GradientType=1);
}
.colorItem.color6{
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffff00ff, endColorstr=#ffff0000, GradientType=1)";
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffff00ff, endColorstr=#ffff0000, GradientType=1);
}
</style>
<div class="colorPicker">
<div class="colorItem color1"></div>
<div class="colorItem color2"></div>
<div class="colorItem color3"></div>
<div class="colorItem color4"></div>
<div class="colorItem color5"></div>
<div class="colorItem color6"></div>
</div>
|
А Opera с версии 9.5 поддерживает SVG в background-image, который, как Data URI можно записать :)
|
Цитата:
|
Градиент для Opera 9.5+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Градиент (только для Opera 9.5+)</title>
</head>
<body>
<style type="text/css">
.colorPicker {
height: 20px;
width: 300px;
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KDQoJPGRlZnM+DQoJCTxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIHgxPSIwJSIgeTE9IjAlIiB4Mj0iMTAwJSIgeTI9IjAlIj4NCg0KCQkJPHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiKDI1NSwwLDApO3N0b3Atb3BhY2l0eToxIi8+DQoJCQk8c3RvcCBvZmZzZXQ9IjIwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiKDI1NSwyNTUsMCk7c3RvcC1vcGFjaXR5OjEiLz4NCg0KCQkJPHN0b3Agb2Zmc2V0PSIyMCUiIHN0eWxlPSJzdG9wLWNvbG9yOnJnYigyNTUsMjU1LDApO3N0b3Atb3BhY2l0eToxIi8+DQoJCQk8c3RvcCBvZmZzZXQ9IjQwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiKDAsMjU1LDI1NSk7c3RvcC1vcGFjaXR5OjEiLz4NCg0KCQkJPHN0b3Agb2Zmc2V0PSI0MCUiIHN0eWxlPSJzdG9wLWNvbG9yOnJnYigwLDI1NSwyNTUpO3N0b3Atb3BhY2l0eToxIi8+DQoJCQk8c3RvcCBvZmZzZXQ9IjYwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiKDAsMCwyNTUpO3N0b3Atb3BhY2l0eToxIi8+DQoNCgkJCTxzdG9wIG9mZnNldD0iNjAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoMCwwLDI1NSk7c3RvcC1vcGFjaXR5OjEiLz4NCgkJCTxzdG9wIG9mZnNldD0iODAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoMjU1LDAsMjU1KTtzdG9wLW9wYWNpdHk6MSIvPg0KDQoJCQk8c3RvcCBvZmZzZXQ9IjgwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiKDI1NSwwLDI1NSk7c3RvcC1vcGFjaXR5OjEiLz4NCgkJCTxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiKDI1NSwwLDApO3N0b3Atb3BhY2l0eToxIi8+DQoNCgkJPC9saW5lYXJHcmFkaWVudD4NCgk8L2RlZnM+DQoJPHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgc3R5bGU9ImZpbGw6dXJsKCNncmFkaWVudCk7Ii8+DQoNCjwvc3ZnPg0KDQo=) no-repeat;
}
</style>
<div class="colorPicker"></div>
</body>
</html>
SVG-файл <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"> <defs> <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" style="stop-color:rgb(255,0,0);stop-opacity:1"/> <stop offset="20%" style="stop-color:rgb(255,255,0);stop-opacity:1"/> <stop offset="20%" style="stop-color:rgb(255,255,0);stop-opacity:1"/> <stop offset="40%" style="stop-color:rgb(0,255,255);stop-opacity:1"/> <stop offset="40%" style="stop-color:rgb(0,255,255);stop-opacity:1"/> <stop offset="60%" style="stop-color:rgb(0,0,255);stop-opacity:1"/> <stop offset="60%" style="stop-color:rgb(0,0,255);stop-opacity:1"/> <stop offset="80%" style="stop-color:rgb(255,0,255);stop-opacity:1"/> <stop offset="80%" style="stop-color:rgb(255,0,255);stop-opacity:1"/> <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/> </linearGradient> </defs> <rect width="100%" height="100%" style="fill:url(#gradient);"/> </svg>Возможно SVG-файл можно сократить. DataURLMaker (надо только не забыть image/svg+xml в CSS подставить и внутри <style type="opera/css"> не будет работать) |
Ну понятно. В общем вариант с СSS отпадает.
|
Я когда только учил js, делал похожий, только квадратный, к верху он осветлялся, посередине нормальные цвета и к низу затемнялся (как в фотошопе, только высота больше), ради интереса генерировал побольше размером, комп секунд на 20 зависал, потом что-то по ошибке намудрил в коде и выдал он мне какой-то офигительный узор, типа фрактала, я потом специально всяко мудрил там, но ничего столь же интересного так и не вышло :( .
upd: еще там учитывался тот факт, что человеческий глаз воспринимает светлость компонентов (r g b) по-разному, красный везде немного осветлялся, синий еще больше. |
Цитата:
|
| Часовой пояс GMT +3, время: 06:17. |