diff --git a/src/common/dom/setup-leaflet-map.js b/src/common/dom/setup-leaflet-map.js index de1a0109c0..7649161de0 100644 --- a/src/common/dom/setup-leaflet-map.js +++ b/src/common/dom/setup-leaflet-map.js @@ -1,7 +1,9 @@ -import Leaflet from "leaflet"; - // Sets up a Leaflet map on the provided DOM element -export default function setupLeafletMap(mapElement) { +export const setupLeafletMap = async (mapElement) => { + const Leaflet = (await import(/* webpackChunkName: "leaflet" */ "leaflet")) + .default; + Leaflet.Icon.Default.imagePath = "/static/images/leaflet"; + const map = Leaflet.map(mapElement); const style = document.createElement("link"); style.setAttribute("href", "/static/images/leaflet/leaflet.css"); @@ -21,5 +23,5 @@ export default function setupLeafletMap(mapElement) { } ).addTo(map); - return map; -} + return [map, Leaflet]; +}; diff --git a/src/panels/lovelace/cards/hui-map-card.js b/src/panels/lovelace/cards/hui-map-card.js index cb52efe46d..32a7631c6d 100644 --- a/src/panels/lovelace/cards/hui-map-card.js +++ b/src/panels/lovelace/cards/hui-map-card.js @@ -1,19 +1,16 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "@polymer/paper-icon-button/paper-icon-button"; -import Leaflet from "leaflet"; import "../../map/ha-entity-marker"; -import setupLeafletMap from "../../../common/dom/setup-leaflet-map"; +import { setupLeafletMap } from "../../../common/dom/setup-leaflet-map"; import { processConfigEntities } from "../common/process-config-entities"; import computeStateDomain from "../../../common/entity/compute_state_domain"; import computeStateName from "../../../common/entity/compute_state_name"; import debounce from "../../../common/util/debounce"; import parseAspectRatio from "../../../common/util/parse-aspect-ratio"; -Leaflet.Icon.Default.imagePath = "/static/images/leaflet"; - class HuiMapCard extends PolymerElement { static get template() { return html` @@ -143,13 +140,14 @@ class HuiMapCard extends PolymerElement { window.addEventListener("resize", this._debouncedResizeListener); } - this._map = setupLeafletMap(this.$.map); - this._drawEntities(this.hass); + this.loadMap(); + } - setTimeout(() => { - this._resetMap(); - this._fitMap(); - }, 1); + async loadMap() { + [this._map, this.Leaflet] = await setupLeafletMap(this.$.map); + this._drawEntities(this.hass); + this._map.invalidateSize(); + this._fitMap(); } disconnectedCallback() { @@ -177,7 +175,7 @@ class HuiMapCard extends PolymerElement { const zoom = this._config.default_zoom; if (this._mapItems.length === 0) { this._map.setView( - new Leaflet.LatLng( + new this.Leaflet.LatLng( this.hass.config.latitude, this.hass.config.longitude ), @@ -186,7 +184,7 @@ class HuiMapCard extends PolymerElement { return; } - const bounds = new Leaflet.latLngBounds( + const bounds = new this.Leaflet.latLngBounds( this._mapItems.map((item) => item.getLatLng()) ); this._map.fitBounds(bounds.pad(0.5)); @@ -245,7 +243,7 @@ class HuiMapCard extends PolymerElement { iconHTML = title; } - markerIcon = Leaflet.divIcon({ + markerIcon = this.Leaflet.divIcon({ html: iconHTML, iconSize: [24, 24], className: "", @@ -253,7 +251,7 @@ class HuiMapCard extends PolymerElement { // create market with the icon mapItems.push( - Leaflet.marker([latitude, longitude], { + this.Leaflet.marker([latitude, longitude], { icon: markerIcon, interactive: false, title: title, @@ -262,7 +260,7 @@ class HuiMapCard extends PolymerElement { // create circle around it mapItems.push( - Leaflet.circle([latitude, longitude], { + this.Leaflet.circle([latitude, longitude], { interactive: false, color: "#FF9800", radius: radius, @@ -285,9 +283,9 @@ class HuiMapCard extends PolymerElement { el.setAttribute("entity-name", entityName); el.setAttribute("entity-picture", entityPicture || ""); - /* Leaflet clones this element before adding it to the map. This messes up + /* this.Leaflet clones this element before adding it to the map. This messes up our Polymer object and we can't pass data through. Thus we hack like this. */ - markerIcon = Leaflet.divIcon({ + markerIcon = this.Leaflet.divIcon({ html: el.outerHTML, iconSize: [48, 48], className: "", @@ -295,7 +293,7 @@ class HuiMapCard extends PolymerElement { // create market with the icon mapItems.push( - Leaflet.marker([latitude, longitude], { + this.Leaflet.marker([latitude, longitude], { icon: markerIcon, title: computeStateName(stateObj), }).addTo(map) @@ -304,7 +302,7 @@ class HuiMapCard extends PolymerElement { // create circle around if entity has accuracy if (gpsAccuracy) { mapItems.push( - Leaflet.circle([latitude, longitude], { + this.Leaflet.circle([latitude, longitude], { interactive: false, color: "#0288D1", radius: gpsAccuracy, diff --git a/src/panels/map/ha-panel-map.js b/src/panels/map/ha-panel-map.js index 0a13829de7..6110c89064 100644 --- a/src/panels/map/ha-panel-map.js +++ b/src/panels/map/ha-panel-map.js @@ -1,7 +1,6 @@ import "@polymer/app-layout/app-toolbar/app-toolbar"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; -import Leaflet from "leaflet"; import "../../components/ha-menu-button"; import "../../components/ha-icon"; @@ -11,9 +10,7 @@ import "./ha-entity-marker"; import computeStateDomain from "../../common/entity/compute_state_domain"; import computeStateName from "../../common/entity/compute_state_name"; import LocalizeMixin from "../../mixins/localize-mixin"; -import setupLeafletMap from "../../common/dom/setup-leaflet-map"; - -Leaflet.Icon.Default.imagePath = "/static/images/leaflet"; +import { setupLeafletMap } from "../../common/dom/setup-leaflet-map"; /* * @appliesMixin LocalizeMixin @@ -61,14 +58,14 @@ class HaPanelMap extends LocalizeMixin(PolymerElement) { connectedCallback() { super.connectedCallback(); - var map = (this._map = setupLeafletMap(this.$.map)); + this.loadMap(); + } + async loadMap() { + [this._map, this.Leaflet] = await setupLeafletMap(this.$.map); this.drawEntities(this.hass); - - setTimeout(() => { - map.invalidateSize(); - this.fitMap(); - }, 1); + this._map.invalidateSize(); + this.fitMap(); } disconnectedCallback() { @@ -82,14 +79,14 @@ class HaPanelMap extends LocalizeMixin(PolymerElement) { if (this._mapItems.length === 0) { this._map.setView( - new Leaflet.LatLng( + new this.Leaflet.LatLng( this.hass.config.latitude, this.hass.config.longitude ), 14 ); } else { - bounds = new Leaflet.latLngBounds( + bounds = new this.Leaflet.latLngBounds( this._mapItems.map((item) => item.getLatLng()) ); this._map.fitBounds(bounds.pad(0.5)); @@ -108,7 +105,7 @@ class HaPanelMap extends LocalizeMixin(PolymerElement) { } var mapItems = (this._mapItems = []); - Object.keys(hass.states).forEach(function(entityId) { + Object.keys(hass.states).forEach((entityId) => { var entity = hass.states[entityId]; var title = computeStateName(entity); @@ -137,7 +134,7 @@ class HaPanelMap extends LocalizeMixin(PolymerElement) { iconHTML = title; } - icon = Leaflet.divIcon({ + icon = this.Leaflet.divIcon({ html: iconHTML, iconSize: [24, 24], className: "", @@ -145,7 +142,7 @@ class HaPanelMap extends LocalizeMixin(PolymerElement) { // create market with the icon mapItems.push( - Leaflet.marker( + this.Leaflet.marker( [entity.attributes.latitude, entity.attributes.longitude], { icon: icon, @@ -157,7 +154,7 @@ class HaPanelMap extends LocalizeMixin(PolymerElement) { // create circle around it mapItems.push( - Leaflet.circle( + this.Leaflet.circle( [entity.attributes.latitude, entity.attributes.longitude], { interactive: false, @@ -181,7 +178,7 @@ class HaPanelMap extends LocalizeMixin(PolymerElement) { .join(""); /* Leaflet clones this element before adding it to the map. This messes up our Polymer object and we can't pass data through. Thus we hack like this. */ - icon = Leaflet.divIcon({ + icon = this.Leaflet.divIcon({ html: "