カラーピッカースライダー
赤、緑、青の各スライダー操作で色をプレビューできるカラーピッカースライダーを実装する方法をご紹介します。
デモ
サンプルコード
HTML
<div class="color-picker-slider">
<dl>
<dt>RED</dt>
<dd>
<div class="slider">
<div class="slider-fill slider-fill-red"></div>
<button class="handle slider-handle-red"></button>
</div>
<input name="red" value="0" maxlength="3" readonly>
</dd>
<dt>GREEN</dt>
<dd>
<div class="slider">
<div class="slider-fill slider-fill-green"></div>
<button class="handle slider-handle-green"></button>
</div>
<input name="green" value="0" maxlength="3" readonly>
</dd>
<dt>BLUE</dt>
<dd>
<div class="slider">
<div class="slider-fill slider-fill-blue"></div>
<button class="handle slider-handle-blue"></button>
</div>
<input name="blue" value="0" maxlength="3" readonly>
</dd>
</dl>
<div class="preview"></div>
</div>
CSS
.color-picker-slider {
overflow:hidden;
width:512px;
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
.color-picker-slider dl {
overflow:hidden;
float:left;
margin:0;
width:401px;
}
.color-picker-slider dl dt {
float:left;
margin-top:10px;
width:54px;
font-size:14px;
}
.color-picker-slider dl dd ~ dt {
margin-top:15px;
}
.color-picker-slider dl dd {
overflow:hidden;
float:left;
margin-left:5px;
}
.color-picker-slider dl dd ~ dd {
margin-top:5px;
}
/* スライダー */
.color-picker-slider dl dd .slider {
position:relative;
float:left;
margin-top:12px;
border:2px inset #f5f5f5;
width:261px;
height:6px;
background-color:#f5f5f5;
}
.color-picker-slider dl dd .slider .slider-fill {
width:0;
height:100%;
}
.color-picker-slider dl dd .slider .slider-fill-red {
background-color:#f00;
}
.color-picker-slider dl dd .slider .slider-fill-green {
background-color:#0f0;
}
.color-picker-slider dl dd .slider .slider-fill-blue {
background-color:#00f;
}
/* ハンドル */
.color-picker-slider dl dd .slider .handle {
position:absolute;
top:-7px;
left:-2px;
border:2px outset #333;
padding:0;
width:10px;
height:20px;
background-color:#333;
cursor:pointer;
}
.color-picker-slider dl dd .slider .handle:focus {
background-color:#555;
}
.color-picker-slider dl dd .slider .handle::-moz-focus-inner {
border:none;
padding:0;
}
/* 値 */
.color-picker-slider dl dd input {
float:left;
margin-left:5px;
border:3px inset #f5f5f5;
padding:5px 8px;
width:50px;
height:16px;
background:#f5f5f5;
font-size:14px;
text-align:center;
}
.color-picker-slider dl dd input:focus {
background-color:#fafafa;
}
/* プレビュー */
.color-picker-slider .preview {
float:left;
margin-left:5px;
width:106px;
height:106px;
background-color:#000;
}
JavaScript
(function() {
// IE8以下でdocument.getElementsByClassNameが使えないためのポリフィル
if (!document.getElementsByClassName) {
document.getElementsByClassName = function(className) {
var elems = document.getElementsByTagName('*'),
results = [];
for (var i = 0, len = elems.length; i > len; i++) {
if ((' ' + elems[i].className + ' ').indexOf(' ' + className + ' ') > -1) {
results.push(elems[i]);
}
}
return results;
};
}
window.onload = function() {
var sliderFillRedElem = document.getElementsByClassName('slider-fill-red')[0],
sliderFillGreenElem = document.getElementsByClassName('slider-fill-green')[0],
sliderFillBlueElem = document.getElementsByClassName('slider-fill-blue')[0],
sliderHandleRedElem = document.getElementsByClassName('slider-handle-red')[0],
sliderHandleGreenElem = document.getElementsByClassName('slider-handle-green')[0],
sliderHandleBlueElem = document.getElementsByClassName('slider-handle-blue')[0],
redFieldElem = document.getElementsByName('red')[0],
greenFieldElem = document.getElementsByName('green')[0],
blueFieldElem = document.getElementsByName('blue')[0],
previewElem = document.getElementsByClassName('preview')[0];
sliderHandleRedElem.setAttribute('data-key', 'red');
sliderHandleGreenElem.setAttribute('data-key', 'green');
sliderHandleBlueElem.setAttribute('data-key', 'blue');
redFieldElem.value = 0;
greenFieldElem.value = 0;
blueFieldElem.value = 0;
sliderHandleRedElem.left = '';
sliderHandleGreenElem.left = '';
sliderHandleBlueElem.left = '';
var itemElem, endX;
/**
* ドラッグ中かどうか
*/
var isDragging = false;
/**
* ハンドルがフォーカス中かどうか
*/
var isFocus = false;
/**
* スライダー開始ハンドラー
*/
var startDragHandle = function() {
isDragging = true;
};
/**
* フォーカスハンドラー
* @param {Object} イベントのオブジェクト
*/
var focusHandle = function(ev) {
var evt = ev || event;
isFocus = true;
itemElem = evt.target || evt.srcElement;
endX = itemElem.parentNode.offsetWidth - itemElem.offsetWidth;
};
/**
* フィールド要素フォーカスハンドラー
* @param {Object} イベントのオブジェクト
*/
var fieldFocusHandle = function(targetItemElem) {
itemElem = targetItemElem;
endX = itemElem.parentNode.offsetWidth - itemElem.offsetWidth;
};
/**
* フォーカス離脱ハンドラー
*/
var blurHandle = function() {
isFocus = false;
itemElem = null;
};
/**
* フィールド要素を取得
*/
var getFieldElem = function() {
if (itemElem.getAttribute('data-key') === 'red') {
return redFieldElem;
} else if (itemElem.getAttribute('data-key') === 'green') {
return greenFieldElem;
} else {
return blueFieldElem;
}
};
/**
* 塗りつぶし要素を取得
*/
var getFillElem = function() {
if (itemElem.getAttribute('data-key') === 'red') {
return sliderFillRedElem;
} else if (itemElem.getAttribute('data-key') === 'green') {
return sliderFillGreenElem;
} else {
return sliderFillBlueElem;
}
};
/**
* スライダーの描画(値と位置)を更新
* @param {Number} ratio 現在位置の比率(0.00~1.00)
*/
var updateRenderSlider = function(ratio) {
getFieldElem().value = Math.round(ratio * 255);
getFillElem().style.width = Math.round(ratio * 100) + '%';
};
/**
* ハンドルの位置を更新
* @param {Number} posX 設定する位置
*/
var updateRenderHandlePosition = function(posX) {
itemElem.style.left = (posX - 2) + 'px';
};
/**
* プレビューに色を反映
*/
var updatePreviewColor = function() {
var red = Number(redFieldElem.value).toString(16),
green = Number(greenFieldElem.value).toString(16),
blue = Number(blueFieldElem.value).toString(16);
if (red.length === 1) red = '0' + red;
if (green.length === 1) green = '0' + green;
if (blue.length === 1) blue = '0' + blue;
previewElem.style.backgroundColor = '#' + red + green + blue;
};
// スライダー開始イベント
sliderHandleRedElem.onmousedown = startDragHandle;
sliderHandleGreenElem.onmousedown = startDragHandle;
sliderHandleBlueElem.onmousedown = startDragHandle;
// ハンドル要素フォーカスイベント
sliderHandleRedElem.onfocus = focusHandle;
sliderHandleGreenElem.onfocus = focusHandle;
sliderHandleBlueElem.onfocus = focusHandle;
redFieldElem.onfocus = function() {
fieldFocusHandle(sliderHandleRedElem);
};
greenFieldElem.onfocus = function() {
fieldFocusHandle(sliderHandleGreenElem);
};
blueFieldElem.onfocus = function() {
fieldFocusHandle(sliderHandleBlueElem);
};
// ドラッグ中イベント
document.onmousemove = function(ev) {
if (!isDragging || !isFocus) return;
var itemX = (ev || event).clientX - itemElem.parentNode.getBoundingClientRect().left;
if (itemX < 0) itemX = 0;
if (itemX > endX) itemX = endX;
updateRenderSlider(itemX / endX);
updateRenderHandlePosition(itemX);
updatePreviewColor();
};
// 矢印キーによるスライド中イベント
document.onkeydown = function(ev) {
if (!isFocus) return;
var evt = ev || event,
keyCode = evt.keyCode || evt.which || -1;
if (keyCode !== 37 && keyCode !== 39) return;
var color = Number(getFieldElem().value),
isChange = false;
if (keyCode === 37 && color > 0) {
color--;
isChange = true;
} else if (keyCode === 39 && color < 255) {
color++;
isChange = true;
}
if (!isChange) return;
var ratio = color / 255;
updateRenderSlider(ratio);
updateRenderHandlePosition(Math.round(ratio * endX));
updatePreviewColor();
};
var fieldHandler = function(ev) {
var evt = ev || event,
keyCode = evt.keyCode || evt.which || -1;
if (keyCode !== 38 && keyCode !== 40) return;
var color = Number((evt.target || evt.srcElement).value),
isChange = false;
if (keyCode === 40 && color > 0) {
color--;
isChange = true;
} else if (keyCode === 38 && color < 255) {
color++;
isChange = true;
}
if (!isChange) return;
var ratio = color / 255;
updateRenderSlider(ratio);
updateRenderHandlePosition(Math.round(ratio * endX));
updatePreviewColor();
};
// 矢印キーによる入力イベント
redFieldElem.onkeydown = fieldHandler;
greenFieldElem.onkeydown = fieldHandler;
blueFieldElem.onkeydown = fieldHandler;
// ドラッグ終了イベント
document.onmouseup = function() {
isDragging = false;
};
// ハンドル要素フォーカス離脱イベント
sliderHandleRedElem.onblur = blurHandle;
sliderHandleGreenElem.onblur = blurHandle;
sliderHandleBlueElem.onblur = blurHandle;
// フィールド要素フォーカス離脱イベント
redFieldElem.onblur = function() { itemElem = null; };
greenFieldElem.onblur = function() { itemElem = null; };
blueFieldElem.onblur = function() { itemElem = null; };
};
})();