如何修改点击拖拽滚动逻辑,实现跳转至对应Hash锚点?
实现拖拽跳转至最近Hash锚点的方案
我之前做了一个鼠标点击拖拽滚动页面的功能(无需滚轮),代码是这样的:
var clicked = false, clickY; $(document).on({ 'mousemove': function(e) { clicked && updateScrollPos(e); }, 'mousedown': function(e) { clicked = true; clickY = e.pageY; }, 'mouseup': function() { clicked = false; $('html').css('cursor', 'auto'); } }); var updateScrollPos = function(e) { $('html').css('cursor', 'row-resize'); $(window).scrollTop($(window).scrollTop() + (clickY - e.pageY)); }
后来我想升级这个功能:当拖拽距离达到10px左右时,直接跳转到当前位置上下最近的Hash锚点——往上拖就跳上面的锚点,往下拖就跳下面的锚点。我知道核心是要替换掉updateScrollPos里的滚动代码,但自己搞不定具体实现。
后来参考了相关方案,最终采用了Saeed Ataee的思路,把原来的拖拽逻辑和锚点跳转结合起来,替换掉了滚轮相关的代码,效果比预期的好,最终代码如下:
$('#nav').onePageNav(); var $current, flag = false, clicked = false, clickY; $('body') .on('mousemove', function(e) { if (!clicked || flag) return; var moveDistance = clickY - e.pageY; // 拖拽距离超过10px时触发锚点跳转 if (Math.abs(moveDistance) > 10) { flag = true; $current = $('div.current'); if (moveDistance > 0) { // 向上拖拽,定位到上一个锚点元素 var $prev = $current.prev(); if ($prev.length) { $('body').scrollTo($prev, 1000, { onAfter : function(){ flag = false; $current.removeClass('current'); $prev.addClass('current'); } }); } else { // 已经是第一个元素,重置标记 flag = false; } } else { // 向下拖拽,定位到下一个锚点元素 var $next = $current.next(); if ($next.length) { $('body').scrollTo($next, 1000, { onAfter : function(){ flag = false; $current.removeClass('current'); $next.addClass('current'); } }); } else { // 已经是最后一个元素,重置标记 flag = false; } } // 跳转触发后暂时关闭拖拽状态,避免重复触发 clicked = false; $('html').css('cursor', 'auto'); } }) .on('mousedown', function(e) { clicked = true; clickY = e.pageY; flag = false; // 每次点击都重置跳转标记 }) .on('mouseup', function() { clicked = false; $('html').css('cursor', 'auto'); });
这里的关键逻辑是:
- 记录鼠标按下时的Y坐标,拖拽时计算移动距离
- 当移动距离超过10px时,根据方向判断是找前一个还是后一个锚点元素
- 用
flag标记避免跳转过程中重复触发事件 - 跳转完成后更新当前激活的锚点类名,同时重置标记
内容的提问来源于stack exchange,提问作者user8139445
相关产品推荐
相关产品推荐

