diff --git a/src/mol-gl/controls/trackball.ts b/src/mol-gl/controls/trackball.ts index 6a61703bce30717fc3d77ec860b167dec20ccffb..57bd3baa468bdd844fcdc9133a20c527c2d39697 100644 --- a/src/mol-gl/controls/trackball.ts +++ b/src/mol-gl/controls/trackball.ts @@ -11,7 +11,7 @@ import { Quat, Vec2, Vec3, EPSILON } from 'mol-math/linear-algebra'; import { cameraLookAt, Viewport } from '../camera/util'; -import InputObserver, { DragInput, WheelInput, MouseButtonsFlag, PinchInput } from 'mol-util/input/input-observer'; +import InputObserver, { DragInput, WheelInput, ButtonsFlag, PinchInput } from 'mol-util/input/input-observer'; export const DefaultTrackballControlsProps = { noScroll: true, @@ -79,8 +79,8 @@ namespace TrackballControls { const _zoomStart = Vec2.zero() const _zoomEnd = Vec2.zero() - // let _touchZoomDistanceStart = 0 - // let _touchZoomDistanceEnd = 0 + let _touchZoomDistanceStart = 0 + let _touchZoomDistanceEnd = 0 const _panStart = Vec2.zero() const _panEnd = Vec2.zero() @@ -156,26 +156,8 @@ namespace TrackballControls { Vec2.copy(_movePrev, _moveCurr) } - function zoomCamera () { - // if (_state === STATE.TOUCH_ZOOM_PAN) { - // const factor = _touchZoomDistanceStart / _touchZoomDistanceEnd - // _touchZoomDistanceStart = _touchZoomDistanceEnd; - // Vec3.scale(_eye, _eye, factor) - // } else { - // const factor = 1.0 + ( _zoomEnd[1] - _zoomStart[1] ) * zoomSpeed - // if (factor !== 1.0 && factor > 0.0) { - // Vec3.scale(_eye, _eye, factor) - // } - - // if (staticMoving) { - // Vec2.copy(_zoomStart, _zoomEnd) - // } else { - // _zoomStart[1] += ( _zoomEnd[1] - _zoomStart[1] ) * dynamicDampingFactor - // } - // } - - const factor = 1.0 + ( _zoomEnd[1] - _zoomStart[1] ) * zoomSpeed + const factor = 1.0 + (_zoomEnd[1] - _zoomStart[1]) * zoomSpeed if (factor !== 1.0 && factor > 0.0) { Vec3.scale(_eye, _eye, factor) } @@ -183,7 +165,7 @@ namespace TrackballControls { if (staticMoving) { Vec2.copy(_zoomStart, _zoomEnd) } else { - _zoomStart[1] += ( _zoomEnd[1] - _zoomStart[1] ) * dynamicDampingFactor + _zoomStart[1] += (_zoomEnd[1] - _zoomStart[1]) * dynamicDampingFactor } } @@ -231,7 +213,7 @@ namespace TrackballControls { } function update() { - Vec3.sub( _eye, object.position, target) + Vec3.sub(_eye, object.position, target) rotateCamera() zoomCamera() @@ -260,26 +242,26 @@ namespace TrackballControls { // listeners - function onDrag({ pageX, pageY, buttons, modifiers, started }: DragInput) { - if (started) { - if (buttons === MouseButtonsFlag.Primary) { + function onDrag({ pageX, pageY, buttons, modifiers, isStart }: DragInput) { + if (isStart) { + if (buttons === ButtonsFlag.Primary) { Vec2.copy(_moveCurr, getMouseOnCircle(pageX, pageY)) Vec2.copy(_movePrev, _moveCurr) - } else if (buttons === MouseButtonsFlag.Auxilary) { + } else if (buttons === ButtonsFlag.Auxilary) { Vec2.copy(_zoomStart, getMouseOnScreen(pageX, pageY)) Vec2.copy(_zoomEnd, _zoomStart) - } else if (buttons === MouseButtonsFlag.Secondary) { + } else if (buttons === ButtonsFlag.Secondary) { Vec2.copy(_panStart, getMouseOnScreen(pageX, pageY)) Vec2.copy(_panEnd, _panStart) } } - if (buttons === MouseButtonsFlag.Primary) { + if (buttons === ButtonsFlag.Primary) { Vec2.copy(_movePrev, _moveCurr) Vec2.copy(_moveCurr, getMouseOnCircle(pageX, pageY)) - } else if (buttons === MouseButtonsFlag.Auxilary) { + } else if (buttons === ButtonsFlag.Auxilary) { Vec2.copy(_zoomEnd, getMouseOnScreen(pageX, pageY)) - } else if (buttons === MouseButtonsFlag.Secondary) { + } else if (buttons === ButtonsFlag.Secondary) { Vec2.copy(_panEnd, getMouseOnScreen(pageX, pageY)) } } @@ -288,81 +270,23 @@ namespace TrackballControls { _zoomStart[1] -= dy } - function onPinch({ delta }: PinchInput) { - console.log(delta) - _zoomStart[1] -= delta - } + function onPinch({ distance, isStart }: PinchInput) { + if (isStart) { + _touchZoomDistanceStart = distance + } + _touchZoomDistanceEnd = distance - // function touchstart(event: TouchEvent ) { - // switch ( event.touches.length ) { - // case 1: - // // _state = STATE.TOUCH_ROTATE; - // Vec2.copy(_moveCurr, getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY)) - // Vec2.copy(_movePrev, _moveCurr) - // break; - // default: // 2 or more - // // _state = STATE.TOUCH_ZOOM_PAN; - // const dx = event.touches[0].pageX - event.touches[1].pageX; - // const dy = event.touches[0].pageY - event.touches[1].pageY; - // _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt(dx * dx + dy * dy); - - // const x = ( event.touches[0].pageX + event.touches[1].pageX) / 2; - // const y = ( event.touches[0].pageY + event.touches[1].pageY) / 2; - // Vec2.copy(_panStart, getMouseOnScreen(x, y)) - // Vec2.copy(_panEnd, _panStart) - // break; - // } - // } - - // function touchmove(event: TouchEvent) { - // event.preventDefault(); - // event.stopPropagation(); - - // switch ( event.touches.length ) { - // case 1: - // Vec2.copy(_movePrev, _moveCurr) - // Vec2.copy(_moveCurr, getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY)) - // break; - // default: // 2 or more - // const dx = event.touches[0].pageX - event.touches[1].pageX; - // const dy = event.touches[0].pageY - event.touches[1].pageY; - // _touchZoomDistanceEnd = Math.sqrt(dx * dx + dy * dy); - - // const x = (event.touches[0].pageX + event.touches[1].pageX) / 2; - // const y = (event.touches[0].pageY + event.touches[1].pageY) / 2; - // Vec2.copy(_panEnd, getMouseOnScreen(x, y)) - // break; - // } - // } - - // function touchend(event: TouchEvent) { - // switch ( event.touches.length ) { - // case 0: - // // _state = STATE.NONE; - // break; - // case 1: - // // _state = STATE.TOUCH_ROTATE; - // Vec2.copy(_moveCurr, getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY)) - // Vec2.copy(_movePrev, _moveCurr) - // break; - - // } - // } + const factor = (_touchZoomDistanceStart / _touchZoomDistanceEnd) * zoomSpeed + _touchZoomDistanceStart = _touchZoomDistanceEnd; + Vec3.scale(_eye, _eye, factor) + } function dispose() { if (disposed) return disposed = true input.dispose() - - // element.removeEventListener( 'touchstart', touchstart as any, false ); - // element.removeEventListener( 'touchend', touchend as any, false ); - // element.removeEventListener( 'touchmove', touchmove as any, false ); } - // element.addEventListener( 'touchstart', touchstart as any, false ); - // element.addEventListener( 'touchend', touchend as any, false ); - // element.addEventListener( 'touchmove', touchmove as any, false ); - // force an update at start update(); diff --git a/src/mol-util/input/input-observer.ts b/src/mol-util/input/input-observer.ts index feaacce2ac38108a3aab1d4fd37cccf8c9328eb1..4c070703c79742068f8a627900a0fe4075b4d216 100644 --- a/src/mol-util/input/input-observer.ts +++ b/src/mol-util/input/input-observer.ts @@ -9,7 +9,6 @@ import { Subject } from 'rxjs'; import { Vec2 } from 'mol-math/linear-algebra'; import toPixels from '../to-pixels' -import TouchPinch from './touch-pinch' function getButtons(event: MouseEvent | Touch) { if (typeof event === 'object') { @@ -51,7 +50,7 @@ export type ModifiersKeys = { meta: boolean } -export const enum MouseButtonsFlag { +export const enum ButtonsFlag { /** No button or un-initialized */ None = 0x0, /** Primary button (usually left) */ @@ -78,7 +77,7 @@ export type DragInput = { dy: number, pageX: number, pageY: number, - started: boolean + isStart: boolean } & BaseInput export type WheelInput = { @@ -96,7 +95,8 @@ export type ClickInput = { export type PinchInput = { delta: number, - distance: number + distance: number, + isStart: boolean } const enum DraggingState { @@ -142,8 +142,6 @@ namespace InputObserver { meta: false } - // const touchPinch = TouchPinch.create(element) - let dragging: DraggingState = DraggingState.Stopped let disposed = false let buttons = 0 @@ -183,10 +181,6 @@ namespace InputObserver { element.addEventListener('touchmove', onTouchMove as any, false) element.addEventListener('touchend', onTouchEnd as any, false) - // touchPinch.place.subscribe(onPinchPlace) - // touchPinch.lift.subscribe(onPinchLift) - // touchPinch.change.subscribe(onPinchChange) - element.addEventListener('blur', handleBlur) element.addEventListener('keyup', handleMods as EventListener) element.addEventListener('keydown', handleMods as EventListener) @@ -197,8 +191,6 @@ namespace InputObserver { if (disposed) return disposed = true - // touchPinch.dispose() - element.removeEventListener( 'contextmenu', onContextMenu, false ) element.removeEventListener('wheel', onMouseWheel, false) @@ -260,79 +252,43 @@ namespace InputObserver { function onTouchStart (ev: TouchEvent) { preventDefault(ev) - console.log('onTouchStart', ev) if (ev.touches.length === 1) { - buttons = MouseButtonsFlag.Primary + buttons = ButtonsFlag.Primary onPointerDown(ev.touches[0]) } else if (ev.touches.length >= 2) { - buttons = MouseButtonsFlag.Secondary + buttons = ButtonsFlag.Secondary onPointerDown(getCenterTouch(ev)) - let lastTouchDistance = getTouchDistance(ev) - pinch.next({ distance: lastTouchDistance, delta: 0 }) + pinch.next({ distance: lastTouchDistance, delta: 0, isStart: true }) } } function onTouchEnd (ev: TouchEvent) { preventDefault(ev) - - console.log('onTouchEnd', ev) } function onTouchMove (ev: TouchEvent) { preventDefault(ev) if (ev.touches.length === 1) { - buttons = MouseButtonsFlag.Primary + buttons = ButtonsFlag.Primary onPointerMove(ev.touches[0]) } else if (ev.touches.length >= 2) { - buttons = MouseButtonsFlag.Secondary - onPointerDown(getCenterTouch(ev)) - const touchDistance = getTouchDistance(ev) - pinch.next({ delta: lastTouchDistance - touchDistance, distance: touchDistance }) + if (lastTouchDistance - touchDistance < 4) { + buttons = ButtonsFlag.Secondary + onPointerMove(getCenterTouch(ev)) + } else { + pinch.next({ + delta: lastTouchDistance - touchDistance, + distance: touchDistance, + isStart: false + }) + } lastTouchDistance = touchDistance } - - // if (dragging === DraggingState.Stopped || isPinching()) return - - // // find currently active finger - // for (let i = 0; i < ev.changedTouches.length; i++) { - // const changed = ev.changedTouches[i] - // const idx = touchPinch.indexOfTouch(changed) - // if (idx !== -1) { - // onInputMove(changed) - // break - // } - // } } - // function onPinchPlace ({ newTouch, oldTouch }: { newTouch?: Touch, oldTouch?: Touch }) { - // dragging = isPinching() ? DraggingState.Stopped : DraggingState.Started - // if (dragging === DraggingState.Started) { - // const firstFinger = oldTouch || newTouch - // if (firstFinger) onInputDown(firstFinger) - // } - // } - - // function onPinchLift ({ removed, otherTouch }: { removed?: Touch, otherTouch?: Touch }) { - // // if either finger is down, consider it dragging - // const sum = touchPinch.fingers.reduce((sum, item) => sum + (item ? 1 : 0), 0) - // dragging = sum >= 1 ? DraggingState.Moving : DraggingState.Stopped - - // if (dragging && otherTouch) { - // eventOffset(mouseStart, otherTouch, element) - // } - // } - - // function isPinching () { - // return touchPinch.pinching - // } - - // function onPinchChange ({ currentDistance, lastDistance }: { currentDistance: number, lastDistance: number }) { - // pinch.next({ delta: currentDistance - lastDistance }) - // } - function onMouseDown (ev: MouseEvent) { preventDefault(ev) @@ -370,27 +326,21 @@ namespace InputObserver { const { pageX, pageY } = ev const [ x, y ] = pointerEnd - console.log('click', { x, y, pageX, pageY, buttons, modifiers }) click.next({ x, y, pageX, pageY, buttons, modifiers }) } } function onPointerMove (ev: PointerEvent) { eventOffset(pointerEnd, ev) - // if (pinch && isPinching()) { - // Vec2.copy(pointerStart, pointerEnd) - // return - // } if (dragging === DraggingState.Stopped) return Vec2.div(pointerDelta, Vec2.sub(pointerDelta, pointerEnd, pointerStart), getClientSize(rectSize)) - const started = dragging === DraggingState.Started + const isStart = dragging === DraggingState.Started const { pageX, pageY } = ev const [ x, y ] = pointerEnd const [ dx, dy ] = pointerDelta - // console.log({ x, y, dx, dy, pageX, pageY, buttons, modifiers, started }) - drag.next({ x, y, dx, dy, pageX, pageY, buttons, modifiers, started }) + drag.next({ x, y, dx, dy, pageX, pageY, buttons, modifiers, isStart }) Vec2.copy(pointerStart, pointerEnd) dragging = DraggingState.Moving diff --git a/src/mol-util/input/touch-pinch.ts b/src/mol-util/input/touch-pinch.ts deleted file mode 100644 index 7c4b12d3e2602944c21ecfa5103094e3a96be658..0000000000000000000000000000000000000000 --- a/src/mol-util/input/touch-pinch.ts +++ /dev/null @@ -1,188 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -/* - * This code has been modified (use TypeScript, RxJS) from https://github.com/Jam3/touch-pinch, - * copyright (c) 2014 Matt DesLauriers. MIT License - */ - -import { Subject } from 'rxjs'; - -import { Vec2 } from 'mol-math/linear-algebra'; -import { eventOffset } from './event-offset' - -interface Finger { - position: Vec2, - touch?: Touch -} - -function Finger (): Finger { - return { - position: Vec2.zero(), - touch: undefined - } -} - -interface TouchPinch { - pinching: boolean - fingers: (Finger|undefined)[] - indexOfTouch: (touch: Touch) => number - - start: Subject<number> - end: Subject<void> - place: Subject<{ newTouch?: Touch, oldTouch?: Touch}> - change: Subject<{ currentDistance: number, lastDistance: number }> - lift: Subject<{ removed: Touch, otherTouch?: Touch }> - - dispose: () => void -} - -namespace TouchPinch { - export function create (target: Element): TouchPinch { - const fingers: (Finger|undefined)[] = [] - let activeCount = 0 - - let lastDistance = 0 - let ended = false - let disposed = false - - const start = new Subject<number>() - const end = new Subject<void>() - const place = new Subject<{ newTouch?: Touch, oldTouch?: Touch}>() - const change = new Subject<{ currentDistance: number, lastDistance: number }>() - const lift = new Subject<{ removed: Touch, otherTouch?: Touch }>() - - target.addEventListener('touchstart', onTouchStart as any, false) - target.addEventListener('touchmove', onTouchMove as any, false) - target.addEventListener('touchend', onTouchRemoved as any, false) - target.addEventListener('touchcancel', onTouchRemoved as any, false) - - return { - get pinching() { return activeCount === 2 }, - fingers, - indexOfTouch, - - start, - end, - place, - change, - lift, - - dispose - } - - function indexOfTouch (touch: Touch) { - const id = touch.identifier - for (let i = 0; i < fingers.length; i++) { - const finger = fingers[i] - if (finger && finger.touch && finger.touch.identifier === id) { - return i - } - } - return -1 - } - - function dispose () { - if (disposed) return - disposed = true - activeCount = 0 - fingers[0] = undefined - fingers[1] = undefined - lastDistance = 0 - ended = false - target.removeEventListener('touchstart', onTouchStart as any, false) - target.removeEventListener('touchmove', onTouchMove as any, false) - target.removeEventListener('touchend', onTouchRemoved as any, false) - target.removeEventListener('touchcancel', onTouchRemoved as any, false) - } - - function onTouchStart (ev: TouchEvent) { - for (let i = 0; i < ev.changedTouches.length; i++) { - const newTouch = ev.changedTouches[i] - const idx = indexOfTouch(newTouch) - - if (idx === -1 && activeCount < 2) { - const first = activeCount === 0 - - // newest and previous finger (previous may be undefined) - const newIndex = fingers[0] ? 1 : 0 - const oldIndex = fingers[0] ? 0 : 1 - const newFinger = Finger() - - // add to stack - fingers[newIndex] = newFinger - activeCount++ - - // update touch event & position - newFinger.touch = newTouch - eventOffset(newFinger.position, newTouch, target) - - const finger = fingers[oldIndex] - const oldTouch = finger ? finger.touch : undefined - place.next({ newTouch, oldTouch }) - - if (!first) { - const initialDistance = computeDistance() - ended = false - start.next(initialDistance) - lastDistance = initialDistance - } - } - } - } - - function onTouchMove (ev: TouchEvent) { - let changed = false - for (let i = 0; i < ev.changedTouches.length; i++) { - const movedTouch = ev.changedTouches[i] - const idx = indexOfTouch(movedTouch) - if (idx !== -1) { - const finger = fingers[idx] - if (finger) { - changed = true - finger.touch = movedTouch // avoid caching touches - eventOffset(finger.position, movedTouch, target) - } - } - } - - if (activeCount === 2 && changed) { - const currentDistance = computeDistance() - change.next({ currentDistance, lastDistance }) - lastDistance = currentDistance - } - } - - function onTouchRemoved (ev: TouchEvent) { - for (let i = 0; i < ev.changedTouches.length; i++) { - const removed = ev.changedTouches[i] - const idx = indexOfTouch(removed) - if (idx !== -1) { - fingers[idx] = undefined - activeCount-- - const otherIdx = idx === 0 ? 1 : 0 - const finger = fingers[otherIdx] - if (finger) { - const otherTouch = finger ? finger.touch : undefined - lift.next({ removed, otherTouch }) - } - } - } - - if (!ended && activeCount !== 2) { - ended = true - end.next() - } - } - - function computeDistance () { - const [ f1, f2 ] = fingers - return (f1 && f2) ? Vec2.distance(f1.position, f2.position) : 0 - } - } -} - -export default TouchPinch \ No newline at end of file