divとJqueryのみで縦スライダー(ドラッグ、ホイール、スワイプ対応 PC/SPクロスブラウザ)
以前にCSSで縦スライダーを制作 しました。しかしクロスブラウザに対応するためWebKitだらけの長いCSSコードになってしまいました。
それならばとInput type="range"を使わないでJqueryとDivのみで縦スライダーを作ってみました。本当はSP版まで行く予定でしたがテストでサーバーに上げていたらGoogleにINDEXされてしまいまして、取り急ぎPC版までの対応です。
⇒SPも対応してみました。
Sample
説明
最初にグレー部分と赤い部分でeventをとっていたのですが、mousemoveなどで上下範囲外になりeventをロストします。そこで黒い部分でeventをとりドラッグなどでのeventロスト防いでみました。
クリックmousedown,タップtouchstart,ドラッグmousemove,スワイプtouchmoveに応じて赤い部分の高さを動かし青いポインターを動かしています。
Jquery
var ckon = 0;
var pageY;
$(".bar").bind({
'mousedown': function(e) {
var index = $(".bar").index(this);
var target_rect = e.currentTarget.getBoundingClientRect();
var x = e.clientX - target_rect.left;
var ck = parseInt(e.clientY + 65 - target_rect.top);/*130px/2*/
ck = ck - 80 ;
if(ck < 0) ck=0;
if(ck > 100) ck=100;
if (x <= 30 && 0 <= ck && ck <= 100){
$(".sliderVal").eq(index).text((ck-100)*-1);
$(".space").eq(index).css('height', ck );
/*ここに入れてもOK?みたい*/
$(".mbox").text( "mousedown" );
}
ckon=1;
},
'touchstart': function(e) {
var index = $(".bar").index(this);
var target_rect = e.currentTarget.getBoundingClientRect();
var x = e.clientX - target_rect.left;
var ck = parseInt(e.clientY + 65 - target_rect.top);/*130px/2*/
ck = ck - 80 ;
if(ck < 0) ck=0;
if(ck > 100) ck=100;
if (x <= 30 && 0 <= ck && ck <= 100){
$(".sliderVal").eq(index).text((ck-100)*-1);
$(".space").eq(index).css('height', ck );
/*ここに入れてもOK?みたい*/
$(".mbox").text( "touchstart" );
$("body").css("overflow","hidden");
$(window).on('touchmove.noScroll', function(e) {
e.preventDefault();
});
}
ckon=1;
},
'mousemove': function(e) {
if (ckon==1){
var index = $(".bar").index(this);
var target_rect = e.currentTarget.getBoundingClientRect();
var x = e.clientX - target_rect.left;
var ck = parseInt(e.clientY + 65 - target_rect.top);/*130px/2*/
ck = ck - 80 ;
if(ck < 0) ck=0;
if(ck > 100) ck=100;
if (x <= 30 && 0 <= ck && ck <= 100){
$(".sliderVal").eq(index).text((ck-100)*-1);
$(".space").eq(index).css('height', ck );
}
}
},
'touchmove': function(e) {
$("body").css("overflow","hidden");/*chromeSP*/
var target_rect = e.currentTarget.getBoundingClientRect();
var windowpagey = $(window).scrollTop();
var index = $(".bar").index(this);
var pageY;
if (e.originalEvent.touches) {
pageY = e.originalEvent.touches[0].pageY;
} else {
pageY = e.pageY;
}
var ori_point=parseInt(target_rect.top + windowpagey + 65);/*130px/2*/
pageY= parseInt(pageY);
$(".mbox").text( "原点(真ん中):"+ ori_point + " 指の位置:" + pageY );
var ck = ori_point - pageY;
if(ck<0){
ck = ck*-1 - 1;
}else{
ck = ck*-1 + 1;
}
if (100<ck) ck = 100;
if (ck < 0) ck = 0;
$(".space").eq(index).css('height', ck );
$(".sliderVal").eq(index).text((ck-100)*-1);/*safariSP*/
$(window).on('touchmove.noScroll', function(e) {
e.preventDefault();
});
},
'mouseenter': function(e) { /*mouseoverダメ内側の要素で反応する*/
//ckon = 0;
$("body").css("overflow","hidden");
},
'mouseleave': function(e) { /*mouseoutダメ内側の要素で反応する*/
ckon = 0;
$("body").css("overflow","auto");
},
'mousewheelevent wheel mousewheel': function(e) {
var delta = e.originalEvent.deltaY ? -(e.originalEvent.deltaY) : e.originalEvent.wheelDelta ? e.originalEvent.wheelDelta : -(e.originalEvent.detail);
delta = parseInt(delta);
var index = $(".bar").index(this);
//alert(delta);
var userAgent = window.navigator.userAgent.toLowerCase();
var ck = parseInt($('.space').eq(index).css('height'));
/*サファリだけ.css('top')の値が拡大率につられて大きくな為,Divの高さにした*/
if( userAgent.match(/(msie|MSIE)/) || userAgent.match(/(T|t)rident/) ) {
if (-40 < delta && delta< 0)delta= delta+28;
if (0<delta && delta <40)delta= delta-28;
if (delta <-40)delta= -2;
if (40 < delta)delta= 2;
} else if(userAgent.indexOf('edge') != -1) {
if (delta< 0)delta= delta+205;
if (0<delta)delta= delta-205;
} else if (userAgent.indexOf('chrome') != -1) {
if (delta< 0)delta= delta+120;
if (0<delta)delta= delta-120;
} else if (userAgent.indexOf('firefox') != -1) {
} else if (userAgent.indexOf('safari') != -1) {
if (delta< 0)delta= delta+114;
if (0<delta)delta= delta-114;
/*wheelの動きが鈍い*/
}
ck = ck+(delta*-1);
//$(".mbox").text( "スクロール"+ delta);
if (-5 <= ck && ck <= 105){
if(ck < 0) ck=0;
if(ck > 100) ck=100;
$(".sliderVal").eq(index).text((ck-100)*-1);
$(".space").eq(index).css('height', ck );
}
},
'touchend mouseup': function(e) {
var target_rect = e.currentTarget.getBoundingClientRect();
var index = $(".bar").index(this);
var x = e.clientX - target_rect.left;
var ck = parseInt(e.clientY + 65 - target_rect.top);/*130px/2*/
ck = ck - 80 ;
if(ck < 0) ck=0;
if(ck > 100) ck=100;
if (x <= 30 && 0 <= ck && ck <= 100){
$(".sliderVal").eq(index).text((ck-100)*-1);
//ck = ck + 'px';
$(".space").eq(index).css('height', ck );
}
ckon=0;
$(".mbox").text( "touchend::mouseup" );
$(window).off('.noScroll');
$("body").css("overflow","auto");
}
});
CSS
.Vertical{
height:150px;
width:30px;
display:inline-block;
text-align:center;
/*border: solid;*/
}
.bar{
margin: 15px;
border-radius: 10px;
height:130px;
width:30px;
display: table-cell;
vertical-align: middle;
/*background-color:black;*/
}
.bardisp{
margin: 0 auto;
background-color:grey;
border-radius: 5px;
height:110px;
width:10px;
}
.space{
/*background-color:red;*/
height:50px;
}
.point{
background-color:blue;
border-radius: 10px;
height:10px;
width:10px;
}
html
<h3><span class="color1">Sample</span></h3>
<div class="Vertical">
<div class="bar">
<div class="bardisp">
<div class="space"></div>
<div class="point"> </div>
</div>
</div>
<output class="sliderVal">50<output>
</div>
<div class="Vertical">
<div class="bar">
<div class="bardisp">
<div class="space"></div>
<div class="point"> </div>
</div>
</div>
<output class="sliderVal">50<output>
</div>
<div class="mbox">
</div>