Skip to content

Commit

Permalink
Implement basic keyboard support for camera orbit
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Joel authored and cdata committed Nov 30, 2018
1 parent e078540 commit 85c4f42
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/features/controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
import {PerspectiveCamera, Vector3} from 'three';

import {$needsRender, $onModelLoad, $onResize, $scene} from '../model-viewer-base.js';
import OrbitControls from '../third_party/three/OrbitControls.js';
import {FRAMED_HEIGHT} from '../three-components/ModelScene.js';
import {PatchedOrbitControls} from '../three-components/PatchedOrbitControls.js';

const ORBIT_NEAR_PLANE = 0.01;
const ORBIT_FAR_PLANE = 1000;
Expand Down Expand Up @@ -58,7 +58,7 @@ export const ControlsMixin = (ModelViewerElement) => {
this[$scene].setCamera(this[$orbitCamera]);

this[$controls] =
new OrbitControls(this[$orbitCamera], this[$scene].canvas);
new PatchedOrbitControls(this[$orbitCamera], this[$scene].canvas);
this[$controls].target.set(0, FRAMED_HEIGHT / 2, 0);
this[$controls].enabled = true;
// Panning performed via right click, two finger move
Expand Down
9 changes: 9 additions & 0 deletions src/third_party/three/OrbitControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ const OrbitControls = function ( object, domElement ) {

};

/**
* NOTE(cdata): This method is added to enable further patching in a
* subclass.
* @see src/three-components/PatchedOrbitControls.js
*/
this.getSphericalDelta = function () {
return sphericalDelta;
};

// this method is exposed, but perhaps it would be better if we can make it private...
this.update = function () {

Expand Down
83 changes: 83 additions & 0 deletions src/three-components/PatchedOrbitControls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright 2018 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import OrbitControls from '../third_party/three/OrbitControls.js';

const $onKeyDown = Symbol('onKeyDown');

const KEYBOARD_ORBIT_INCREMENT = Math.PI / 10;

/**
* This patched extension of OrbitControls adds automatic support for
* controlling the orbit of the camera with the keyboard arrows when the
* element is focused.
*/
export class PatchedOrbitControls extends OrbitControls {
constructor(...args) {
super(...args);

this[$onKeyDown] = (event) => this.onKeyDown(event);
this.domElement.addEventListener('keydown', this[$onKeyDown]);
}

dispose() {
super.dispose();
this.domElement.removeEventListener('keydown', this[$onKeyDown]);
}

onKeyDown(event) {
let handled = false;

switch (event.keyCode) {
case this.keys.UP:
this.orbitUp(KEYBOARD_ORBIT_INCREMENT);
handled = true;
break;
case this.keys.BOTTOM:
this.orbitDown(KEYBOARD_ORBIT_INCREMENT);
handled = true;
break;
case this.keys.LEFT:
this.orbitLeft(KEYBOARD_ORBIT_INCREMENT);
handled = true;
break;
case this.keys.RIGHT:
this.orbitRight(KEYBOARD_ORBIT_INCREMENT);
handled = true;
break;
}

if (handled) {
event.preventDefault();
this.update();
}
}

orbitUp(increment) {
this.getSphericalDelta().phi += increment;
}

orbitDown(increment) {
this.getSphericalDelta().phi -= increment;
}

orbitLeft(increment) {
this.getSphericalDelta().theta += increment;
}

orbitRight(increment) {
this.getSphericalDelta().theta -= increment;
}
}

0 comments on commit 85c4f42

Please sign in to comment.