in src/component/keyboard/KeySpatialNavigationHandler.ts [68:142]
protected _enable(): void {
const spatialEdges$: Observable<NavigationEdgeStatus> = this._navigator.stateService.currentImage$.pipe(
switchMap(
(image: Image): Observable<NavigationEdgeStatus> => {
return image.spatialEdges$;
}));
this._keyDownSubscription = this._container.keyboardService.keyDown$.pipe(
withLatestFrom(
spatialEdges$,
this._navigator.stateService.currentState$))
.subscribe(([event, edgeStatus, frame]: [KeyboardEvent, NavigationEdgeStatus, AnimationFrame]): void => {
let spherical = isSpherical(frame.state.currentImage.cameraType);
let direction: NavigationDirection = null;
switch (event.keyCode) {
case 37: // left
direction = event.shiftKey && !spherical ? NavigationDirection.TurnLeft : NavigationDirection.StepLeft;
break;
case 38: // up
direction = event.shiftKey && !spherical ? NavigationDirection.Spherical : NavigationDirection.StepForward;
break;
case 39: // right
direction = event.shiftKey && !spherical ? NavigationDirection.TurnRight : NavigationDirection.StepRight;
break;
case 40: // down
direction = event.shiftKey && !spherical ? NavigationDirection.TurnU : NavigationDirection.StepBackward;
break;
default:
return;
}
event.preventDefault();
if (event.altKey || !edgeStatus.cached ||
(event.shiftKey && spherical)) {
return;
}
if (!spherical) {
this._moveDir(direction, edgeStatus);
} else {
const shifts: { [dir: number]: number } = {};
shifts[NavigationDirection.StepBackward] = Math.PI;
shifts[NavigationDirection.StepForward] = 0;
shifts[NavigationDirection.StepLeft] = Math.PI / 2;
shifts[NavigationDirection.StepRight] = -Math.PI / 2;
const phi: number = this._rotationFromCamera(frame.state.camera).phi;
const navigationAngle: number = this._spatial.wrapAngle(phi + shifts[direction]);
const threshold: number = Math.PI / 4;
const edges: NavigationEdge[] = edgeStatus.edges.filter(
(e: NavigationEdge): boolean => {
return e.data.direction === NavigationDirection.Spherical || e.data.direction === direction;
});
let smallestAngle: number = Number.MAX_VALUE;
let toKey: string = null;
for (const edge of edges) {
const angle: number = Math.abs(this._spatial.wrapAngle(edge.data.worldMotionAzimuth - navigationAngle));
if (angle < Math.min(smallestAngle, threshold)) {
smallestAngle = angle;
toKey = edge.target;
}
}
if (toKey == null) {
return;
}
this._moveTo(toKey);
}
});
}