JSFiddle - React, Tailwind, and code Playground
HTML
<nav class="nav-horizontal root">
<div class="mask">
<div class="list">
<ul class="target">
<li><a href="#" draggable=false>Alpha</a></li>
<li><a href="#" draggable=false>Beta</a></li>
<li><a href="#" draggable=false>Gamma</a></li>
<li><a href="#" draggable=false>Delta</a></li>
<li><a href="#" draggable=false>Epsilon</a></li>
<li><a href="#" draggable=false>Zeta</a></li>
<li><a href="#" draggable=false>Eta</a></li>
<li><a href="#" draggable=false>Theta</a></li>
<li><a href="#" draggable=false>Iota</a></li>
<li><a href="#" draggable=false>Kappa</a></li>
<li><a href="#" draggable=false>Lambda</a></li>
<li><a href="#" draggable=false>Mu</a></li>
<li><a href="#" draggable=false>Nu</a></li>
<li><a href="#" draggable=false>Xi</a></li>
</ul>
</div>
</div>
</nav>
CSS
:root {
--h: 3rem; /* 可視領域の高さ */
}
.nav-horizontal {
overflow: hidden;
height: var(--h);
width: 100%;
position: relative;
}
.nav-horizontal .mask {
height: 5em;
width: 100%;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch; /* タッチパネル対応 */
position: relative;
}
.nav-horizontal .list {
display: inline-table;
max-width: 100vw;
overflow-y: scroll;
}
.nav-horizontal .list li {
display: table-cell;
background: salmon;
padding: 5px 10px;
}
.target {
position: absolute;
height: var(--h);
top: 0px;
background-color: red;
color: black;
padding: 0;
margin: 0;
}
JavaScript
var _isMoving = false; //移動中かどうかのフラグ true:移動中 false:停止中
var _clickX, _clickY; //クリックされた位置
var _position; //クリックされた時の要素の位置
//mousedownイベント
$(".target").on("mousedown", function(e) {
console.clear(); //いったん計測結果を整理
if (_isMoving) return; //移動中の場合は処理しない
console.log('mousedown しました');
_isMoving = true; //移動中にする
//クリックされた座標を保持します
_clickX = e.screenX;
_clickY = e.screenY;
//クリックされた時の要素の座標を保持します
_position = $(".target").position();
});
//mousemoveイベント
$(".root").on("mousemove", function(e) {
console.log('mousemove しそうです');
if (_isMoving == false) return; //移動中でない場合は処理しない
console.log('mousemove しました');
//クリックされた時の要素の座標に、移動量を加算したものを、座標として設定します
const left = _position.left + e.screenX - _clickX;
console.log('left =',left);
console.log('_position =', _position);
console.log('e.screenX =', e.screenX);
if( left <=0 ){
$(".target").css("left", left + "px");
}
// 過度なスクロールを戻す
const w_win = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
const w_ul = $('.target').width();
const w_remainder_nav = w_ul + left;
const w_max_left = w_ul - w_win;
console.log('w_win =', w_win);
console.log('w_ul =', w_ul);
console.log('w_remainder_nav =', w_remainder_nav);
console.log('w_max_left =', w_max_left);
if( w_win - w_remainder_nav > 0 ){
console.log('右に調整');
$(".target").css("left", "-" + w_max_left + "px");
}
});
//mouseupイベント
$(".target").on("mouseup", function(e) {
console.log('mouseup しました');
_isMoving = false;
_position = {};
});