長針と短針どちらでも直接回せて、長針と短針それぞれ連動して動作する時刻入力ピッカーが欲しかったので自作してみました。
####実動サンプル####
スマホでも操作可能です。
PCではマウスホイールにも対応していますが、ブラウザごとに異なる感度をまだ吸収しきれていませんのでこちらは補助的なものとお考えください。
キーボードでは方向キー左右で1分単位、上下で15分単位の送り戻し、SPACEでAM/PM切替、数値キーでの直接入力ができます。
文字盤の空白部分右半分、左半分をそれぞれクリックすることで1分単位の送り戻しも可能です。
###スクリプト###
"use strict";
{
const
timePickerParam = {
// 主要パーツ デフォルトスタイル
styles: {
// サイズ
width: 200,
height: 200,
// 外枠
frame: {
color: '#f0f0f0', // 背景色
},
// 目盛り
dial: {
color1: '#c0c0c0', // 1分 色
color5: '#808080', // 5分 色
color15: '#808080', // 15分 色
},
// 時針(短針)
hourHand: {
color: '#666666', // 色
length: '0.6', // 長さ(ピッカー半径を1とした相対値)
width: '0.1', // 幅(ピッカー半径を1とした相対値)
offset: '0.05', // 中心からのオフセット
},
// 分針(長針)
minuteHand: {
color: '#888888', // 色
length: '1.0', // 長さ
width: '0.08', // 幅
offset: '0.1', // 中心からのオフセット
},
// closeボタン
closeButton: {
color: '#a0a0a0',
background: '#e0e0e0',
},
// AM/PMボタン
ampmButton: {
display: '', // noneで非表示
onColor: '#000000',
offColor: '#c0c0c0',
},
// 時刻プレビュー
preview: {
display: '', // noneで非表示
color: '#000000',
},
},
// 操作開始後に無操作で非表示となる時間(ms)
timeout: 5000,
// 選択間隔 1~30(分)
step: 1,
// イベント制御ID用オブジェクト
ids: {},
},
tpHandler = (function() {
const events = {};
let key = 1;
return {
add: function(target, type, listener, capture) {
target.addEventListener(type, listener, capture);
events[key] = {
target: target,
type: type,
listener: listener,
capture: capture
};
return key++;
},
remove: function(key) {
if(key in events) {
const e = events[key];
e.target.removeEventListener(e.type, e.listener, e.capture);
delete(events[key]);
}
}
};
}());
function tpSetStyle(width, height, styles) {
if(styles === undefined) styles = {};
const stylesDefault = JSON.parse(JSON.stringify(timePickerParam.styles));
if(width === undefined) width = timePickerParam.styles.width;
if(height === undefined) height = timePickerParam.styles.height;
const sizeMin = Math.min(width, height);
// ピッカー外枠
let d = document.querySelector('#timepicker').style;
let st = stylesDefault.frame;
overRide(st, styles.frame);
d.width = width + 'px';
d.height = height + 'px';
d.background = st.color;
d.position = 'absolute';
d.left = '50px';
d.top = '50px';
d.overflow = 'hidden';
// 目盛り
const cv = document.querySelector('#timepicker #tp_canvas');
cv.width = width;
cv.height = height;
const ctx = cv.getContext('2d');
d = cv.style;
d.position = 'absolute';
st = stylesDefault.dial;
overRide(st, styles.dial);
for(let i = 0; i < 60; i++) {
ctx.beginPath();
ctx.strokeStyle = i % 5 === 0 ?
(i % 15 === 0 ? st.color15 : st.color5) : st.color1;
const r = (Math.PI * 2) / 60 * i;
const c = Math.cos(r);
const s = Math.sin(r);
const sr = (i % 15 === 0) ?
sizeMin / 2 * .8 : (i % 5 === 0) ? sizeMin / 2 * .9 : sizeMin / 2 * .95;
ctx.moveTo(width / 2 + c * sr, height / 2 + s * sr);
ctx.lineTo(width / 2 + c * (sizeMin / 2 * .98), height / 2 + s * (sizeMin / 2 * .98));
ctx.stroke();
}
st = stylesDefault.closeButton;
overRide(st, styles.closeButton);
// クローズボタン X記号
ctx.beginPath();
ctx.fillStyle = st.background;
ctx.fillRect(width - width * 0.12, 0, width * 0.12, width * 0.12);
ctx.strokeStyle = st.color;
ctx.moveTo(width - width * 0.02, width * 0.02);
ctx.lineTo(width - width * 0.1, width * 0.1);
ctx.moveTo(width - width * 0.1, width * 0.02);
ctx.lineTo(width - width * 0.02, width * 0.1);
ctx.stroke();
// closeボタン
d = document.querySelector('#timepicker #tp_close').style;
d.position = 'absolute';
d.right = '0px';
d.top = '0px';
d.width = (width * 0.12) + 'px';
d.height = (width * 0.12) + 'px';
d.cursor = 'pointer';
// 時刻プレビュー
d = document.querySelector('#timepicker #tp_view').style;
st = stylesDefault.preview;
overRide(st, styles.preview);
d.display = st.display;
d.position = 'absolute';
d.left = '2px';
d.bottom = '2px';
d.border = '0';
d.padding = '0';
d.background = 'rgba(0, 0, 0, 0)';
d.color = st.color;
// フォーカス制御用ダミー
d = document.querySelector('#timepicker #tp_dummy').style;
d.position = 'fixed';
d.top = '-100px';
if(timePickerParam.touchFlg) document.querySelector('#timepicker #tp_dummy').type = 'checkbox';
// 時針
d = document.querySelector('#timepicker #tp_hour').style;
st = stylesDefault.hourHand;
overRide(st, styles.hourHand);
d.background = st.color;
d.width = (sizeMin / 2 * st.length) + 'px';
d.height = (sizeMin / 2 * st.width) + 'px';
d.cursor = 'pointer';
d.position = 'absolute';
d.left = -(sizeMin / 2 * st.offset) + 'px';
d.top = -(sizeMin / 2 * st.width / 2) + 'px';
// 時針クリック補助
d = document.querySelector('#timepicker #tp_hourMargin').style;
d.width = (sizeMin / 2 * .5) + 'px';
d.height = (sizeMin / 2 * .4) + 'px';
d.cursor = 'pointer';
d.position = 'absolute';
d.left = (sizeMin / 2 * .15) + 'px';
d.top = -(sizeMin / 2 * .2) + 'px';
// 時針回転制御用親要素
d = document.querySelector('#timepicker #tp_hourParent').style;
d.position = 'absolute';
d.width = '0px';
d.height = '0px';
d.left = '50%';
d.top = '50%';
d.transform = 'rotate(270deg)';
d.zIndex = '10';
// 分針
d = document.querySelector('#timepicker #tp_minute').style;
st = stylesDefault.minuteHand;
overRide(st, styles.minuteHand);
d.background = st.color;
d.width = (sizeMin / 2 * st.length) + 'px';
d.height = (sizeMin / 2 * st.width) + 'px';
d.cursor = 'pointer';
d.position = 'absolute';
d.left = -(sizeMin / 2 * st.offset) + 'px';
d.top = -(sizeMin / 2 * st.width / 2) + 'px';
// 分針クリック補助
d = document.querySelector('#timepicker #tp_minuteMargin').style;
d.width = (sizeMin / 2 * 0.8) + 'px';
d.height = (sizeMin / 2 * .4) + 'px';
d.cursor = 'pointer';
d.position = 'absolute';
d.left = (sizeMin / 2 * .2) + 'px';
d.top = -(sizeMin / 2 * .2) + 'px';
// 分針回転制御用親要素
d = document.querySelector('#timepicker #tp_minuteParent').style;
d.position = 'absolute';
d.width = '0px';
d.height= '0px';
d.left = '50%';
d.top = '50%';
d.transform = 'rotate(270deg)';
d.zIndex = '11';
// AM/PMボタン親
d = document.querySelector('#timepicker #tp_ampmParent').style;
st = stylesDefault.ampmButton;
overRide(st, styles.ampmButton);
d.display = st.display;
d.position = 'absolute';
d.right = '0px';
d.bottom = '0px';
// AM/PMボタン
for(let i = 0; i < 2; i++) {
d = document.querySelector('#timepicker #tp_' + ['am', 'pm'][i]).style;
d.position = 'relative';
d.padding = '0';
d.border = '0';
d.cursor = 'pointer';
d.background = 'rgba(0, 0, 0, 0)';
}
timePickerParam.ampmOnColor = st.onColor;
timePickerParam.ampmOffColor = st.offColor;
// ステップ送り戻し(文字盤空白部分 左右半分ずつ)
for(let i = 0; i < 2; i++) {
d = document.querySelector('#timepicker #tp_' + ['left', 'right'][i] + 'Adjust').style;
d.position = 'absolute';
d.width = '50%';
d.height = '100%';
d[['left', 'right'][i]] = '0px';
}
timePickerParam.timeout_ = timePickerParam.timeout;
if(styles.timeout !== undefined) {
let t = parseInt(styles.timeout);
if(t <= 0) t = 36e5;
timePickerParam.timeout_ = t;
}
timePickerParam.step_ = timePickerParam.step;
if(styles.step !== undefined) {
timePickerParam.step_ = styles.step;
}
if(timePickerParam.step_ < 1) timePickerParam.step_ = 1;
else if(timePickerParam.step_ > 30) timePickerParam.step_ = 30;
timePickerParam.step_ = Math.floor(timePickerParam.step_);
function overRide(t, f) {
if(f === undefined) return;
for(let i in f) t[i] = f[i];
}
}
window.addEventListener('load', function() {
const html =
"<div id='timepicker'>" +
" <canvas id='tp_canvas' width='" + timePickerParam.styles.width +
"' height='" + timePickerParam.styles.height + "'></canvas>" +
" <input type='button' id='tp_view' value='00:00'>" +
" <input type='text' id='tp_dummy'>" +
" <div id='tp_leftAdjust'></div>" +
" <div id='tp_rightAdjust'></div>" +
" <div id='tp_minuteParent'>" +
" <div id='tp_minuteMargin'></div>" +
" <div id='tp_minute'></div>" +
" </div>" +
" <div id='tp_hourParent'>" +
" <div id='tp_hourMargin'></div>" +
" <div id='tp_hour'></div>" +
" </div>" +
" <div id='tp_close'></div>" +
" <div id='tp_ampmParent'>" +
" <input type='button' id='tp_am' class='tp_ampm' value='AM'>" +
" <input type='button' id='tp_pm' class='tp_ampm' value='PM'>" +
" </div>" +
"</div>";
document.querySelector('body').insertAdjacentHTML('beforeend', html);
tpSetStyle();
document.querySelector('#timepicker').style.display = 'none';
timePickerParam.touchFlg = window.ontouchstart !== undefined ? true : false;
let x, y;
let r, r_;
timePickerParam.n = 0;
timePickerParam.pm = 0;
let hourFlg = false;
let minuteFlg = false;
// 時針クリック
document.querySelector('#timepicker #tp_hour').addEventListener(timePickerParam.touchFlg ? 'touchstart' : 'mousedown', function(e) {
selectHour();
});
document.querySelector('#timepicker #tp_hourMargin').addEventListener(timePickerParam.touchFlg ? 'touchstart' : 'mousedown', function(e) {
selectHour();
});
function selectHour() {
if(!hourFlg) {
hourFlg = true;
if(timePickerParam.touchFlg) tpAddHandler();
const parent = document.querySelector('#timepicker #tp_hourParent');
r_ = r = (parseInt(parent.style.transform.replace(/^[^\d-]+/g, '')) + 450 ) % 360;
setTimeout(function(){ document.querySelector('#timepicker #tp_dummy').focus();}, 10);
}
}
// 分針クリック
document.querySelector('#timepicker #tp_minute').addEventListener(timePickerParam.touchFlg ? 'touchstart' : 'mousedown', function(e) {
selectMinute();
});
document.querySelector('#timepicker #tp_minuteMargin').addEventListener(timePickerParam.touchFlg ? 'touchstart' : 'mousedown', function(e) {
selectMinute();
});
function selectMinute() {
if(!minuteFlg) {
minuteFlg = true;
if(timePickerParam.touchFlg) tpAddHandler();
const parent = document.querySelector('#timepicker #tp_minuteParent');
r_ = r = (parseInt(parent.style.transform.replace(/^[^\d-]+/g, '')) + 450 ) % 360;
setTimeout(function(){ document.querySelector('#timepicker #tp_dummy').focus();}, 10);
}
}
// 針ドラッグ
window.addEventListener(timePickerParam.touchFlg ? 'touchmove' : 'mousemove', function(e) {
let n = timePickerParam.n;
let pm = n >= 720 ? 1 : 0;
const tp = document.querySelector('#timepicker');
if(hourFlg || minuteFlg) {
const parent = document.querySelector(hourFlg ? '#timepicker #tp_hourParent' : '#timepicker #tp_minuteParent');
const ex = timePickerParam.touchFlg ? e.touches[0].clientX : e.clientX;
const ey = timePickerParam.touchFlg ? e.touches[0].clientY : e.clientY;
x = ex - (tp.offsetLeft - window.pageXOffset) - (tp.clientWidth / 2);
y = ey - (tp.offsetTop - window.pageYOffset) - (tp.clientHeight / 2);
const at = Math.atan2(y, x);
const k = minuteFlg ?
Math.floor(((at * (360 / (Math.PI * 2))) % 360) / 6) * 6:
(at * (360 / (Math.PI * 2))) % 360;
parent.style.transform = 'rotate(' + k + 'deg)';
if(minuteFlg) {
let p = 6 * timePickerParam.step_;
if(p >= 180) p = 90;
r = (Math.round(Math.floor((k + 450) % 360) / p) * p) % 360;
n = Math.floor(n / 60) * 60 + (r / 6);
if(Math.abs(r - r_) > 180) n -= (360 * (r - r_ > 0 ? 1 : -1)) / 6;
r_ = r;
}
if(hourFlg) {
r = (k + 450) % 360;
if(Math.abs(r - r_) > 300) pm ^= 1;
n = r * 2 + pm * 720;
r_ = r;
n = Math.floor((n + 1440) % 1440);
}
timePickerParam.n = n;
timePickerParam.pm = pm;
tpUpdatePicker();
timeoutUpdate();
}
});
// マウスホイール
window.addEventListener('wheel', function(e) {
if(!timePickerParam.ids['wheel']) return;
const delta = e.wheelDelta !== undefined ? e.deltaY / 40 : e.deltaY / 20;
let n = timePickerParam.n + delta / 4;
timePickerParam.n = Math.round(n);
tpUpdatePicker();
timeoutUpdate();
});
function timeoutUpdate() {
if(timePickerParam.ids['timeout']) {
clearTimeout(timePickerParam.ids['timeout']);
timePickerParam.ids['timeout'] = 0;
}
if(!timePickerParam.ids['timeout']) {
timePickerParam.ids['timeout'] = setTimeout(function() {
document.querySelector('#timepicker').style.display = 'none';
tpRemoveHandler();
}, timePickerParam.timeout_);
}
}
// 針リリース
window.addEventListener(timePickerParam.touchFlg ? 'touchend' : 'mouseup', function() {
if(hourFlg) {
hourFlg = false;
}
if(minuteFlg) {
minuteFlg = false;
}
if(document.querySelector('#timepicker').style.display !== 'none')
document.querySelector('#timepicker #tp_dummy').focus();
if(timePickerParam.touchFlg) tpRemoveHandler();
});
// closeボタン
document.querySelector('#tp_close').addEventListener('click', function() {
document.querySelector('#timepicker').style.display = 'none';
tpRemoveHandler();
});
// AM/PMボタン
document.querySelector('#tp_am').addEventListener('click', function() {
toggleAmpm();
});
document.querySelector('#tp_pm').addEventListener('click', function() {
toggleAmpm();
});
function toggleAmpm() {
timePickerParam.n = (timePickerParam.n + 720) % 1440;
timePickerParam.pm = timePickerParam.n >= 720 ? 1 : 0;
tpPrintTime(timePickerParam.n);
tpSetAmpmAttribute(timePickerParam.pm);
tpUpdatePicker();
timeoutUpdate();
}
// キーボード
window.addEventListener('keydown', function() {
if(document.querySelector('#timepicker').style.display === 'none') return;
const kcode = event.keyCode;
let incremental = 0;
// 左
if (kcode === 37) incremental = -timePickerParam.step_;
// 右
else if (kcode === 39) incremental = timePickerParam.step_;
// 上
else if (kcode === 38) incremental = timePickerParam.step_ < 15 ? 15 : timePickerParam.step_;
// 下
else if (kcode === 40) incremental = timePickerParam.step_ < 15 ? -15 : -timePickerParam.step_;
// space
else if (kcode === 32) incremental = 720;
// enter
else if (kcode === 13) {
document.querySelector('#timepicker').style.display = 'none';
tpRemoveHandler();
}
// esc
else if (kcode === 27) {
document.querySelector('#timepicker').style.display = 'none';
timePickerParam.o.value = timePickerParam.ev;
tpRemoveHandler();
}
// 0~9
else if(kcode >= 48 && kcode <= 57 || kcode >= 96 && kcode <= 105) {
if(timePickerParam.numKeyInTime === undefined || Date.now() - timePickerParam.numKeyInTime > 2000) timePickerParam.time = '0000';
timePickerParam.numKeyInTime = Date.now();
const tmp = (timePickerParam.time + String(kcode - (kcode >= 96 ? 96 : 48))).slice(-4);
let h = Number(tmp.slice(0,2)), m = Number(tmp.slice(-2));
timePickerParam.time = tmp;
if(h <= 24 && h >= 0 && m < 60 && m >= 0) {
h %= 24;
timePickerParam.n = h * 60 + m;
tpUpdatePicker();
}
timeoutUpdate();
}
if(incremental) {
timePickerParam.n = (timePickerParam.n + 1440 + incremental) % 1440;
if((kcode === 38 || kcode === 40))
timePickerParam.n = Math.floor(timePickerParam.n / incremental) * incremental;
tpUpdatePicker();
timeoutUpdate();
}
});
document.querySelector('#timepicker #tp_leftAdjust')
.addEventListener(timePickerParam.touchFlg ? 'touchstart' : 'mousedown', function() {
timePickerParam.n -= timePickerParam.step_;
tpUpdatePicker();
timeoutUpdate();
});
document.querySelector('#timepicker #tp_rightAdjust')
.addEventListener(timePickerParam.touchFlg ? 'touchstart' : 'mousedown', function() {
timePickerParam.n += timePickerParam.step_;
tpUpdatePicker();
timeoutUpdate();
});
// dataset(data-timepicker)指定のinput要素にclickイベントを追加
const inputElements = document.querySelectorAll('input');
for(let i = 0; i < inputElements.length; i++) {
const dataset = inputElements[i].dataset.timepicker;
if(dataset === undefined) continue;
const params = dataset.split(';');
let width = timePickerParam.styles.width;
let height = timePickerParam.styles.height;
for(let l = 0; l < params.length; l++) {
const param = params[l].split(':');
if(param[0].trim().toLowerCase() === 'width')
width = Math.abs(parseInt(param[1]));
else if(param[0].trim().toLowerCase() === 'height')
height = Math.abs(parseInt(param[1]));
}
inputElements[i].addEventListener('click', function() {
timepicker(this, width, height);
});
}
}, false);
function tpUpdatePicker() {
timePickerParam.n = (timePickerParam.n + 1440) % 1440;
timePickerParam.n_ = timePickerParam.n;
const step = timePickerParam.step_;
timePickerParam.n_ = Math.round(timePickerParam.n_ / step) * step;
timePickerParam.n_ = (timePickerParam.n_ + 1440) % 1440;
timePickerParam.pm = timePickerParam.n_ >= 720 ? 1 : 0;
tpPrintTime(timePickerParam.n_);
tpSetAmpmAttribute(timePickerParam.pm);
document.querySelector('#timepicker #tp_minuteParent').style.transform =
'rotate(' + (timePickerParam.n_ * 6 - 90) + 'deg)';
document.querySelector('#timepicker #tp_hourParent').style.transform =
'rotate(' + (timePickerParam.n_ / 2 - 90) + 'deg)';
}
function tpPrintTime(n) {
const hour = ('0' + Math.floor(n / 60)).slice(-2);
const minute = ('0' + (n % 60)).slice(-2);
document.querySelector('#timepicker #tp_view').value = hour + ':' + minute;
timePickerParam.o.value = hour + ':' + minute;
}
function tpRemoveHandler() {
if(timePickerParam.ids['touchmove'] > 0) {
tpHandler.remove(timePickerParam.ids['touchmove']);
timePickerParam.ids['touchmove'] = 0;
}
if(timePickerParam.ids['wheel'] > 0) {
tpHandler.remove(timePickerParam.ids['wheel']);
timePickerParam.ids['wheel'] = 0;
}
}
function tpAddHandler() {
timePickerParam.ids['touchmove'] = tpHandler.add(window, 'touchmove', function(e) {
e.preventDefault();
}, { passive: false });
timePickerParam.ids['wheel'] = tpHandler.add(window, 'wheel', function(e) {
e.preventDefault();
}, { passive: false });
}
function tpSetAmpmAttribute(f) {
if(f === undefined) f = timePickerParam.pm;
const am = document.querySelector('#timepicker #tp_am').style;
const pm = document.querySelector('#timepicker #tp_pm').style;
am.color = timePickerParam[f ? 'ampmOffColor' : 'ampmOnColor' ];
pm.color = timePickerParam[f ? 'ampmOnColor' : 'ampmOffColor'];
}
window.timepicker = function(e, width, height) {
let styles = {};
if(typeof(width) === 'object') {
styles = width;
width = styles.width !== undefined ? styles.width : undefined;
height = styles.height !== undefined ? styles.height : undefined;
}
if(width === undefined) width = timePickerParam.styles.width;
if(height === undefined) height = timePickerParam.styles.height;
tpSetStyle(width, height, styles);
const picker = document.querySelector('#timepicker');
if(picker.style.display !== 'none' && timePickerParam.o === e) {
picker.style.display = 'none';
tpRemoveHandler();
return;
}
picker.style.left = (e.offsetLeft) + 'px';
picker.style.top = (4 + e.offsetTop + e.clientHeight) + 'px';
const bw = document.querySelector('body').clientWidth;
if(e.offsetLeft + width > bw) picker.style.left = (bw - width) + 'px';
timePickerParam.ev = e.value;
e.value = e.value.replace(/^(\d{1,2})(\d\d)$/, "$1:$2");
const d = new Date('Thu Jan 01 1970 ' + (!e.value ? '_' : e.value) + ':00');
const now = new Date();
const t = isNaN(d.getHours()) ?
now.getHours() * 60 + now.getMinutes() : d.getHours() * 60 + d.getMinutes();
picker.querySelector('#tp_view').value = isNaN(d.getHours()) ?
('0' + now.getHours()).slice(-2) + ':' + ('0' + now.getMinutes()).slice(-2) :
('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2);
timePickerParam.time = picker.querySelector('#tp_view').value.replace(':', '');
timePickerParam.n = Math.round(t / timePickerParam.step_) * timePickerParam.step_;
timePickerParam.o = e;
tpUpdatePicker();
picker.style.display = 'block';
document.querySelector('#timepicker #tp_dummy').focus();
tpRemoveHandler();
if(!timePickerParam.touchFlg) tpAddHandler();
if(timePickerParam.ids['timeout']) {
clearTimeout(timePickerParam.ids['timeout']);
timePickerParam.ids['timeout'] = 0;
}
}
}
###設定例###
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='user-scalable=no,width=device-width,initial-scale=1'>
<script src='./timepicker.js'></script>
</head>
<body>
<div style='height:80px;'> </div>
<!-- onclick='timepicker(this)'で指定 -->
<input type='text' value='10:10' onclick='timepicker(this)'>
<input type='text' value='18:00' onclick='timepicker(this)'>
<input type='text' onclick='timepicker(this)'>
<!-- type='text' 以外でも可 -->
<input type='time' onclick='timepicker(this, 150, 150)'>
<input type='button' value='00:00' onclick='timepicker(this, 150, 150)'>
<div style='height:20px;'> </div>
<!-- dataset(data-timepicker)で指定 -->
<input type='text' data-timepicker=''><!-- 空文字の場合はデフォルトサイズ -->
<input type='text' data-timepicker='width:300; height:300'><!-- widthとheightが指定可能 -->
<input type='text' data-timepicker='width:300'><!-- どちらか片方でも可 -->
<input type='text' data-timepicker='height:300'>
<div style='height:20px;'> </div>
<p>
オブジェクトで装飾パラメータを渡すサンプル<br>
<script>
const options = {
width: 150,
height: 150,
frame: {
color: 'rgba(240, 255, 255, 0.5)',
},
dial: {
color1: 'rgba(0,0,0,0)',
color5: '#c0c0ff',
color15: '#8080ff',
},
hourHand: {
color: '#8888cc',
length: '0.3',
width: '0.05',
offset: '-0.1',
},
minuteHand: {
color: '#8888cc',
length: '0.5',
width: '0.015',
offset: '-0.4',
},
closeButton: {
color: '#8080ff',
background: 'transparent',
},
ampmButton: {
onColor: '#8080ff',
offColor: '#e0e0ff',
},
preview: {
color: '#8080ff',
},
};
</script>
<input type='text' onclick='timepicker(this, options)'>
<input type='text' onclick='timepicker(this, {frame:{color:"#aca"}, minuteHand:{color:"white"}, hourHand:{color:"white"}, ampmButton:{display:"none"}, preview:{display:"none"}, closeButton:{color:"white", background:"#bdb"} })'>
<input type='text' onclick='timepicker(this, {frame:{color:"black"}, dial:{color1:"#0f0",color5:"#0f0", color15:"#0f0"}, minuteHand:{color:"white", length:"0.9", width:"0.02", offset:"0"}, hourHand:{color:"white", width:"0.02", offset:"0"}, ampmButton:{display:"none"}, preview:{display:"none"}, closeButton:{color:"white", background:"black"} })'>
</p>
<div style='height:800px;'> </div>
</body>
</html>
timepicker.jsを読み込み、対応させたいinput要素にonclick='timepicker(this)'
またはdata-timepicker
を追記することで適用できます。
<script src='./timepicker.js'></script>
<input type='text' onclick='timepicker(this)'>
<input type='text' data-timepicker>
タイムピッカーのサイズはスクリプト内で設定されているサイズ(200x200ピクセル)がデフォルトになりますが、onclick='timepicker(this, 150, 150)'
やdata-timepicker='width:150; height:150'
のように個別にサイズ指定もできます。
<input type='text' onclick='timepicker(this, 150, 150)'>
<input type='text' data-timepicker='width:150; height:150'>
onclickで指定する場合はオブジェクトで装飾オプションを渡すこともできます。
<input type='text' onclick='timepicker(this, {width:150, height:150, frame:{color:"#000000"}, minuteHand:{color:"#ffffff"}, hourHand:{color:"#ffffff"}, ampmButton:{onColor:"#ffffff", offColor:"#888888"}, closeButton:{color:"#ffffff", background:"transparent"} })'>
適用させたinput要素をクリックするとピッカーを表示、対象input要素をもう一度クリックするかピッカーのクローズボタンをクリック、または操作後一定時間(デフォルト5秒)無操作で消えます。