Skip to content

Commit bc37f6d

Browse files
committed
min and max pitch options
1 parent 94598e7 commit bc37f6d

File tree

2 files changed

+94
-5
lines changed

2 files changed

+94
-5
lines changed

src/geo/transform.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,24 @@ class Transform {
4646
_renderWorldCopies: boolean;
4747
_minZoom: number;
4848
_maxZoom: number;
49+
_minPitch: number;
50+
_maxPitch: number;
4951
_center: LngLat;
5052
_constraining: boolean;
5153
_posMatrixCache: {[number]: Float32Array};
5254
_alignedPosMatrixCache: {[number]: Float32Array};
5355

54-
constructor(minZoom: ?number, maxZoom: ?number, renderWorldCopies: boolean | void) {
56+
constructor(minZoom: ?number, maxZoom: ?number, minPitch: ?number, maxPitch: ?number, renderWorldCopies: boolean | void) {
5557
this.tileSize = 512; // constant
5658
this.maxValidLatitude = 85.051129; // constant
5759

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

64+
this._minPitch = minPitch || 0;
65+
this._maxPitch = maxPitch || 60;
66+
6267
this.setMaxBounds();
6368

6469
this.width = 0;
@@ -74,7 +79,7 @@ class Transform {
7479
}
7580

7681
clone(): Transform {
77-
const clone = new Transform(this._minZoom, this._maxZoom, this._renderWorldCopies);
82+
const clone = new Transform(this._minZoom, this._maxZoom, this._minPitch, this.maxPitch, this._renderWorldCopies);
7883
clone.tileSize = this.tileSize;
7984
clone.latRange = this.latRange;
8085
clone.width = this.width;
@@ -103,6 +108,20 @@ class Transform {
103108
this.zoom = Math.min(this.zoom, zoom);
104109
}
105110

111+
get minPitch(): number { return this._minPitch; }
112+
set minPitch(pitch: number) {
113+
if (this._minPitch === pitch) return;
114+
this._minPitch = pitch;
115+
this.pitch = Math.max(this.pitch, pitch);
116+
}
117+
118+
get maxPitch(): number { return this._maxPitch; }
119+
set maxPitch(pitch: number) {
120+
if (this._maxPitch === pitch) return;
121+
this._maxPitch = pitch;
122+
this.pitch = Math.min(this.pitch, pitch);
123+
}
124+
106125
get renderWorldCopies(): boolean { return this._renderWorldCopies; }
107126
set renderWorldCopies(renderWorldCopies?: ?boolean) {
108127
if (renderWorldCopies === undefined) {
@@ -145,7 +164,7 @@ class Transform {
145164
return this._pitch / Math.PI * 180;
146165
}
147166
set pitch(pitch: number) {
148-
const p = clamp(pitch, 0, 60) / 180 * Math.PI;
167+
const p = clamp(pitch, this.minPitch, this.maxPitch) / 180 * Math.PI;
149168
if (this._pitch === p) return;
150169
this._unmodified = false;
151170
this._pitch = p;

src/ui/map.js

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ type MapOptions = {
7979
scrollZoom?: boolean,
8080
minZoom?: ?number,
8181
maxZoom?: ?number,
82+
minPitch?: ?number,
83+
maxPitch?: ?number,
8284
boxZoom?: boolean,
8385
dragRotate?: boolean,
8486
dragPan?: boolean,
@@ -97,6 +99,10 @@ type MapOptions = {
9799

98100
const defaultMinZoom = 0;
99101
const defaultMaxZoom = 22;
102+
103+
const defaultMinPitch = 0;
104+
const defaultMaxPitch = 60;
105+
100106
const defaultOptions = {
101107
center: [0, 0],
102108
zoom: 0,
@@ -106,6 +112,9 @@ const defaultOptions = {
106112
minZoom: defaultMinZoom,
107113
maxZoom: defaultMaxZoom,
108114

115+
minPitch: defaultMinPitch,
116+
maxPitch: defaultMaxPitch,
117+
109118
interactive: true,
110119
scrollZoom: true,
111120
boxZoom: true,
@@ -147,6 +156,8 @@ const defaultOptions = {
147156
* @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.
148157
* @param {number} [options.minZoom=0] The minimum zoom level of the map (0-24).
149158
* @param {number} [options.maxZoom=22] The maximum zoom level of the map (0-24).
159+
* @param {number} [options.minPitch=0] The minimum pitch of the map (0-90).
160+
* @param {number} [options.maxPitch=60] The maximum pitch of the map (0-90).
150161
* @param {Object|string} [options.style] The map's Mapbox style. This must be an a JSON object conforming to
151162
* the schema described in the [Mapbox Style Specification](https://mapbox.com/mapbox-gl-style-spec/), or a URL to
152163
* such JSON.
@@ -311,10 +322,14 @@ class Map extends Camera {
311322
options = extend({}, defaultOptions, options);
312323

313324
if (options.minZoom != null && options.maxZoom != null && options.minZoom > options.maxZoom) {
314-
throw new Error(`maxZoom must be greater than minZoom`);
325+
throw new Error(`maxZoom must be greater than or equal to minZoom`);
326+
}
327+
328+
if (options.minPitch != null && options.maxPitch != null && options.minPitch > options.maxPitch) {
329+
throw new Error(`maxPitch must be greater than or equal to minPitch`);
315330
}
316331

317-
const transform = new Transform(options.minZoom, options.maxZoom, options.renderWorldCopies);
332+
const transform = new Transform(options.minZoom, options.maxZoom, options.minPitch, options.maxPitch, options.renderWorldCopies);
318333
super(transform, options);
319334

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

604+
/**
605+
* Sets or clears the map's minimum pitch.
606+
* If the map's current pitch is lower than the new minimum,
607+
* the map will ease to the new minimum.
608+
*
609+
* @param {number | null | undefined} minPitch The minimum pitch to set (0-90).
610+
* If `null` or `undefined` is provided, the function removes the current minimum pitch (i.e. sets it to 0).
611+
* @returns {Map} `this`
612+
*/
613+
setMinPitch(minPitch?: ?number) {
614+
615+
minPitch = minPitch === null || minPitch === undefined ? defaultMinPitch : minPitch;
616+
617+
if (minPitch >= defaultMinPitch && minPitch <= this.transform.maxPitch) {
618+
this.transform.minPitch = minPitch;
619+
this._update();
620+
621+
if (this.getPitch() < minPitch) this.setPitch(minPitch);
622+
623+
return this;
624+
625+
} else throw new Error(`minPitch must be between ${defaultMinPitch} and the current maxPitch, inclusive`);
626+
}
627+
628+
/**
629+
* Returns the map's minimum allowable pitch.
630+
*
631+
* @returns {number} minPitch
632+
*/
633+
getMinPitch() { return this.transform.minPitch; }
634+
635+
/**
636+
* Sets or clears the map's maximum pitch.
637+
* If the map's current pitch is higher than the new maximum,
638+
* the map will zoom to the new maximum.
639+
*
640+
* @param {number | null | undefined} maxPitch The maximum pitch to set.
641+
* If `null` or `undefined` is provided, the function removes the current maximum pitch (sets it to 60).
642+
* @returns {Map} `this`
643+
*/
644+
setMaxPitch(maxPitch?: ?number) {
645+
646+
maxPitch = maxPitch === null || maxPitch === undefined ? defaultMaxPitch : maxPitch;
647+
648+
if (maxPitch >= this.transform.minPitch) {
649+
this.transform.maxPitch = maxPitch;
650+
this._update();
651+
652+
if (this.getPitch() > maxPitch) this.setPitch(maxPitch);
653+
654+
return this;
655+
656+
} else throw new Error(`maxPitch must be greater than the current minPitch`);
657+
}
658+
589659
/**
590660
* Returns the state of renderWorldCopies.
591661
*

0 commit comments

Comments
 (0)