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>