はじめに
どんなやつ?
こうゆうやつを作りたい(作った)。Android的にはシークバーっていうんだけどなんて呼ぶのが正しいのだろうか。
どうやって?
最小値0で最大値100で作る。この値はあくまで表示なので値を足したりかけたりすればどんな範囲でも作れる。また、値の変動はスムーズにしたいので四捨五入する。これらの値は独自属性を作り、格納する。
背景(Bar
とする)と移動する丸(Toggle
とする)は別々にしてDivで実装。同一の親に入れとく。
実装
HTML
jQueryとjQueryUIの導入を忘れないように。
<div class="seekBarParent">
<div class="seekBar"></div>
<div class="seekToggle" data-parcent="0"></div>
</div>
命名適当。data-parcent
という独自属性を作っています。
CSS
めんどくさいからToggleの大きさはvh
単位決め打ちで作る。
.seekBarParent {
position: relative;
/* ご自由に */
}
/* 以下の高さとか大きさとかどうぞ自由に */
.seekBar {
position: relative;
width: calc(100% - (5vh * 0.4));
height: 15%;
top: 42.5%;
left: calc(5vh * 0.2);
border-radius: calc(5vh * 0.15);
border: solid 1px #e50000;
}
.seekToggle {
position: absolute;
height: 40%;
width: calc(5vh * 0.4);
top: 32%;
left: 0%;
border-radius: 50%;
background-color: #e50000;
box-shadow: 2px 2px 3px rgb(51, 51, 51);
}
/* パーセントの数字 */
.seekToggle::before {
content: attr(data-parcent);
position: absolute;
height: auto;
width: 120%;
top: -80%;
left: -10%;
text-align: center;
color: #e50000;
font-size: 0.75em;
}
計算(calc
)を多用してしまう...CSSの勉強不足です...
JavaScript
;
を後ろにつける派です。
$(function () {
// initialize
init();
$(".seekToggle").draggable({
axis: "x",
containment: "parent",
drag: function () {
var nowLeft = $(this).position().left;
var parentWidth = $(this).parent().outerWidth() - $(this).width();
var parcent = Math.round(nowLeft * 100 / parentWidth);
$(this).attr("data-parcent", parcent);
$(this).parent().children(".seekBar").css(
{
"background": "linear-gradient(90deg, #e50000 0%, #e50000 " + parcent + "%, transparent " + parcent + "%, transparent 100%)"
});
}
});
});
ちょっと(かなり)解説。
エレメントにjQueryUI
のdraggable
を指定するとドラッグできるようになります。
axis: "x"
で横方向のみ、containment: "parent"
で親領域内でのみドラッグできるようにしてます。
drag: function() {}
のなかでドラッグ中、毎フレームで実行する処理を書き入れます。
現在の親領域内でのleft
をnowLeft
に格納し、これを親領域で割ればいいのですがここで注意が必要です。
一番左にドラッグしたときのことを考えましょう。nowLeft
は0です。これはいいでしょう。しかし一番右にドラッグしたときは少し違います。nowLeft
は親の横領域いっぱいにはならず、親の横領域-toggleの横領域になります。parentWidthとnowLeftがほぼ一致しないと100%にはなりません。これを考え、parentWidth は$(this).parent().outerWidth() - $(this).width()
としています。(わからない人は- $(this).width()
を消してやってみて下さい、100%に絶対になりません。)
Math.round()
で四捨五入して整数にしています。Before要素に値を代入し、背景色を変えます。グラデーションを使い、境目まで色を同じにすることで背景色を二色で塗り分けています。
以上で、できました。しかし、初期値を0
以外考えていません。初期値を与えたい場合はdata-parcent
に0以外を与え、以下のソースコードを追加してください。(0
の時も働くので追加しといて損はないと思います)
data-parcent
に値を与えるのはJSでもいいですし、HTMLに直接書いてもいいです。
$(function () {
// initialize
init();
// 省略...
});
function init() {
// 動的にdata-parcentに値を与える。
setInitSeek();
}
function setInitSeek() {
$('.seekToggle').each(function(index, element){
var parcent = $(element).attr('data-parcent');
var parentWidth = $(this).parent().outerWidth() - $(this).width();
var left = parentWidth * parcent / 100;
$(element).css(
{
"left": left
});
$(element).parent().children(".seekBar").css(
{
"background": "linear-gradient(90deg, #e50000 0%, #e50000 " + parcent + "%, transparent " + parcent + "%, transparent 100%)"
});
});
}
さっきはnowLeft
からparcent
を求めたので逆のことをしてcssを変えています。data-parcent
に初期値を入れてから実行しないと意味ないです。init()
に他の初期化処理全部まとめたほうがわかりやすいですよ。
最後に
今回は、スライダー?シークバー?可変プログレスバー?を作ってみました。CSSをちょっと変えればいろんなデザインにできると思います。また、今回は0%から100%まで全部赤でしたが、%に応じて色を変えたりすると面白そうです。