all files / src/scroll/ mouse-wheel.js

3.8% Statements 3/79
0% Branches 0/56
14.29% Functions 1/7
3.8% Lines 3/79
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144                                                                                                                                                                                                                                                                                         
import { addEvent, removeEvent } from '../util/dom'
import { ease } from '../util/ease'
 
export function mouseWheelMixin(BScroll) {
  BScroll.prototype._initMouseWheel = function () {
    this._handleMouseWheelEvent(addEvent)
 
    this.on('destroy', () => {
      clearTimeout(this.mouseWheelTimer)
      clearTimeout(this.mouseWheelEndTimer)
      this._handleMouseWheelEvent(removeEvent)
    })
 
    this.firstWheelOpreation = true
  }
 
  BScroll.prototype._handleMouseWheelEvent = function (eventOperation) {
    eventOperation(this.wrapper, 'wheel', this)
    eventOperation(this.wrapper, 'mousewheel', this)
    eventOperation(this.wrapper, 'DOMMouseScroll', this)
  }
 
  BScroll.prototype._onMouseWheel = function (e) {
    if (!this.enabled) {
      return
    }
    e.preventDefault()
 
    if (this.options.stopPropagation) {
      e.stopPropagation()
    }
 
    if (this.firstWheelOpreation) {
      this.trigger('scrollStart')
    }
    this.firstWheelOpreation = false
 
    const {speed = 20, invert = false, easeTime = 300} = this.options.mouseWheel
 
    clearTimeout(this.mouseWheelTimer)
    this.mouseWheelTimer = setTimeout(() => {
      if (!this.options.snap && !easeTime) {
        this.trigger('scrollEnd', {
          x: this.x,
          y: this.y
        })
      }
      this.firstWheelOpreation = true
    }, 400)
 
    let wheelDeltaX
    let wheelDeltaY
 
    switch (true) {
      case 'deltaX' in e:
        if (e.deltaMode === 1) {
          wheelDeltaX = -e.deltaX * speed
          wheelDeltaY = -e.deltaY * speed
        } else {
          wheelDeltaX = -e.deltaX
          wheelDeltaY = -e.deltaY
        }
        break
      case 'wheelDeltaX' in e:
        wheelDeltaX = e.wheelDeltaX / 120 * speed
        wheelDeltaY = e.wheelDeltaY / 120 * speed
        break
      case 'wheelDelta' in e:
        wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * speed
        break
      case 'detail' in e:
        wheelDeltaX = wheelDeltaY = -e.detail / 3 * speed
        break
      default:
        return
    }
 
    let direction = invert ? -1 : 1
    wheelDeltaX *= direction
    wheelDeltaY *= direction
 
    if (!this.hasVerticalScroll) {
      wheelDeltaX = wheelDeltaY
      wheelDeltaY = 0
    }
 
    let newX
    let newY
    if (this.options.snap) {
      newX = this.currentPage.pageX
      newY = this.currentPage.pageY
 
      if (wheelDeltaX > 0) {
        newX--
      } else if (wheelDeltaX < 0) {
        newX++
      }
 
      if (wheelDeltaY > 0) {
        newY--
      } else if (wheelDeltaY < 0) {
        newY++
      }
 
      this._goToPage(newX, newY)
      return
    }
 
    newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0)
    newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0)
 
    this.movingDirectionX = this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0
    this.movingDirectionY = this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0
 
    if (newX > this.minScrollX) {
      newX = this.minScrollX
    } else if (newX < this.maxScrollX) {
      newX = this.maxScrollX
    }
 
    if (newY > this.minScrollY) {
      newY = this.minScrollY
    } else if (newY < this.maxScrollY) {
      newY = this.maxScrollY
    }
 
    const needTriggerEnd = this.y === newY
    this.scrollTo(newX, newY, easeTime, ease.swipe)
    this.trigger('scroll', {
      x: this.x,
      y: this.y
    })
    clearTimeout(this.mouseWheelEndTimer)
    if (needTriggerEnd) {
      this.mouseWheelEndTimer = setTimeout(() => {
        this.trigger('scrollEnd', {
          x: this.x,
          y: this.y
        })
      }, easeTime)
    }
  }
}