Skip to content

Commit

Permalink
min and max pitch options
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewharvey committed Jul 5, 2019
1 parent 94598e7 commit bc37f6d
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 5 deletions.
25 changes: 22 additions & 3 deletions src/geo/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,24 @@ class Transform {
_renderWorldCopies: boolean;
_minZoom: number;
_maxZoom: number;
_minPitch: number;
_maxPitch: number;
_center: LngLat;
_constraining: boolean;
_posMatrixCache: {[number]: Float32Array};
_alignedPosMatrixCache: {[number]: Float32Array};

constructor(minZoom: ?number, maxZoom: ?number, renderWorldCopies: boolean | void) {
constructor(minZoom: ?number, maxZoom: ?number, minPitch: ?number, maxPitch: ?number, renderWorldCopies: boolean | void) {
this.tileSize = 512; // constant
this.maxValidLatitude = 85.051129; // constant

this._renderWorldCopies = renderWorldCopies === undefined ? true : renderWorldCopies;
this._minZoom = minZoom || 0;
this._maxZoom = maxZoom || 22;

this._minPitch = minPitch || 0;
this._maxPitch = maxPitch || 60;

this.setMaxBounds();

this.width = 0;
Expand All @@ -74,7 +79,7 @@ class Transform {
}

clone(): Transform {
const clone = new Transform(this._minZoom, this._maxZoom, this._renderWorldCopies);
const clone = new Transform(this._minZoom, this._maxZoom, this._minPitch, this.maxPitch, this._renderWorldCopies);
clone.tileSize = this.tileSize;
clone.latRange = this.latRange;
clone.width = this.width;
Expand Down Expand Up @@ -103,6 +108,20 @@ class Transform {
this.zoom = Math.min(this.zoom, zoom);
}

get minPitch(): number { return this._minPitch; }
set minPitch(pitch: number) {
if (this._minPitch === pitch) return;
this._minPitch = pitch;
this.pitch = Math.max(this.pitch, pitch);
}

get maxPitch(): number { return this._maxPitch; }
set maxPitch(pitch: number) {
if (this._maxPitch === pitch) return;
this._maxPitch = pitch;
this.pitch = Math.min(this.pitch, pitch);
}

get renderWorldCopies(): boolean { return this._renderWorldCopies; }
set renderWorldCopies(renderWorldCopies?: ?boolean) {
if (renderWorldCopies === undefined) {
Expand Down Expand Up @@ -145,7 +164,7 @@ class Transform {
return this._pitch / Math.PI * 180;
}
set pitch(pitch: number) {
const p = clamp(pitch, 0, 60) / 180 * Math.PI;
const p = clamp(pitch, this.minPitch, this.maxPitch) / 180 * Math.PI;
if (this._pitch === p) return;
this._unmodified = false;
this._pitch = p;
Expand Down
74 changes: 72 additions & 2 deletions src/ui/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ type MapOptions = {
scrollZoom?: boolean,
minZoom?: ?number,
maxZoom?: ?number,
minPitch?: ?number,
maxPitch?: ?number,
boxZoom?: boolean,
dragRotate?: boolean,
dragPan?: boolean,
Expand All @@ -97,6 +99,10 @@ type MapOptions = {

const defaultMinZoom = 0;
const defaultMaxZoom = 22;

const defaultMinPitch = 0;
const defaultMaxPitch = 60;

const defaultOptions = {
center: [0, 0],
zoom: 0,
Expand All @@ -106,6 +112,9 @@ const defaultOptions = {
minZoom: defaultMinZoom,
maxZoom: defaultMaxZoom,

minPitch: defaultMinPitch,
maxPitch: defaultMaxPitch,

interactive: true,
scrollZoom: true,
boxZoom: true,
Expand Down Expand Up @@ -147,6 +156,8 @@ const defaultOptions = {
* @param {HTMLElement|string} options.container The HTML element in which Mapbox GL JS will render the map, or the element's string `id`. The specified element must have no children.
* @param {number} [options.minZoom=0] The minimum zoom level of the map (0-24).
* @param {number} [options.maxZoom=22] The maximum zoom level of the map (0-24).
* @param {number} [options.minPitch=0] The minimum pitch of the map (0-90).
* @param {number} [options.maxPitch=60] The maximum pitch of the map (0-90).
* @param {Object|string} [options.style] The map's Mapbox style. This must be an a JSON object conforming to
* the schema described in the [Mapbox Style Specification](https://mapbox.com/mapbox-gl-style-spec/), or a URL to
* such JSON.
Expand Down Expand Up @@ -311,10 +322,14 @@ class Map extends Camera {
options = extend({}, defaultOptions, options);

if (options.minZoom != null && options.maxZoom != null && options.minZoom > options.maxZoom) {
throw new Error(`maxZoom must be greater than minZoom`);
throw new Error(`maxZoom must be greater than or equal to minZoom`);
}

if (options.minPitch != null && options.maxPitch != null && options.minPitch > options.maxPitch) {
throw new Error(`maxPitch must be greater than or equal to minPitch`);
}

const transform = new Transform(options.minZoom, options.maxZoom, options.renderWorldCopies);
const transform = new Transform(options.minZoom, options.maxZoom, options.minPitch, options.maxPitch, options.renderWorldCopies);
super(transform, options);

this._interactive = options.interactive;
Expand Down Expand Up @@ -586,6 +601,61 @@ class Map extends Camera {
} else throw new Error(`maxZoom must be greater than the current minZoom`);
}

/**
* Sets or clears the map's minimum pitch.
* If the map's current pitch is lower than the new minimum,
* the map will ease to the new minimum.
*
* @param {number | null | undefined} minPitch The minimum pitch to set (0-90).
* If `null` or `undefined` is provided, the function removes the current minimum pitch (i.e. sets it to 0).
* @returns {Map} `this`
*/
setMinPitch(minPitch?: ?number) {

minPitch = minPitch === null || minPitch === undefined ? defaultMinPitch : minPitch;

if (minPitch >= defaultMinPitch && minPitch <= this.transform.maxPitch) {
this.transform.minPitch = minPitch;
this._update();

if (this.getPitch() < minPitch) this.setPitch(minPitch);

return this;

} else throw new Error(`minPitch must be between ${defaultMinPitch} and the current maxPitch, inclusive`);
}

/**
* Returns the map's minimum allowable pitch.
*
* @returns {number} minPitch
*/
getMinPitch() { return this.transform.minPitch; }

/**
* Sets or clears the map's maximum pitch.
* If the map's current pitch is higher than the new maximum,
* the map will zoom to the new maximum.
*
* @param {number | null | undefined} maxPitch The maximum pitch to set.
* If `null` or `undefined` is provided, the function removes the current maximum pitch (sets it to 60).
* @returns {Map} `this`
*/
setMaxPitch(maxPitch?: ?number) {

maxPitch = maxPitch === null || maxPitch === undefined ? defaultMaxPitch : maxPitch;

if (maxPitch >= this.transform.minPitch) {
this.transform.maxPitch = maxPitch;
this._update();

if (this.getPitch() > maxPitch) this.setPitch(maxPitch);

return this;

} else throw new Error(`maxPitch must be greater than the current minPitch`);
}

/**
* Returns the state of renderWorldCopies.
*
Expand Down

0 comments on commit bc37f6d

Please sign in to comment.