繁体   English   中英

使用 jQuery 在拖动时滚动页面

[英]Scroll the page on drag with jQuery

我曾尝试使用 kinetic.js 和下面的代码,但是当我在 IE11 中尝试此操作时,每次滚动时它都会跳到顶部:

$("html").kinetic();

我想让页面在平板电脑和 IE10 和 11 上可滚动,这样用户就可以像在移动设备上一样向上推动页面向下滚动。

我怎样才能在纯 JS 或 jQuery 中做到这一点而不跳到顶部?

您可以通过记录单击时鼠标的位置以及拖动时的当前位置来非常简单地做到这一点。 尝试这个:

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));
}

要防止在拖动时选择文本,请添加以下 CSS:

body {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

示例小提琴


更新

这是上面作为 jQuery 插件的版本,扩展为允许通过设置进行垂直和水平滚动。 它还允许您更改也使用的cursor

 (function($) { $.dragScroll = function(options) { var settings = $.extend({ scrollVertical: true, scrollHorizontal: true, cursor: null }, options); var clicked = false, clickY, clickX; var getCursor = function() { if (settings.cursor) return settings.cursor; if (settings.scrollVertical && settings.scrollHorizontal) return 'move'; if (settings.scrollVertical) return 'row-resize'; if (settings.scrollHorizontal) return 'col-resize'; } var updateScrollPos = function(e, el) { $('html').css('cursor', getCursor()); var $el = $(el); settings.scrollVertical && $el.scrollTop($el.scrollTop() + (clickY - e.pageY)); settings.scrollHorizontal && $el.scrollLeft($el.scrollLeft() + (clickX - e.pageX)); } $(document).on({ 'mousemove': function(e) { clicked && updateScrollPos(e, this); }, 'mousedown': function(e) { clicked = true; clickY = e.pageY; clickX = e.pageX; }, 'mouseup': function() { clicked = false; $('html').css('cursor', 'auto'); } }); } }(jQuery)) $.dragScroll();
 /* Note: CSS is not relevant to the solution. This is only needed for this demonstration */ body, html { padding: 0; margin: 0; } div { height: 1000px; width: 2000px; border-bottom: 3px dashed #EEE; /* gradient is only to make the scroll movement more obvious */ background: rgba(201, 2, 2, 1); background: -moz-linear-gradient(-125deg, rgba(201, 2, 2, 1) 0%, rgba(204, 0, 204, 1) 16%, rgba(94, 0, 201, 1) 31%, rgba(0, 153, 199, 1) 43%, rgba(0, 199, 119, 1) 56%, rgba(136, 199, 0, 1) 69%, rgba(199, 133, 0, 1) 83%, rgba(107, 0, 0, 1) 100%); background: -webkit-gradient(left top, right bottom, color-stop(0%, rgba(201, 2, 2, 1)), color-stop(16%, rgba(204, 0, 204, 1)), color-stop(31%, rgba(94, 0, 201, 1)), color-stop(43%, rgba(0, 153, 199, 1)), color-stop(56%, rgba(0, 199, 119, 1)), color-stop(69%, rgba(136, 199, 0, 1)), color-stop(83%, rgba(199, 133, 0, 1)), color-stop(100%, rgba(107, 0, 0, 1))); background: -webkit-linear-gradient(-125deg, rgba(201, 2, 2, 1) 0%, rgba(204, 0, 204, 1) 16%, rgba(94, 0, 201, 1) 31%, rgba(0, 153, 199, 1) 43%, rgba(0, 199, 119, 1) 56%, rgba(136, 199, 0, 1) 69%, rgba(199, 133, 0, 1) 83%, rgba(107, 0, 0, 1) 100%); background: -o-linear-gradient(-125deg, rgba(201, 2, 2, 1) 0%, rgba(204, 0, 204, 1) 16%, rgba(94, 0, 201, 1) 31%, rgba(0, 153, 199, 1) 43%, rgba(0, 199, 119, 1) 56%, rgba(136, 199, 0, 1) 69%, rgba(199, 133, 0, 1) 83%, rgba(107, 0, 0, 1) 100%); background: -ms-linear-gradient(-125deg, rgba(201, 2, 2, 1) 0%, rgba(204, 0, 204, 1) 16%, rgba(94, 0, 201, 1) 31%, rgba(0, 153, 199, 1) 43%, rgba(0, 199, 119, 1) 56%, rgba(136, 199, 0, 1) 69%, rgba(199, 133, 0, 1) 83%, rgba(107, 0, 0, 1) 100%); background: linear-gradient(-110deg, rgba(201, 2, 2, 1) 0%, rgba(204, 0, 204, 1) 16%, rgba(94, 0, 201, 1) 31%, rgba(0, 153, 199, 1) 43%, rgba(0, 199, 119, 1) 56%, rgba(136, 199, 0, 1) 69%, rgba(199, 133, 0, 1) 83%, rgba(107, 0, 0, 1) 100%); filter: progid: DXImageTransform.Microsoft.gradient( startColorstr='#c90202', endColorstr='#6b0000', GradientType=1); color: #EEE; padding: 20px; font-size: 2em; } body { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div>First...</div> <div>Second...</div>

我只是想补充。 使用 Rory 的代码,我进行了水平滚动。

var clicked = false, base = 0;

$('#someDiv').on({
    mousemove: function(e) {
        clicked && function(xAxis) {
            var _this = $(this);
            if(base > xAxis) {
                base = xAxis;
                _this.css('margin-left', '-=1px');
            }
            if(base < xAxis) {
                base = xAxis;
                _this.css('margin-left', '+=1px');
            }
        }.call($(this), e.pageX);
    },
    mousedown: function(e) {
        clicked = true;
        base = e.pageX;
    },
    mouseup: function(e) {
        clicked = false;
        base = 0;
    }
});

此代码适用于水平和垂直鼠标拖动滚动。 这很简单。

var curYPos = 0,
    curXPos = 0,
    curDown = false;

window.addEventListener('mousemove', function(e){ 
  if(curDown === true){
    window.scrollTo(document.body.scrollLeft + (curXPos - e.pageX), document.body.scrollTop + (curYPos - e.pageY));
  }
});

window.addEventListener('mousedown', function(e){ curDown = true; curYPos = e.pageY; curXPos = e.pageX; });
window.addEventListener('mouseup', function(e){ curDown = false; }); 

基于 Rory McCrossan 的想法,使用 AngularJS2 实现。

import {Directive, ElementRef, OnDestroy, Input} from "@angular/core";

declare var jQuery: any;

@Directive({
    selector: '[appDragScroll]'
})
export class DragScrollDirective implements OnDestroy {

    @Input() scrollVertical: boolean = true;
    @Input() scrollHorizontal: boolean = true;

    private dragging = false;
    private originalMousePositionX: number;
    private originalMousePositionY: number;
    private originalScrollLeft: number;
    private originalScrollTop: number;

    constructor(private nodeRef: ElementRef) {
        let self = this;

        jQuery(document).on({
            "mousemove": function (e) {
                self.dragging && self.updateScrollPos(e);
            },
            "mousedown": function (e) {
                self.originalMousePositionX = e.pageX;
                self.originalMousePositionY = e.pageY;
                self.originalScrollLeft = jQuery(self.nodeRef.nativeElement).scrollLeft();
                self.originalScrollTop = jQuery(self.nodeRef.nativeElement).scrollTop();
                self.dragging = true;
            },
            "mouseup": function (e) {
                jQuery('html').css('cursor', 'auto');
                self.dragging = false;
            }
        });

    }

    ngOnDestroy(): void {
        jQuery(document).off("mousemove");
        jQuery(document).off("mousedown");
        jQuery(document).off("mouseup");
    }

    private updateScrollPos(e) {
        jQuery('html').css('cursor', this.getCursor());

        let $el = jQuery(this.nodeRef.nativeElement);
        if (this.scrollHorizontal) {
            $el.scrollLeft(this.originalScrollLeft + (this.originalMousePositionX - e.pageX));
        }
        if (this.scrollVertical) {
            $el.scrollTop(this.originalScrollTop + (this.originalMousePositionY - e.pageY));
        }
    }

    private getCursor() {
        if (this.scrollVertical && this.scrollHorizontal) return 'move';
        if (this.scrollVertical) return 'row-resize';
        if (this.scrollHorizontal) return 'col-resize';
    }

}

基于第一个答案,这是鼠标拖动水平滚动的代码:

var clicked = false, clickX;
$(document).on({
    'mousemove': function(e) {
        clicked && updateScrollPos(e);
    },
    'mousedown': function(e) {
        e.preventDefault();        
        clicked = true;
        clickX = e.pageX;
    },
    'mouseup': function() {
        clicked = false;
        $('html').css('cursor', 'auto');
    }
});

var updateScrollPos = function(e) {
    $('html').css('cursor', 'grabbing');
    $(window).scrollLeft($(window).scrollLeft() + (clickX - e.pageX));
}

我对 Rory 的代码进行了相当多的修改,并让每个元素的侧滚动功能正常工作。 对于在 web 应用程序的单个视图中有多个可滚动磁贴的项目,我需要它。 .drag类添加到任何元素,可能做一些样式,应该很好。

// jQuery sidescroll code. Can easily be modified for vertical scrolling as well.
// This code was hacked together so clean it up if you use it in prod.
// Written by Josh Moore
// Thanks to Rory McCrossan for a good starting point

// How far away the mouse should move on a drag before interrupting click
// events (your own code must also interrupt regular click events with a
// method that calls getAllowClick())
const THRESHOLD = 32;
var clicked = false;
var allowClick = true;

// mouseX: most recent mouse position. updates when mouse moves.
//     el: jQuery element that will be scrolled.
//    thX: "threshold X", where the mouse was at the beginning of the drag
var mouseX, startY, el, thX;

// Add the .drag class to any element that should be scrollable.
// You may need to also add these CSS rules:
//   overflow: hidden; /* can be replaced with overflow-x or overflow-y */
//   whitespace: none;
function drag() {
    $('.drag').on({
        'mousemove': e => {
            if (el != null && clicked) {
                el.scrollLeft(el.scrollLeft() + (mouseX - e.pageX));
                mouseX = e.pageX;
                allowClick = Math.abs(thX - mouseX) > THRESHOLD ? false : true;
            }
        },
        'mousedown': e => {
            clicked = true;
            // This lets the user click child elements of the scrollable.
            // Without it, you must click the .drag element directly to be able to scroll.
            el = $(e.target).closest('.drag');
            mouseX = e.pageX;
            thX = e.pageX;
        },
        'mouseup': e => {
            clicked = false;
            el = null;
            allowClick = true;
        }
    });
}

function getAllowClick() {
    return allowClick;
}

同样,我没有使用垂直滚动,但添加起来非常简单(用 Y 替换 X、 scrollTop()而不是scrollLeft()等)。 希望这对将来的人有所帮助!

这个框架是用 vanilla javascript 编写的,对我来说效果最好。

它还支持 div 内的滚动条。

注意:如果创建动态内容,调用dragscroll.reset(); 渲染后。

拖动滚动

用法

演示

下面是一个基于单个元素类的简单滚动解决方案

      var cursordown = false;
      var cursorypos = 0;
      var cursorxpos = 0;
      $('.cursorgrab').mousedown(function(e){
        cursordown = true; 
        cursorxpos = $(this).scrollLeft() + e.clientX; 
        cursorypos = $(this).scrollTop() +e.clientY;
      }).mousemove(function(e){
        if(!cursordown) return;
        try { $(this).scrollLeft(cursorxpos - e.clientX); } catch(e) { }
        try { $(this).scrollTop(cursorypos - e.clientY); } catch(e) { }
      }).mouseup(end = function(e){
        cursordown = false;
      }).mouseleave(end)
        .css('user-select', 'none')
        .css('cursor', 'grab');

完全验证水平和垂直滚动

您只需将.cursorgrab类设置到您的元素中

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM