Класс прокрутки Javascript и скорость колесика мыши в разных браузерах - PullRequest
3 голосов
/ 02 декабря 2010

Я получаю много сообщений о том, что колесико мыши ведет себя по-разному в разных браузерах при использовании этого класса полосы прокрутки. В некоторых браузерах (например, Firefox) он очень медленный, а в других (в основном это новые версии Safari на Snow Leopard) он идеален.

Есть идеи, что здесь происходит и как это исправить? Я использую библиотеку Mootools. Здесь стоит обратить внимание на строку wheel: (Browser.firefox) ? 20 : 1. Здесь вы устанавливаете скорость или шаги для колесика мыши.

Здесь это настроено в jsFiddle: http://jsfiddle.net/brandondurham/6SUyM/

var ScrollBar = new Class({

    Implements: [Events, Options],

    options: {
        wheel: (Browser.firefox) ? 20 : 1
    },

    initialize: function(main, options) {

        this.setOptions(options);

        this.main = $(main);
        this.content = this.main.getFirst();

        this.vScrollbar = new Element('div', {
            'class': 'scrollbar'
        }).inject(this.content, 'after');

        this.vTrack = new Element('div', {
            'class': 'track'
        }).inject(this.vScrollbar);

        this.vThumb = new Element('div', {
            'class': 'handle'
        }).inject(this.vTrack);

        this.bound = {
            'vStart': this.vStart.bind(this),
            'end': this.end.bind(this),
            'vDrag': this.vDrag.bind(this),
            'vTouchDrag': this.vTouchDrag.bind(this),
            'wheel': this.wheel.bind(this),
            'vPage': this.vPage.bind(this),
        };

        this.vScrollbar.set('tween', {
            duration: 200,
            transition: 'cubic:out'
        });
        this.main.addEvent('mouseenter', function(event){
            this.vScrollbar.get('tween').cancel();
            this.vScrollbar.tween('width', 12);
        }.bind(this));
        this.main.addEvent('mouseleave', function(event){
            this.vScrollbar.get('tween').cancel();
            this.vScrollbar.tween('width', 0);
        }.bind(this));

        this.vPosition = {};
        this.vMouse = {};
        this.update();
        this.attach();

        this.scrollContent = new Fx.Scroll(this.content, {
            duration: 800,
            transition: Fx.Transitions.Cubic.easeOut,
        });
        this.scrollThumb = new Fx.Morph(this.vThumb, {
            duration: 400,
            transition: Fx.Transitions.Cubic.easeOut,
        });
    },

    update: function() {

        var panel_id = (this.content.getFirst()) ? this.content.getFirst().get('id') : '';

        if ((this.content.scrollHeight <= this.main.offsetHeight) || panel_id == 'random-doodle') this.main.addClass('noscroll');
        else this.main.removeClass('noscroll');

        this.vContentSize = this.content.offsetHeight;
        this.vContentScrollSize = this.content.scrollHeight;
        this.vTrackSize = this.vTrack.offsetHeight;

        this.vContentRatio = this.vContentSize / this.vContentScrollSize;

        this.vThumbSize = (this.vTrackSize * this.vContentRatio).limit(12, this.vTrackSize);

        this.vScrollRatio = this.vContentScrollSize / this.vTrackSize;

        this.vThumb.setStyle('height', this.vThumbSize);

        this.vUpdateThumbFromContentScroll();
        this.vUpdateContentFromThumbPosition();

    },

    vUpdateContentFromThumbPosition: function() {
        this.content.scrollTop = this.vPosition.now * this.vScrollRatio;
    },

    vUpdateContentFromThumbPosition2: function() {
        var pos = this.vPosition.now * this.vScrollRatio;
        this.scrollContent.start(0, pos);
    },

    vUpdateThumbFromContentScroll: function() {
        this.vPosition.now = (this.content.scrollTop / this.vScrollRatio).limit(0, (this.vTrackSize - this.vThumbSize));
        this.vThumb.setStyle('top', this.vPosition.now);
    },

    vUpdateThumbFromContentScroll2: function(pos) {
        this.vPosition.now = (this.content.scrollTopNew / this.vScrollRatio).limit(0, (this.vTrackSize - this.vThumbSize));           
        this.scrollThumb.start({
            'top': this.vPosition.now       
        });
    },

    attach: function() {
        if (this.options.wheel) this.content.addEvent('mousewheel', this.bound.wheel);
        this.content.addEvent('touchstart', this.bound.vStart);
        this.vThumb.addEvent('mousedown', this.bound.vStart);
        this.vTrack.addEvent('mouseup', this.bound.vPage);
    },

    wheel: function(event) {
        this.content.scrollTop -= event.wheel * this.options.wheel;
        this.vUpdateThumbFromContentScroll();
        event.stop();
    },

    scrollTo: function(pos){
        myInstance = this;
        this.content.scrollTopNew = pos;
        this.scrollContent.start(0, this.content.scrollTopNew);
        myInstance.vUpdateThumbFromContentScroll2(pos);
    },

    vPage: function(event) {
        // if scrolling up
        if (event.page.y > this.vThumb.getPosition().y) {
            myInstance = this;
            this.content.scrollTopNew = this.content.scrollTop.toInt() + this.content.offsetHeight.toInt();
            this.scrollContent.start(0, this.content.scrollTopNew);
        }
        // if scrolling down
        else {
            myInstance = this;    
            this.content.scrollTopNew = this.content.scrollTop.toInt() - this.content.offsetHeight.toInt();    
            this.scrollContent.start(0, this.content.scrollTopNew);       
        }
        myInstance.vUpdateThumbFromContentScroll2(event.page.y);
        event.stop();
    },

    vStart: function(event) {
        this.vMouse.start = event.page.y;
        this.vPosition.start = this.vThumb.getStyle('top').toInt();
        document.addEvent('touchmove', this.bound.vTouchDrag);
        document.addEvent('touchend', this.bound.end);
        document.addEvent('mousemove', this.bound.vDrag);
        document.addEvent('mouseup', this.bound.end);
        this.vThumb.addEvent('mouseup', this.bound.end);
        event.stop();
    },

    end: function(event) {
        document.removeEvent('touchmove', this.bound.vTouchDrag);
        document.removeEvent('mousemove', this.bound.vDrag);
        document.removeEvent('mouseup', this.bound.end);
        this.vThumb.removeEvent('mouseup', this.bound.end);
        event.stop();
    },

    vTouchDrag: function(event) {
        this.vMouse.now = event.page.y;
        this.vPosition.now = (this.vPosition.start - (this.vMouse.now - this.vMouse.start)).limit(0, (this.vTrackSize - this.vThumbSize));
        this.vUpdateContentFromThumbPosition();
        this.vUpdateThumbFromContentScroll();
        event.stop();
    },

    vDrag: function(event) {
        this.vMouse.now = event.page.y;
        this.vPosition.now = (this.vPosition.start + (this.vMouse.now - this.vMouse.start)).limit(0, (this.vTrackSize - this.vThumbSize));
        this.vUpdateContentFromThumbPosition();
        this.vUpdateThumbFromContentScroll();
        event.stop();
    }

});

1 Ответ

1 голос
/ 23 февраля 2011

Событие колесика мыши очень странно в javascript, основной проблемой обычно является Safari, так как они используются для настройки соотношения при каждом выпуске точки, и даже тогда значения, сообщаемые событием, не одинаковы во всех основных браузерах.

Некоторое время назад об этом говорили на трекере MooTools ( ссылка ) и сравнивая различные решения. Я пришел к выводу, что стандартного способа нормализации события не существует.
Последнийсообщение об этой проблеме показывает возможное решение для нормализации ( ссылка ), но оно нарушает ускорение колеса в Safari (и, вероятно, любое другое ускорение, которое предлагает другая комбинация браузера / ОС / драйвера мыши), поэтому это компромисс, которыйвам нужно будет оценить, соответствует ли он требованиям вашего сценария использования.

...