-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathThreeDOFControls.ts
108 lines (99 loc) · 3.63 KB
/
ThreeDOFControls.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { BaseControls } from './BaseControls'
import { CameraRig, CameraAction, RigComponent } from '../CameraRig'
import { PointerAdaptor } from '../adaptors/PointerAdaptor'
/**
* Properties that can be passed to the {@link three-story-controls#ThreeDOFControls} constructor
*/
//TODO: add option for relative or absolute control (in terms of screen space)
export interface ThreeDOFControlsProps {
/** DOM element that should listen for pointer events. Defaults to `document.body` */
domElement?: HTMLElement
/** Mutiplier for panning. Defaults to Math.PI / 20 */
panFactor?: number
/** Mutiplier for tilting. Defaults to Math.PI / 20 */
tiltFactor?: number
/** Mutiplier for truck translation. Defaults to 1 */
truckFactor?: number
/** Mutiplier for pedestal translation. Defaults to 1 */
pedestalFactor?: number
/** Damping factor between 0 and 1. Defaults to 0.7 */
dampingFactor?: number
}
const defaultProps: ThreeDOFControlsProps = {
domElement: document.body,
panFactor: Math.PI / 20,
tiltFactor: Math.PI / 20,
truckFactor: 1,
pedestalFactor: 1,
dampingFactor: 0.7,
}
/**
* Control scheme for slight rotation and translation movement in response to mouse movements (designed to be used in conjunction with other control schemes)
* @remarks
* Note: CSS property `touch-action: none` will probably be needed on listener element
*
* See {@link three-story-controls#ThreeDOFControlsProps} for all properties that can be passed to the constructor.
*
* {@link https://nytimes.github.io/three-story-controls/examples/demos/story-points/ | DEMO w/ story points }
*
* {@link https://nytimes.github.io/three-story-controls/examples/demos/scroll-controls/ | DEMO w/ scroll controls}
*
* @example
* ```js
* const scene = new Scene()
* const camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
* const cameraRig = new CameraRig(camera, scene)
* const controls = new ThreeDOFControls(cameraRig)
*
* controls.enable()
*
* // render loop
* function animate(t) {
* controls.update(t)
* }
* ```
*/
export class ThreeDOFControls implements BaseControls {
readonly cameraRig: CameraRig
private pointerAdaptor: PointerAdaptor
private enabled = false
private panFactor: number
private tiltFactor: number
private truckFactor: number
private pedestalFactor: number
constructor(cameraRig: CameraRig, props: ThreeDOFControlsProps = {}) {
this.cameraRig = cameraRig
Object.assign(this, defaultProps, props)
this.pointerAdaptor = new PointerAdaptor({
domElement: props.domElement || defaultProps.domElement,
dampingFactor: props.dampingFactor || defaultProps.dampingFactor,
})
this.onPointerMove = this.onPointerMove.bind(this)
}
isEnabled(): boolean {
return this.enabled
}
enable(): void {
this.pointerAdaptor.connect()
this.pointerAdaptor.addEventListener('update', this.onPointerMove)
this.enabled = true
}
disable(): void {
this.pointerAdaptor.disconnect()
this.pointerAdaptor.removeEventListener('update', this.onPointerMove)
this.enabled = false
}
update(time: number): void {
if (this.enabled) {
this.pointerAdaptor.update(time)
}
}
private onPointerMove(event): void {
if (event.pointerCount === 0) {
this.cameraRig.do(CameraAction.Pan, -event.deltas.x * this.panFactor, RigComponent.Eyes)
this.cameraRig.do(CameraAction.Tilt, -event.deltas.y * this.tiltFactor, RigComponent.Eyes)
this.cameraRig.do(CameraAction.Truck, event.deltas.x * this.truckFactor, RigComponent.Eyes)
this.cameraRig.do(CameraAction.Pedestal, event.deltas.y * this.pedestalFactor, RigComponent.Eyes)
}
}
}