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