all files / src/scroll/ zoom.js

7.79% Statements 6/77
0% Branches 0/47
14.29% Functions 1/7
7.79% Lines 6/77
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                                                                                                                                                                                                                                                           
import { eventType, style, offsetToBody } from '../util/dom'
import { getDistance } from '../util/lang'
 
export function zoomMixin(BScroll) {
  BScroll.prototype._initZoom = function () {
    const {start = 1, min = 1, max = 4} = this.options.zoom
    this.scale = Math.min(Math.max(start, min), max)
    this.setScale(this.scale)
    this.scrollerStyle[style.transformOrigin] = '0 0'
  }
 
  BScroll.prototype._zoomTo = function (scale, originX, originY, startScale) {
    this.scaled = true
 
    const lastScale = scale / (startScale || this.scale)
    this.setScale(scale)
 
    this.refresh()
 
    let newX = Math.round(this.startX - (originX - this.relativeX) * (lastScale - 1))
    let newY = Math.round(this.startY - (originY - this.relativeY) * (lastScale - 1))
 
    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
    }
 
    if (this.x !== newX || this.y !== newY) {
      this.scrollTo(newX, newY, this.options.bounceTime)
    }
 
    this.scaled = false
  }
 
  BScroll.prototype.zoomTo = function (scale, x, y) {
    let {left, top} = offsetToBody(this.wrapper)
    let originX = x + left - this.x
    let originY = y + top - this.y
    this._zoomTo(scale, originX, originY)
  }
 
  BScroll.prototype._zoomStart = function (e) {
    const firstFinger = e.touches[0]
    const secondFinger = e.touches[1]
    const deltaX = Math.abs(firstFinger.pageX - secondFinger.pageX)
    const deltaY = Math.abs(firstFinger.pageY - secondFinger.pageY)
 
    this.startDistance = getDistance(deltaX, deltaY)
    this.startScale = this.scale
 
    let {left, top} = offsetToBody(this.wrapper)
 
    this.originX = Math.abs(firstFinger.pageX + secondFinger.pageX) / 2 + left - this.x
    this.originY = Math.abs(firstFinger.pageY + secondFinger.pageY) / 2 + top - this.y
 
    this.trigger('zoomStart')
  }
 
  BScroll.prototype._zoom = function (e) {
    if (!this.enabled || this.destroyed || eventType[e.type] !== this.initiated) {
      return
    }
 
    if (this.options.preventDefault) {
      e.preventDefault()
    }
 
    if (this.options.stopPropagation) {
      e.stopPropagation()
    }
 
    const firstFinger = e.touches[0]
    const secondFinger = e.touches[1]
    const deltaX = Math.abs(firstFinger.pageX - secondFinger.pageX)
    const deltaY = Math.abs(firstFinger.pageY - secondFinger.pageY)
    const distance = getDistance(deltaX, deltaY)
    let scale = distance / this.startDistance * this.startScale
 
    this.scaled = true
 
    const {min = 1, max = 4} = this.options.zoom
 
    if (scale < min) {
      scale = 0.5 * min * Math.pow(2.0, scale / min)
    } else if (scale > max) {
      scale = 2.0 * max * Math.pow(0.5, max / scale)
    }
 
    const lastScale = scale / this.startScale
 
    const x = this.startX - (this.originX - this.relativeX) * (lastScale - 1)
    const y = this.startY - (this.originY - this.relativeY) * (lastScale - 1)
 
    this.setScale(scale)
 
    this.scrollTo(x, y, 0)
  }
 
  BScroll.prototype._zoomEnd = function (e) {
    if (!this.enabled || this.destroyed || eventType[e.type] !== this.initiated) {
      return
    }
 
    if (this.options.preventDefault) {
      e.preventDefault()
    }
 
    if (this.options.stopPropagation) {
      e.stopPropagation()
    }
 
    this.isInTransition = false
    this.isAnimating = false
    this.initiated = 0
 
    const {min = 1, max = 4} = this.options.zoom
 
    const scale = this.scale > max ? max : this.scale < min ? min : this.scale
 
    this._zoomTo(scale, this.originX, this.originY, this.startScale)
 
    this.trigger('zoomEnd')
  }
}