Mercurial > hg > ugly-duckling
view src/app/visualisations/WavesJunk.ts @ 509:041468f553e1 tip master
Merge pull request #57 from LucasThompson/fix/session-stack-max-call-stack
Fix accidental recursion in PersistentStack
author | Lucas Thompson <LucasThompson@users.noreply.github.com> |
---|---|
date | Mon, 27 Nov 2017 11:04:30 +0000 |
parents | 82d476b976e0 |
children |
line wrap: on
line source
/** * Created by lucast on 24/05/2017. */ import wavesUI from 'waves-ui-piper'; import * as Hammer from 'hammerjs'; import {TimePixelMapper} from '../playhead/PlayHeadHelpers'; // TODO this is named as such as a reminder that it needs to be re-factored export function attachTouchHandlerBodges(element: HTMLElement, timeline: Timeline) { interface Point { x: number; y: number; } let zoomGestureJustEnded = false; const pixelToExponent: Function = wavesUI.utils.scales.linear() .domain([0, 100]) // 100px => factor 2 .range([0, 1]); const calculateDistance: (p1: Point, p2: Point) => number = (p1, p2) => { return Math.pow( Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2), 0.5); }; 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(element, { recognizers: [ [Hammer.Pan, { direction: Hammer.DIRECTION_HORIZONTAL }] ] }); // it seems HammerJs binds the event to the window? // causing these events to propagate to other components? 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'); return; } timeline.timeContext.offset = offsetAtPanStart + timeline.timeContext.timeToPixel.invert(ev.deltaX); timeline.tracks.update(); }; const zoom = (ev) => { if (ev.touches.length < 2) { return; } ev.preventDefault(); const minZoom = timeline.state.minZoom; const maxZoom = timeline.state.maxZoom; 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 = timeline.timeContext.timeToPixel.invert(midPoint.x); const exponent = pixelToExponent(distance - initialDistance); const targetZoom = initialZoom * Math.pow(2, exponent); timeline.timeContext.zoom = Math.min(Math.max(targetZoom, minZoom), maxZoom); const newCenterTime = timeline.timeContext.timeToPixel.invert(midPoint.x); timeline.timeContext.offset += newCenterTime - lastCenterTime; timeline.tracks.update(); }; hammertime.on('panstart', (ev) => { offsetAtPanStart = timeline.timeContext.offset; startX = ev.center.x; }); hammertime.on('panleft', scroll); hammertime.on('panright', scroll); element.addEventListener('touchstart', (e) => { if (e.touches.length < 2) { return; } isZooming = true; initialZoom = timeline.timeContext.zoom; initialDistance = calculateDistance({ x: e.touches[0].clientX, y: e.touches[0].clientY }, { x: e.touches[1].clientX, y: e.touches[1].clientY }); }); element.addEventListener('touchend', () => { if (isZooming) { isZooming = false; zoomGestureJustEnded = true; } }); element.addEventListener('touchmove', zoom); } export function naivePagingMapper(timeline: Timeline): TimePixelMapper { return (currentTime: number) => { const currentOffset = timeline.timeContext.offset; const offsetTimestamp = currentOffset + currentTime; const visibleDuration = timeline.timeContext.visibleDuration; const mustPageForward = offsetTimestamp > visibleDuration; const mustPageBackward = currentTime < -currentOffset; if (mustPageForward) { const hasSkippedMultiplePages = offsetTimestamp - visibleDuration > visibleDuration; timeline.timeContext.offset = hasSkippedMultiplePages ? -currentTime + 0.5 * visibleDuration : currentOffset - visibleDuration; } if (mustPageBackward) { const hasSkippedMultiplePages = currentTime + visibleDuration < -currentOffset; timeline.timeContext.offset = hasSkippedMultiplePages ? -currentTime + 0.5 * visibleDuration : currentOffset + visibleDuration; } if (mustPageForward || mustPageBackward) { timeline.tracks.update(); } // return timeline.timeContext.timeToPixel(timeline.offset + currentTime); }; }