mirror of
https://github.com/maputnik/editor.git
synced 2026-10-13 14:33:44 +00:00
feat: Add ability to control the max zoom of the map (#2201)
- Resolves #2202 ## Launch Checklist The map max zoom was increased to 24 without the ability to change it. - https://github.com/maplibre/maputnik/issues/593 The default is 22 for all maplibre instances if you don't override it in your code. The zoom levels to over scale is dependent on max zoom, which can affect how the map looks. This PR adds the ability to change this. This was added to the debug dialog: <img width="446" height="446" alt="image" src="https://github.com/user-attachments/assets/ea68c392-309f-4476-8922-790670762d56" /> - [x] Briefly describe the changes in this PR. - [x] Link to related issues. - [x] Include before/after visuals or gifs if this PR includes visual changes. - [x] Write tests for all new functionality. - [x] Add an entry to `CHANGELOG.md` under the `## main` section.
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
- Exported HTML now loads MapLibre GL JS as an ES module, since v6 no longer ships a UMD bundle
|
- Exported HTML now loads MapLibre GL JS as an ES module, since v6 no longer ships a UMD bundle
|
||||||
- Add `font-faces`, `sky`, `roll` and `centerAltitude` to the style settings modal
|
- Add `font-faces`, `sky`, `roll` and `centerAltitude` to the style settings modal
|
||||||
- The sidebar can now be resized, both as a whole and in the split between the layer list and the layer editor
|
- The sidebar can now be resized, both as a whole and in the split between the layer list and the layer editor
|
||||||
|
- Allow viewing and changing the map's max zoom in the debug modal
|
||||||
- _...Add new stuff here..._
|
- _...Add new stuff here..._
|
||||||
|
|
||||||
### 🐞 Bug fixes
|
### 🐞 Bug fixes
|
||||||
|
|||||||
@@ -64,6 +64,30 @@ describe("modals", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("debug", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await when.setStyle("zoom_7_center_0_51");
|
||||||
|
await then(get.locationHash()).shouldInclude("#7/51/0");
|
||||||
|
await when.typeKeys("!");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("max zoom is empty until the user sets it", async () => {
|
||||||
|
await then(get.elementByTestId("modal:debug.max-zoom")).shouldHaveValue("");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("lowering the max zoom zooms the map out to it", async () => {
|
||||||
|
await when.setValue("modal:debug.max-zoom", "3");
|
||||||
|
await then(get.locationHash()).shouldInclude("#3/51/0");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("typing a multi-digit max zoom keeps the map in place", async () => {
|
||||||
|
await when.type("modal:debug.max-zoom", "{selectall}{backspace}22");
|
||||||
|
// Let the debounced update reach the map
|
||||||
|
await when.wait(1000);
|
||||||
|
await then(get.locationHash()).shouldInclude("#7/51/0");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("export", () => {
|
describe("export", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await when.click("nav:export");
|
await when.click("nav:export");
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
showTileBoundaries: false,
|
showTileBoundaries: false,
|
||||||
showCollisionBoxes: false,
|
showCollisionBoxes: false,
|
||||||
showOverdrawInspector: false,
|
showOverdrawInspector: false,
|
||||||
|
maxZoom: undefined,
|
||||||
},
|
},
|
||||||
openlayersDebugOptions: {
|
openlayersDebugOptions: {
|
||||||
debugToolbox: false,
|
debugToolbox: false,
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps,
|
|||||||
map.showTileBoundaries = this.props.options?.showTileBoundaries!;
|
map.showTileBoundaries = this.props.options?.showTileBoundaries!;
|
||||||
map.showCollisionBoxes = this.props.options?.showCollisionBoxes!;
|
map.showCollisionBoxes = this.props.options?.showCollisionBoxes!;
|
||||||
map.showOverdrawInspector = this.props.options?.showOverdrawInspector!;
|
map.showOverdrawInspector = this.props.options?.showOverdrawInspector!;
|
||||||
|
map.setMaxZoom(this.props.options?.maxZoom);
|
||||||
|
|
||||||
// set the map view when the prop was updated from outside
|
// set the map view when the prop was updated from outside
|
||||||
if (this.props.mapView._from === "app") {
|
if (this.props.mapView._from === "app") {
|
||||||
@@ -152,7 +153,6 @@ class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps,
|
|||||||
container: this.container!,
|
container: this.container!,
|
||||||
style: this.props.mapStyle,
|
style: this.props.mapStyle,
|
||||||
hash: true,
|
hash: true,
|
||||||
maxZoom: 24,
|
|
||||||
// make root relative urls in stylefiles work as maplibre gl js does
|
// make root relative urls in stylefiles work as maplibre gl js does
|
||||||
// not support this for everything:
|
// not support this for everything:
|
||||||
// https://github.com/maplibre/maplibre-gl-js/issues/6818
|
// https://github.com/maplibre/maplibre-gl-js/issues/6818
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { debounce } from "lodash";
|
||||||
import { Trans, type WithTranslation, withTranslation } from "react-i18next";
|
import { Trans, type WithTranslation, withTranslation } from "react-i18next";
|
||||||
|
import type { MapOptions } from "maplibre-gl";
|
||||||
|
|
||||||
import { Modal } from "./Modal";
|
import { Modal } from "./Modal";
|
||||||
|
import { FieldNumber } from "../FieldNumber";
|
||||||
|
|
||||||
|
|
||||||
type ModalDebugInternalProps = {
|
type ModalDebugInternalProps = {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
renderer: string
|
renderer: string
|
||||||
onChangeMaplibreGlDebug(key: string, checked: boolean): unknown
|
onChangeMaplibreGlDebug(key: string, value: boolean | number | undefined): unknown
|
||||||
onChangeOpenlayersDebug(key: string, checked: boolean): unknown
|
onChangeOpenlayersDebug(key: string, checked: boolean): unknown
|
||||||
onOpenToggle(): void
|
onOpenToggle(): void
|
||||||
maplibreGlDebugOptions?: object
|
maplibreGlDebugOptions?: Partial<MapOptions>
|
||||||
openlayersDebugOptions?: object
|
openlayersDebugOptions?: object
|
||||||
mapView: {
|
mapView: {
|
||||||
zoom: number
|
zoom: number
|
||||||
@@ -23,6 +26,15 @@ type ModalDebugInternalProps = {
|
|||||||
|
|
||||||
|
|
||||||
class ModalDebugInternal extends React.Component<ModalDebugInternalProps> {
|
class ModalDebugInternal extends React.Component<ModalDebugInternalProps> {
|
||||||
|
// Typing "22" would otherwise apply 2 first and zoom the map out of the current view
|
||||||
|
onChangeMaxZoom = debounce((value: number | undefined) => {
|
||||||
|
this.props.onChangeMaplibreGlDebug("maxZoom", value);
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.onChangeMaxZoom.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {t, mapView} = this.props;
|
const {t, mapView} = this.props;
|
||||||
|
|
||||||
@@ -39,15 +51,24 @@ class ModalDebugInternal extends React.Component<ModalDebugInternalProps> {
|
|||||||
<section className="maputnik-modal-section maputnik-modal-shortcuts">
|
<section className="maputnik-modal-section maputnik-modal-shortcuts">
|
||||||
<h1>{t("Options")}</h1>
|
<h1>{t("Options")}</h1>
|
||||||
{this.props.renderer === "mlgljs" &&
|
{this.props.renderer === "mlgljs" &&
|
||||||
<ul>
|
<>
|
||||||
{Object.entries(this.props.maplibreGlDebugOptions!).map(([key, val]) => {
|
<ul>
|
||||||
return <li key={key}>
|
{Object.entries(this.props.maplibreGlDebugOptions!).filter((entry): entry is [string, boolean] => typeof entry[1] === "boolean").map(([key, val]) => {
|
||||||
<label>
|
return <li key={key}>
|
||||||
<input type="checkbox" checked={val} onChange={(e) => this.props.onChangeMaplibreGlDebug(key, e.target.checked)} /> {key}
|
<label>
|
||||||
</label>
|
<input type="checkbox" checked={val} onChange={(e) => this.props.onChangeMaplibreGlDebug(key, e.target.checked)} /> {key}
|
||||||
</li>;
|
</label>
|
||||||
})}
|
</li>;
|
||||||
</ul>
|
})}
|
||||||
|
</ul>
|
||||||
|
<FieldNumber
|
||||||
|
label={t("Max Zoom")}
|
||||||
|
data-wd-key="modal:debug.max-zoom"
|
||||||
|
value={this.props.maplibreGlDebugOptions!.maxZoom ?? undefined}
|
||||||
|
min={0}
|
||||||
|
onChange={this.onChangeMaxZoom}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
{this.props.renderer === "ol" &&
|
{this.props.renderer === "ol" &&
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user