使 HTML5 可拖动项目滚动页面?

问题描述 投票:0回答:4

我在网页上的一些 div 上使用 HTML5 属性

draggable = "true"
。我希望这样当您将这些项目之一拖到页面底部时,它会向下滚动页面,当您将其拖到顶部时,它会向上滚动页面。

我最终会在侧边栏上创建一个播放列表,并且由于它不会始终显示在页面上,具体取决于您在页面上查看的位置,因此当您拖动时页面需要滚动。

我的页面是这里,您可以尝试拖动帖子的图片。在 Chrome 上,当我拖动到底部时,它会自动让我向下滚动,但不能向上滚动。在 Firefox 上,它不会自动让我向任一方向滚动。有什么帮助吗?

这里有一个简单的 jsfiddle 可以帮助您入门。在 Chrome 上,您应该能够向下拖动 Google 图标并使其向下滚动页面,但不能向上滚动。

javascript html draggable
4个回答
43
投票

这里有一段代码,可以在您拖动某些内容时向上或向下滚动页面。只需将拖动对象放置在页面的顶部或底部即可。 :)

    var stop = true;
    $(".draggable").on("drag", function (e) {

        stop = true;

        if (e.originalEvent.clientY < 150) {
            stop = false;
            scroll(-1)
        }

        if (e.originalEvent.clientY > ($(window).height() - 150)) {
            stop = false;
            scroll(1)
        }

    });

    $(".draggable").on("dragend", function (e) {
         stop = true;
    });

    var scroll = function (step) {
        var scrollY = $(window).scrollTop();
        $(window).scrollTop(scrollY + step);
        if (!stop) {
            setTimeout(function () { scroll(step) }, 20);
        }
    }

1
投票

我制作了一个简单的 JavaScript 拖放类。它可以在拖动时自动向上或向下滚动页面。 请参阅此jsfiddle。也可以在我的 github 页面上找到。 现在不建议高速拖动。我需要解决这个问题。

下面的代码是库的一部分。

var autoscroll = function (offset, poffset, parentNode) {
  var xb = 0;
  var yb = 0;
  if (poffset.isBody == true) {
    var scrollLeft = poffset.scrollLeft;
    var scrollTop = poffset.scrollTop;
    var scrollbarwidth = (document.documentElement.clientWidth - document.body.offsetWidth); //All
    var scrollspeed = (offset.right + xb) - (poffset.right + scrollbarwidth);
    if (scrollspeed > 0) {
      this.scrollLeft(parentNode, scrollLeft + scrollspeed);
    }
    scrollspeed = offset.left - (xb);
    if (scrollspeed < 0) {
      this.scrollLeft(parentNode, scrollLeft + scrollspeed);
    }
    scrollspeed = (offset.bottom + yb) - (poffset.bottom);
    if (scrollspeed > 0) {
      this.scrollTop(parentNode, scrollTop + scrollspeed);
    }
    scrollspeed = offset.top - (yb);
    if (scrollspeed < 0) {
      this.scrollTop(parentNode, scrollTop + scrollspeed);
    }
  } else {
    var scrollLeft = offset.scrollLeft;
    var scrollTop = offset.scrollTop;
    var scrollbarwidth = parentNode.offsetWidth - parentNode.clientWidth; //17
    var scrollbarheight = parentNode.offsetHeight - parentNode.clientHeight; //17
    var scrollspeed = (offset.right + xb) - (poffset.right - scrollbarwidth);
    if (scrollspeed > 0) {
      this.scrollLeft(parentNode, scrollLeft + scrollspeed);
    }
    scrollspeed = offset.left - (xb + poffset.left);
    if (scrollspeed < 0) {
      this.scrollLeft(parentNode, scrollLeft + scrollspeed);
    }
    scrollspeed = (offset.bottom + scrollbarheight + yb) - (poffset.bottom);
    if (scrollspeed > 0) {
      this.scrollTop(parentNode, scrollTop + scrollspeed);
    }
    scrollspeed = offset.top - (yb + poffset.top);
    if (scrollspeed < 0) {
      this.scrollTop(parentNode, scrollTop + scrollspeed);
    }
  }
};

1
投票

这是 AngularPlayers 答案的 javascript 版本,我添加了水平支持。我注意到 JQuery 解决方案和 Javascript 解决方案在移动 safari 上都有一个错误,当发生过度滚动的弹跳效果时,该错误允许页面无限增长。

VerticalMaxed
HorizontalMaxed
的目的是在再次滚动之前检查滚动条是否没有最大化。这可以防止页面在过度滚动弹跳期间增长。

var stopX = true;
var stopY = true;

document.addEventListener('drag', function(e) {
    if (event.target.classList.contains('draggable')) {
        stopY = true;
                    
        // Handle Y
        if (e.clientY < 150) {
            stopY = false;
            scroll(0,-1)
        }

        if ((e.clientY > ( document.documentElement.clientHeight - 150)) && !VerticalMaxed()) { 
            stopY = false;
            scroll(0,1) 
        }
                
        // Handle X
        stopX = true;
        if (e.clientX < 150) {
            stopX = false;
            scroll(-1,0)
        }

        if ((e.clientX > ( document.documentElement.clientWidth - 150)) && !HorizontalMaxed()) { 
            stopX = false;
            scroll(1,0)
        }
    }

});

document.addEventListener('dragend', function(e) {
    if (event.target.classList.contains('draggable')) {
        stopY = true;
        //stopY = true;
        stopX = true;
    }
});

// On drag scroll, prevents page from growing with mobile safari rubber-band effect
var VerticalMaxed = function(){ return (window.innerHeight + window.scrollY) >= document.body.offsetHeight}
var HorizontalMaxed = function(){ return (window.pageXOffset) > (document.body.scrollWidth - document.body.clientWidth);}

var scroll = function (stepX, stepY) {
    var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
    var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
    window.scrollTo((scrollX + stepX), (scrollY + stepY));
                
    if (!stopY || !stopX) {
        setTimeout(function () { scroll(stepX, stepY) }, 20);
    }
}

0
投票

试图让它变得更流畅,发现

requestAnimationFrame
对此很有用。 基于AngularPlayer

的答案
var MaxScrollSpeed = 20;
var scrollDelta = 0;
var scrollingTimer = null;

$(".draggable").on("drag", function (e) {

    if (e.originalEvent.clientY < 150) {
        scrollDelta = Math.max(-MaxScrollSpeed, e.originalEvent.clientY - 150);
    } else if (e.originalEvent.clientY > ($(window).height() - 150)) {
        scrollDelta = Math.min(MaxScrollSpeed, e.originalEvent.clientY - ($(window).height() - 150));
    } else {
        scrollDelta = 0;
    }

    if (scrollDelta !== 0 && !scrollingTimer) {
        scrollingTimer = requestAnimationFrame(scroll);
    }

});

$(".draggable").on("dragend", function (e) {
    scrollDelta = 0;
    if (scrollingTimer) {
        cancelAnimationFrame(scrollingTimer);
    }
    scrollingTimer = null;
});

var scroll = function() {
    if (scrollDelta !== 0) {
        window.scrollBy({left: 0, top: scrollDelta, behavior: 'instant'});
    }
    scrollDelta = 0;
    scrollingTimer = null;
}
© www.soinside.com 2019 - 2024. All rights reserved.