###実現したいこと
タッチパネル、マウス操作の双方に対応した、横スクロールメニューを実装したいです。
###発生している問題
自力で実装してだいたい出来上がってきたのですが、数ピクセルだけズレてしまう問題が解決できません。
下のソースコードとサンプルですが、マウスで右にスクロールしていくと、最後の<li>Xi</li>
が数ピクセルだけ見切れてしまうのです。
###該当のソースコード
動作サンプル
html
1<nav class="nav-horizontal root"> 2 <div class="mask"> 3 <div class="list"> 4 <ul class="target"> 5 <li><a href="#" draggable=false>Alpha</a></li> 6 <li><a href="#" draggable=false>Beta</a></li> 7 <li><a href="#" draggable=false>Gamma</a></li> 8 <li><a href="#" draggable=false>Delta</a></li> 9 <li><a href="#" draggable=false>Epsilon</a></li> 10 <li><a href="#" draggable=false>Zeta</a></li> 11 <li><a href="#" draggable=false>Eta</a></li> 12 <li><a href="#" draggable=false>Theta</a></li> 13 <li><a href="#" draggable=false>Iota</a></li> 14 <li><a href="#" draggable=false>Kappa</a></li> 15 <li><a href="#" draggable=false>Lambda</a></li> 16 <li><a href="#" draggable=false>Mu</a></li> 17 <li><a href="#" draggable=false>Nu</a></li> 18 <li><a href="#" draggable=false>Xi</a></li> 19 </ul> 20 </div> 21 </div> 22</nav>
css
1:root { 2 --h: 3rem; /* 可視領域の高さ */ 3} 4.nav-horizontal { 5 overflow: hidden; 6 height: var(--h); 7 width: 100%; 8 position: relative; 9} 10.nav-horizontal .mask { 11 height: 5em; 12 width: 100%; 13 overflow-x: auto; 14 overflow-y: hidden; 15 -webkit-overflow-scrolling: touch; /* タッチパネル対応 */ 16 position: relative; 17} 18.nav-horizontal .list { 19 display: inline-table; 20 max-width: 100vw; 21 overflow-y: scroll; 22} 23.nav-horizontal .list li { 24 display: table-cell; 25 background: salmon; 26 padding: 5px 10px; 27} 28.target { 29 position: absolute; 30 height: var(--h); 31 top: 0px; 32 background-color: red; 33 color: black; 34 padding: 0; 35 margin: 0; 36}
jQuery
1var _isMoving = false; //移動中かどうかのフラグ true:移動中 false:停止中 2var _clickX, _clickY; //クリックされた位置 3var _position; //クリックされた時の要素の位置 4 5//mousedownイベント 6$(".target").on("mousedown", function(e) { 7 console.clear(); //いったん計測結果を整理 8 9 if (_isMoving) return; //移動中の場合は処理しない 10 console.log('mousedown しました'); 11 12 _isMoving = true; //移動中にする 13 14 //クリックされた座標を保持します 15 _clickX = e.screenX; 16 _clickY = e.screenY; 17 18 //クリックされた時の要素の座標を保持します 19 _position = $(".target").position(); 20}); 21 22//mousemoveイベント 23$(".root").on("mousemove", function(e) { 24 console.log('mousemove しそうです'); 25 if (_isMoving == false) return; //移動中でない場合は処理しない 26 console.log('mousemove しました'); 27 28 //クリックされた時の要素の座標に、移動量を加算したものを、座標として設定します 29 const left = _position.left + e.screenX - _clickX; 30 31 console.log('left =',left); 32 console.log('_position =', _position); 33 console.log('e.screenX =', e.screenX); 34 if( left <=0 ){ 35 $(".target").css("left", left + "px"); 36 } 37 38 // 過度なスクロールを戻す 39 const w_win = $(window).width(); 40 const w_ul = $('.target').width(); 41 const w_remainder_nav = w_ul + left; 42 const w_max_left = w_ul - w_win; 43 console.log('w_win =', w_win); 44 console.log('w_ul =', w_ul); 45 console.log('w_remainder_nav =', w_remainder_nav); 46 console.log('w_max_left =', w_max_left); 47 48 if( w_win - w_remainder_nav > 0 ){ 49 console.log('過度なスクロールを戻す'); 50 $(".target").css("left", "-" + w_max_left + "px"); 51 } 52}); 53 54//mouseupイベント 55$(".target").on("mouseup", function(e) { 56 console.log('mouseup しました'); 57 _isMoving = false; 58 _position = {}; 59});
###試したこと
ズレるということは計測のどこかに誤りがあるということでしょうから見直しました。
まず最終的なズレはw_max_left
に集約されますので、ここに+ 15
を加えるとズレなくなりました。
//const w_max_left = w_ul - w_win; const w_max_left = w_ul - w_win + 15;
そして15px
といえば思い出すのはスクロールばーです。そこでスクロールバーの幅が原因か?とアタリをつけてw_win
を次の通り変更しましたが、やはりズレは解消できませんでした。
jQuery
1//const w_win = $(window).width(); 2const w_win = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
なぜズレてしまうのか、どう解消されるのか、わかる方いらっしゃいませんでしょうか?
宜しくお願い致します。
回答1件
あなたの回答
tips
プレビュー