diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index b8bce73063..f3d381ee40 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -53,28 +53,25 @@ const MediaModal = { } }, created () { - this.mediaSwipeGestureRight = GestureService.swipeGesture( - GestureService.DIRECTION_RIGHT, - this.goPrev, - 50 - ) - this.mediaSwipeGestureLeft = GestureService.swipeGesture( - GestureService.DIRECTION_LEFT, - this.goNext, - 50 - ) + this.mediaGesture = new GestureService.SwipeAndScaleGesture({ + direction: GestureService.DIRECTION_LEFT, + callbackPositive: this.goNext, + callbackNegative: this.goPrev, + threshold: 50 + }) }, methods: { getType (media) { return fileTypeService.fileType(media.mimetype) }, mediaTouchStart (e) { - GestureService.beginSwipe(e, this.mediaSwipeGestureRight) - GestureService.beginSwipe(e, this.mediaSwipeGestureLeft) + this.mediaGesture.start(e) }, mediaTouchMove (e) { - GestureService.updateSwipe(e, this.mediaSwipeGestureRight) - GestureService.updateSwipe(e, this.mediaSwipeGestureLeft) + this.mediaGesture.move(e) + }, + mediaTouchEnd (e) { + this.mediaGesture.end(e) }, hide () { this.$store.dispatch('closeMediaViewer') diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 8680267bf9..b5a65d5044 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -13,6 +13,7 @@ :title="currentMedia.description" @touchstart.stop="mediaTouchStart" @touchmove.stop="mediaTouchMove" + @touchend.stop="mediaTouchEnd" @click="hide" @load="onImageLoaded" > diff --git a/src/services/gesture_service/gesture_service.js b/src/services/gesture_service/gesture_service.js index 88a328f3c8..8df4f03dda 100644 --- a/src/services/gesture_service/gesture_service.js +++ b/src/services/gesture_service/gesture_service.js @@ -4,9 +4,17 @@ const DIRECTION_RIGHT = [1, 0] const DIRECTION_UP = [0, -1] const DIRECTION_DOWN = [0, 1] +const isSwipeEvent = e => (e.touches.length === 1) +const isSwipeEventEnd = e => (e.changedTouches.length === 1) + +const isScaleEvent = e => (e.targetTouches.length === 2) +// const isScaleEventEnd = e => (e.changedTouches.length === 2) + const deltaCoord = (oldCoord, newCoord) => [newCoord[0] - oldCoord[0], newCoord[1] - oldCoord[1]] -const touchEventCoord = e => ([e.touches[0].screenX, e.touches[0].screenY]) +const touchCoord = touch => [touch.screenX, touch.screenY] + +const touchEventCoord = e => touchCoord(e.touches[0]) const vectorLength = v => Math.sqrt(v[0] * v[0] + v[1] * v[1]) @@ -61,6 +69,76 @@ const updateSwipe = (event, gesture) => { gesture._swiping = false } +class SwipeAndScaleGesture { + constructor ({ + direction, callbackPositive, callbackNegative, + previewCallback, threshold = 30, perpendicularTolerance = 1.0 + }) { + this.direction = direction + this.previewCallback = previewCallback + this.callbackPositive = callbackPositive + this.callbackNegative = callbackNegative + this.threshold = threshold + this.perpendicularTolerance = perpendicularTolerance + this._startPos = [0, 0] + this._swiping = false + } + + start (event) { + console.log('start() called', event) + if (isSwipeEvent(event)) { + this._startPos = touchEventCoord(event) + console.log('start pos:', this._startPos) + this._swiping = true + } else if (isScaleEvent(event)) { + this._scalePoints = [...event.targetTouches] + this._swiping = false + } + } + + move (event) { + if (isScaleEvent(event)) { + } + } + + end (event) { + console.log('end() called', event) + if (!isSwipeEventEnd(event)) { + console.log('not swipe event') + return + } + if (!this._swiping) { + console.log('not swiping') + return + } + this.swiping = false + + console.log('is swipe event') + + // movement too small + const touch = event.changedTouches[0] + const delta = deltaCoord(this._startPos, touchCoord(touch)) + if (vectorLength(delta) < this.threshold) return + // movement is opposite from direction + const isPositive = dotProduct(delta, this.direction) > 0 + + // movement perpendicular to direction is too much + const towardsDir = project(delta, this.direction) + const perpendicularDir = perpendicular(this.direction) + const towardsPerpendicular = project(delta, perpendicularDir) + if ( + vectorLength(towardsDir) * this.perpendicularTolerance < + vectorLength(towardsPerpendicular) + ) return + + if (isPositive) { + this.callbackPositive() + } else { + this.callbackNegative() + } + } +} + const GestureService = { DIRECTION_LEFT, DIRECTION_RIGHT, @@ -68,7 +146,8 @@ const GestureService = { DIRECTION_DOWN, swipeGesture, beginSwipe, - updateSwipe + updateSwipe, + SwipeAndScaleGesture } export default GestureService