Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions modules/core/src/controllers/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,19 @@
// THE SOFTWARE.

/* eslint-disable max-statements, complexity */
import TransitionManager from './transition-manager';
import TransitionManager, {TRANSITION_EVENTS} from './transition-manager';
import LinearInterpolator from '../transitions/linear-interpolator';

const NO_TRANSITION_PROPS = {
transitionDuration: 0
};

const LINEAR_TRANSITION_PROPS = {
transitionDuration: 300,
transitionEasing: t => t,
transitionInterruption: TRANSITION_EVENTS.BREAK
};

const DEFAULT_INERTIA = 300;
const INERTIA_EASING = t => 1 - (1 - t) * (1 - t);

Expand All @@ -48,6 +55,15 @@ export default class Controller {
onViewStateChange: this._onTransition.bind(this),
onStateChange: this._setInteractionState.bind(this)
});

const linearTransitionProps = this.linearTransitionProps;
this._transition = linearTransitionProps && {
...LINEAR_TRANSITION_PROPS,
transitionInterpolator: new LinearInterpolator({
transitionProps: linearTransitionProps
})
};

this._events = null;
this._interactionState = {
isDragging: false
Expand All @@ -61,6 +77,10 @@ export default class Controller {
this.setProps(options);
}

get linearTransitionProps() {
return null;
}

set events(customEvents) {
this.toggleEvents(this._customEvents, false);
this.toggleEvents(customEvents, true);
Expand Down Expand Up @@ -688,8 +708,23 @@ export default class Controller {
return true;
}

_getTransitionProps() {
// Transitions on double-tap and key-down are only supported by MapController
return NO_TRANSITION_PROPS;
_getTransitionProps(opts) {
const {_transition} = this;

if (!_transition) {
return NO_TRANSITION_PROPS;
}

// Enables Transitions on double-tap and key-down events.
return opts
? {
..._transition,
transitionInterpolator: new LinearInterpolator({
...opts,
transitionProps: this.linearTransitionProps,
makeViewport: this.controllerState.makeViewport
})
}
: _transition;
}
}
14 changes: 2 additions & 12 deletions modules/core/src/controllers/first-person-controller.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import Controller from './controller';
import ViewState from './view-state';
import {mod} from '../utils/math-utils';
import LinearInterpolator from '../transitions/linear-interpolator';
import {TRANSITION_EVENTS} from './transition-manager';

import {Vector3, _SphericalCoordinates as SphericalCoordinates, clamp} from 'math.gl';

Expand All @@ -15,13 +13,6 @@ const DEFAULT_STATE = {
minPitch: -90
};

const LINEAR_TRANSITION_PROPS = {
transitionDuration: 300,
transitionEasing: t => t,
transitionInterpolator: new LinearInterpolator(['position', 'pitch', 'bearing']),
transitionInterruption: TRANSITION_EVENTS.BREAK
};

class FirstPersonState extends ViewState {
constructor({
/* Viewport arguments */
Expand Down Expand Up @@ -303,8 +294,7 @@ export default class FirstPersonController extends Controller {
super(FirstPersonState, props);
}

_getTransitionProps() {
// Enables Transitions on double-tap and key-down events.
return LINEAR_TRANSITION_PROPS;
get linearTransitionProps() {
return ['position', 'pitch', 'bearing'];
}
}
14 changes: 2 additions & 12 deletions modules/core/src/controllers/globe-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,6 @@ import Controller from './controller';

import {MapState} from './map-controller';
import {mod} from '../utils/math-utils';
import LinearInterpolator from '../transitions/linear-interpolator';
import {TRANSITION_EVENTS} from './transition-manager';

const LINEAR_TRANSITION_PROPS = {
transitionDuration: 300,
transitionEasing: t => t,
transitionInterpolator: new LinearInterpolator(['longitude', 'latitude', 'zoom']),
transitionInterruption: TRANSITION_EVENTS.BREAK
};

class GlobeState extends MapState {
// Apply any constraints (mathematical or defined by _viewportProps) to map state
Expand Down Expand Up @@ -44,8 +35,7 @@ export default class GlobeController extends Controller {
this.touchRotate = false;
}

_getTransitionProps() {
// Enables Transitions on double-tap and key-down events.
return LINEAR_TRANSITION_PROPS;
get linearTransitionProps() {
return ['longitude', 'latitude', 'zoom'];
}
}
43 changes: 6 additions & 37 deletions modules/core/src/controllers/map-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,10 @@ import Controller from './controller';
import ViewState from './view-state';
import {normalizeViewportProps} from '@math.gl/web-mercator';
import assert from '../utils/assert';
import LinearInterpolator from '../transitions/linear-interpolator';
import {TRANSITION_EVENTS} from './transition-manager';

const PITCH_MOUSE_THRESHOLD = 5;
const PITCH_ACCEL = 1.2;

const LINEAR_TRANSITION_PROPS = {
transitionDuration: 300,
transitionEasing: t => t,
transitionInterpolator: new LinearInterpolator(),
transitionInterruption: TRANSITION_EVENTS.BREAK
};

const DEFAULT_STATE = {
pitch: 0,
bearing: 0,
Expand Down Expand Up @@ -132,12 +123,10 @@ export class MapState extends ViewState {
return this;
}

const [longitude, latitude] = this._calculateNewLngLat({startPanLngLat, pos});
const viewport = this.makeViewport(this._viewportProps);
const newProps = viewport.panByPosition(startPanLngLat, pos);

return this._getUpdatedState({
longitude,
latitude
});
return this._getUpdatedState(newProps);
}

/**
Expand Down Expand Up @@ -236,15 +225,10 @@ export class MapState extends ViewState {
const zoom = this._calculateNewZoom({scale, startZoom});

const zoomedViewport = this.makeViewport({...this._viewportProps, zoom});
const [longitude, latitude] = zoomedViewport.getMapCenterByLngLatPosition({
lngLat: startZoomLngLat,
pos
});

return this._getUpdatedState({
zoom,
longitude,
latitude
...zoomedViewport.panByPosition(startZoomLngLat, pos)
});
}

Expand Down Expand Up @@ -374,12 +358,6 @@ export class MapState extends ViewState {
return pos && viewport.unproject(pos);
}

// Calculate a new lnglat based on pixel dragging position
_calculateNewLngLat({startPanLngLat, pos}) {
const viewport = this.makeViewport(this._viewportProps);
return viewport.getMapCenterByLngLatPosition({lngLat: startPanLngLat, pos});
}

// Calculates new zoom
_calculateNewZoom({scale, startZoom}) {
const {maxZoom, minZoom} = this._viewportProps;
Expand Down Expand Up @@ -461,16 +439,7 @@ export default class MapController extends Controller {
}
}

_getTransitionProps(opts) {
// Enables Transitions on double-tap and key-down events.
return opts
? {
...LINEAR_TRANSITION_PROPS,
transitionInterpolator: new LinearInterpolator({
...opts,
makeViewport: this.controllerState.makeViewport
})
}
: LINEAR_TRANSITION_PROPS;
get linearTransitionProps() {
return ['longitude', 'latitude', 'zoom', 'bearing', 'pitch'];
}
}
14 changes: 2 additions & 12 deletions modules/core/src/controllers/orbit-controller.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {clamp, Vector2} from 'math.gl';
import Controller from './controller';
import ViewState from './view-state';
import LinearInterpolator from '../transitions/linear-interpolator';
import {TRANSITION_EVENTS} from './transition-manager';
import {mod} from '../utils/math-utils';

const DEFAULT_STATE = {
Expand All @@ -17,13 +15,6 @@ const DEFAULT_STATE = {
maxZoom: Infinity
};

const LINEAR_TRANSITION_PROPS = {
transitionDuration: 300,
transitionEasing: t => t,
transitionInterpolator: new LinearInterpolator(['target', 'zoom', 'rotationX', 'rotationOrbit']),
transitionInterruption: TRANSITION_EVENTS.BREAK
};

/* Helpers */

const zoom2Scale = zoom => Math.pow(2, zoom);
Expand Down Expand Up @@ -373,8 +364,7 @@ export default class OrbitController extends Controller {
super(OrbitState, props);
}

_getTransitionProps() {
// Enables Transitions on double-tap and key-down events.
return LINEAR_TRANSITION_PROPS;
get linearTransitionProps() {
return ['target', 'zoom', 'rotationX', 'rotationOrbit'];
}
}
14 changes: 2 additions & 12 deletions modules/core/src/controllers/orthographic-controller.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
import Controller from './controller';
import {OrbitState} from './orbit-controller';
import LinearInterpolator from '../transitions/linear-interpolator';
import {TRANSITION_EVENTS} from './transition-manager';

const LINEAR_TRANSITION_PROPS = {
transitionDuration: 300,
transitionEasing: t => t,
transitionInterpolator: new LinearInterpolator(['target', 'zoom']),
transitionInterruption: TRANSITION_EVENTS.BREAK
};

export default class OrthographicController extends Controller {
constructor(props) {
Expand All @@ -21,8 +12,7 @@ export default class OrthographicController extends Controller {
return false;
}

_getTransitionProps() {
// Enables Transitions on double-tap and key-down events.
return LINEAR_TRANSITION_PROPS;
get linearTransitionProps() {
return ['target', 'zoom'];
}
}
23 changes: 12 additions & 11 deletions modules/core/src/transitions/linear-interpolator.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ export default class LinearInterpolator extends TransitionInterpolator {
if (makeViewport && around) {
const startViewport = makeViewport(startProps);
const endViewport = makeViewport(endProps);
const aroundLngLat = startViewport.unproject(around);
const aroundPosition = startViewport.unproject(around);
result.start.around = around;
Object.assign(result.end, {
around: endViewport.project(aroundLngLat),
aroundLngLat,
around: endViewport.project(aroundPosition),
aroundPosition,
width: endProps.width,
height: endProps.height
});
Expand All @@ -53,16 +53,17 @@ export default class LinearInterpolator extends TransitionInterpolator {
propsInTransition[key] = lerp(startProps[key] || 0, endProps[key] || 0, t);
}

if (endProps.aroundLngLat) {
if (endProps.aroundPosition) {
// Linear transition should be performed in common space
const viewport = this.opts.makeViewport({...endProps, ...propsInTransition});
const [longitude, latitude] = viewport.getMapCenterByLngLatPosition({
lngLat: endProps.aroundLngLat,
// anchor point in current screen coordinates
pos: lerp(startProps.around, endProps.around, t)
});
propsInTransition.longitude = longitude;
propsInTransition.latitude = latitude;
Object.assign(
propsInTransition,
viewport.panByPosition(
endProps.aroundPosition,
// anchor point in current screen coordinates
lerp(startProps.around, endProps.around, t)
)
);
}
return propsInTransition;
}
Expand Down
12 changes: 6 additions & 6 deletions modules/core/src/viewports/globe-viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,12 @@ export default class GlobeViewport extends Viewport {
return xyz;
}

getMapCenterByLngLatPosition({lngLat, pos}) {
const fromPosition = this.unproject(pos);
return [
lngLat[0] - fromPosition[0] + this.longitude,
lngLat[1] - fromPosition[1] + this.latitude
];
panByPosition(coords, pixel) {
const fromPosition = this.unproject(pixel);
return {
longitude: coords[0] - fromPosition[0] + this.longitude,
latitude: coords[1] - fromPosition[1] + this.latitude
};
}
}

Expand Down
12 changes: 12 additions & 0 deletions modules/core/src/viewports/viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,18 @@ export default class Viewport {

// EXPERIMENTAL METHODS

/**
* Needed by panning and linear transition
* Pan the viewport to place a given world coordinate at screen point [x, y]
*
* @param {Array} coords - world coordinates
* @param {Array} pixel - [x,y] coordinates on screen
* @return {Object} props of the new viewport
*/
panByPosition(coords, pixel) {
return null;
}

getCameraPosition() {
return this.cameraPosition;
}
Expand Down
19 changes: 5 additions & 14 deletions modules/core/src/viewports/web-mercator-viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,24 +167,15 @@ export default class WebMercatorViewport extends Viewport {
return addMetersToLngLat(lngLatZ, xyz);
}

/**
* Get the map center that place a given [lng, lat] coordinate at screen
* point [x, y]
*
* @param {Array} lngLat - [lng,lat] coordinates
* Specifies a point on the sphere.
* @param {Array} pos - [x,y] coordinates
* Specifies a point on the screen.
* @return {Array} [lng,lat] new map center.
*/
getMapCenterByLngLatPosition({lngLat, pos}) {
const fromLocation = pixelsToWorld(pos, this.pixelUnprojectionMatrix);
const toLocation = this.projectFlat(lngLat);
panByPosition(coords, pixel) {
const fromLocation = pixelsToWorld(pixel, this.pixelUnprojectionMatrix);
const toLocation = this.projectFlat(coords);

const translate = vec2.add([], toLocation, vec2.negate([], fromLocation));
const newCenter = vec2.add([], this.center, translate);

return this.unprojectFlat(newCenter);
const [longitude, latitude] = this.unprojectFlat(newCenter);
return {longitude, latitude};
}

getBounds(options = {}) {
Expand Down
Loading