HTMLでもレンジスライダー用のタグが数年前から使えるようになりましたね。
しかし、ブラウザで見た目がマチマチだし値は1パーツに一個しか付与できず、とても使い勝手が悪いです。レンジスライダー(つまみのある範囲の選べるフォーム)のJSライブラリ・noUiSliderの使い方についてメモしました。noUiSliderはつまみを2個以上実装したい時に便利です。
導入の仕方やレンジスライダーを使った動的フォームの実装方法などのコードサンプルを中心に詳しく解説します。
かみーゆ/フロントエンドエンジニア
- JavaScript の基礎は分かる
- レンジスライダーを実装したい
- 2個以上の値をレンジで実装する必要がある
- 範囲内で直感的に使えるフォームを実装したい
- jQueryを使いたくない
レンジスライダーとは?
レンジスライダーとは範囲(レンジ)内で値を選択できるフォームの一種です。
HTMLでもレンジスライダーのフォームパーツはあります。
<input type="range" min="0" max="100">
が、ご覧の通り、見た目がマチマチです。
今回はサクッとJavaScriptのライブラリで解決します。
noUiSlider 導入方法
早速、noUiSliderの導入方法をご紹介します。
noUiSlider はよくjQueryと紹介されてますが、実際にはjQueryなしで実装可能です。
基本の導入方法
もっとも簡単な noUiSlider 導入方法は JavaScript とCSSのソースを読み込む方法です。ソースは GitHub にありますが、今回はお気軽にCDNを読み込む方法をご紹介します。
※ オプション について解説はこの記事の一番最後にまとめています。
<!-- css -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.6.1/nouislider.css">
<!-- js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.6.1/nouislider.min.js"></script>
<div class="range-wrapper">
<div id="range"></div>
</div>
#range {
height: 10px;
}
.range-wrapper {
width: 800px;
margin: 0 auto;
padding: 50px;
}
const range = document.getElementById('range');
noUiSlider.create(range, {
range: {
'min': 0,
'max': 10
},
step: 1,
start: [2, 4],
connect: true,
behaviour: 'tap-drag',
pips: {
mode: 'steps',
stepped: true,
density: 10
}
});
オプションのpips
でメモリと数字が表示されます。
小数点をつけたくない場合は pips
の詳細オプションを density
を 10
にします。
※ オプション について解説はこの記事の一番最後にまとめています。
コードサンプル noUiSlider Basic | CodePen
上のスクショのように、ツールチップ(つまみの上の数字)を表示したい時は、オプション tooltips
を true
にします。
const rangeSlider = document.getElementById('values-slider');
noUiSlider.create(range, {
range: {
'min': 0,
'max': 10
},
step: 1,
start: [2, 4],
connect: true,
behaviour: 'tap-drag',
tooltips: true,
pips: {
mode: 'steps',
stepped: true,
density: 10,
}
});
※ オプション について解説はこの記事の一番最後にまとめています。
const rangeSlider = document.getElementById('range');
const valuesForSlider = [0,1,2,3,4, 5,6,7,8,9,10]
const format = {
to: function(value) {
return valuesForSlider[Math.round(value)];
},
from: function (value) {
return valuesForSlider.indexOf(Number(value));
}
};
noUiSlider.create(rangeSlider, {
start: [4, 8],
range: { min: 0, max: valuesForSlider.length - 1 },
step: 1,
connect: true,
tooltips: true,
format: format,
behaviour: 'tap-drag',
pips: {
mode: 'steps',
stepped: true,
density: 10,
format: format,
}
});
コードサンプル noUiSlider Tooltip | CodePen
Events:動的に値やオプションなどを変更する
noUiSliderでは、スライダーの変化やオプションの書き換えなどができるメソッドが用意されています。
スライダーが更新されたら、フォームの値を変更
noUiSliderのイベントを利用して、スライダーの変化を受け取ることができます。
noUiSlider.on()
メソッドを使って、フォームの値をリアルタイムでレンダリングさせます。
<div class="range-wrapper">
<div class="range-num">
<input type="number" min="0" max="10" id="num-min" step="1" value="5" readonly> ~
<input type="number" min="0" max="10" id="num-max" step="1" value="8" readonly>
</div>
<div id="range"></div>
</div>
#range {
height: 10px;
}
.range-wrapper {
width: 800px;
margin: 0 auto;
padding: 50px;
}
.range-num {
margin-bottom: 40px;
}
.range-num input{
border: 2px solid #ccc;
height: 32px;
padding-left: 5px;
width: 50px;
font-size: 16px;
}
const range = document.getElementById('range');
const min = document.getElementById('num-min');
const max = document.getElementById('num-max');
noUiSlider.create(range, {
range: {
'min': 0,
'max': 10
},
step: 1,
start: [min.value, max.value],
connect: true,
behaviour: 'tap-drag',
pips: {
mode: 'steps',
stepped: true,
density: 10
}
});
range.noUiSlider.on('update', function( values, handle ) {
min.value = Math.trunc(values[0])
max.value = Math.trunc(values[1])
})
セットできるイベントは
‘start’、‘slide’、‘drag’、‘update’、‘change’、‘set’、‘end’ の7つです。
最大値、最小値の場合値自体を表示しない処理も可能です。分かりづらいので値がない場合の placeholder
属性を追加します。
<input type="number" min="0" max="10" id="num-min" step="1" value="5" readonly placeholder="最大値"> ~
<input type="number" min="0" max="10" id="num-max" step="1" value="8" readonly placeholder="最大値">
range.noUiSlider.on('update', function( values, handle ) {
min.value = Math.trunc(values[0]) === 0 ? '' : Math.trunc(values[0])
max.value = Math.trunc(values[1]) === 10 ? '' : Math.trunc(values[1])
})
コードサンプル noUiSlider Update | CodePen
オプションを変更する
noUiSlider では、オプションの変更もあとから可能です。
たとえば、チェックボックスの値が変更されたタイミングでレンジの最大値を変え るなども可能です。
<div class="range-wrapper">
<div class="range-num">
<label><input type="radio" name="gender" value="male" checked>男性</label>
<label><input type="radio" name="gender" value="female">女性</label>
</div>
<div id="range"></div>
</div>
const valuesSlider = document.getElementById('values-slider');
const genders = document.querySelectorAll('input[name=gender]');
noUiSlider.create(range, {
range: {
'min': 0,
'max': 10
},
step: 1,
start: [5, 8],
connect: true,
behaviour: 'tap-drag',
pips: {
mode: 'steps',
stepped: true,
density: 10
}
});
genders.forEach(function(item){
item.addEventListener('change', function(){
let maxLevel = item.value === 'female' ? 15 : 10
range.noUiSlider.updateOptions({
range: {
'min': 0,
'max': maxLevel
},
});
}, false);
}, false);
コードサンプル noUiSlider UpdateOption | CodePen
まとめ
たまたま見つけて使ってみたのですが、公式サイトを見ると全くjQueryじゃない上に高機能で感動したのがきっかけでご紹介させていたきました。
この記事が皆さんのコーディングライフの一助となれば幸いです。
最後までお読みいただきありがとうございました。
おまけ・オプション
オプションです。
その他、キーボードサポートなどのオプションもありますが、きりがないのでOption | noUiSliderをご確認ください。
おまけ・スライダーの挙動
オプションの中でも、スライダーの挙動のみ詳しく説明します。
behaviour: "drag"
値 | スライダーの挙動 |
---|---|
drag | 範囲をドラック可能でいつもつまみをドラッグできる |
drag-fixed | 範囲をドラック可能。範囲を変えることができないので、ツマミのみを動かす。 |
tap | スライダーをタップすると近くにハンドルが動く。 |
tap-drag | タップしたところにハンドルが動く。 |
hover | バーの上をペンやカーソルを当てるとホバーでイベント発火。 |
unconstrained-tap | ハンドルが互いに通りすぎることができる |
none | 基本の挙動を除いて、他はすべてオフ |