Mercurial > hg > ugly-duckling
changeset 205:b638c714bd1d
Implement pinch-zoom manually using touchevents, as HammerJS was preventing scrolling the page. This should also allow for smoother transitioning between gestures - needs testing on a device.
author | Lucas Thompson <dev@lucas.im> |
---|---|
date | Fri, 24 Mar 2017 15:27:07 +0000 |
parents | bdfd4b4b7130 |
children | 1db0bb28688b |
files | src/app/waveform/waveform.component.ts |
diffstat | 1 files changed, 47 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/src/app/waveform/waveform.component.ts Fri Mar 24 12:08:36 2017 +0000 +++ b/src/app/waveform/waveform.component.ts Fri Mar 24 15:27:07 2017 +0000 @@ -247,7 +247,18 @@ Math.pow(p2.y - p1.y, 2), 0.5); }; - const hammertime = new Hammer(this.trackDiv.nativeElement); + const calculateMidPoint: (p1: Point, p2: Point) => Point = (p1, p2) => { + return { + x: 0.5 * (p1.x + p2.x), + y: 0.5 * (p1.y + p2.y) + }; + }; + + const hammertime = new Hammer.Manager(this.trackDiv.nativeElement, { + recognizers: [ + [Hammer.Pan, { direction: Hammer.DIRECTION_HORIZONTAL }] + ] + }); // it seems HammerJs binds the event to the window? // causing these events to propagate to other components? @@ -255,8 +266,11 @@ let initialZoom; let initialDistance; let offsetAtPanStart; + let startX; + let isZooming; const scroll = (ev) => { + if (ev.center.x - startX === 0) return; if (zoomGestureJustEnded) { zoomGestureJustEnded = false; console.log("Skip this event: likely a single touch dangling from pinch"); @@ -268,18 +282,22 @@ }; const zoom = (ev) => { + if (ev.touches.length < 2) return; const minZoom = componentTimeline.state.minZoom; const maxZoom = componentTimeline.state.maxZoom; - const distance = calculateDistance({ - x: ev.pointers[0].clientX, - y: ev.pointers[0].clientY - }, { - x: ev.pointers[1].clientX, - y: ev.pointers[1].clientY - }); + const p1: Point = { + x: ev.touches[0].clientX, + y: ev.touches[0].clientY + }; + const p2: Point = { + x: ev.touches[1].clientX, + y: ev.touches[1].clientY + }; + const distance = calculateDistance(p1, p2); + const midPoint = calculateMidPoint(p1, p2); const lastCenterTime = - componentTimeline.timeContext.timeToPixel.invert(ev.center.x); + componentTimeline.timeContext.timeToPixel.invert(midPoint.x); const exponent = pixelToExponent(distance - initialDistance); const targetZoom = initialZoom * Math.pow(2, exponent); @@ -288,32 +306,40 @@ Math.min(Math.max(targetZoom, minZoom), maxZoom); const newCenterTime = - componentTimeline.timeContext.timeToPixel.invert(ev.center.x); + componentTimeline.timeContext.timeToPixel.invert(midPoint.x); componentTimeline.timeContext.offset += newCenterTime - lastCenterTime; componentTimeline.tracks.update(); }; - hammertime.get('pinch').set({ enable: true }); - hammertime.on('panstart', () => { + hammertime.on('panstart', (ev) => { offsetAtPanStart = componentTimeline.timeContext.offset; + startX = ev.center.x; }); hammertime.on('panleft', scroll); hammertime.on('panright', scroll); - hammertime.on('pinchstart', (e) => { + + + const element: HTMLElement = this.trackDiv.nativeElement; + element.addEventListener('touchstart', (e) => { + if (e.touches.length < 2) return; + isZooming = true; initialZoom = componentTimeline.timeContext.zoom; initialDistance = calculateDistance({ - x: e.pointers[0].clientX, - y: e.pointers[0].clientY + x: e.touches[0].clientX, + y: e.touches[0].clientY }, { - x: e.pointers[1].clientX, - y: e.pointers[1].clientY + x: e.touches[1].clientX, + y: e.touches[1].clientY }); }); - hammertime.on('pinch', zoom); - hammertime.on('pinchend', () => { - zoomGestureJustEnded = true; - }); + element.addEventListener('touchend', () => { + if (isZooming) { + isZooming = false; + zoomGestureJustEnded = true; + } + }); + element.addEventListener('touchmove', zoom); } // this.timeline.createTrack(track, height/2, `wave-${this.trackIdPrefix}`); // this.timeline.createTrack(track, height/2, `grid-${this.trackIdPrefix}`);