From 590be2e0c3e3ace05ee75b3afb753354e5dcf45e Mon Sep 17 00:00:00 2001 From: Michael Wolf Date: Sun, 4 Nov 2018 00:50:01 +0100 Subject: [PATCH 1/8] Added LIcon component for dynamically create divIcons --- examples/src/App.vue | 11 ++- examples/src/components/Icon.vue | 84 ++++++++++++++++++++++ src/components/LIcon.vue | 120 +++++++++++++++++++++++++++++++ src/main.js | 1 + types/index.d.ts | 22 +++++- 5 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 examples/src/components/Icon.vue create mode 100644 src/components/LIcon.vue diff --git a/examples/src/App.vue b/examples/src/App.vue index b84966f9..f1287f39 100644 --- a/examples/src/App.vue +++ b/examples/src/App.vue @@ -77,6 +77,11 @@ href="#" @click="currentView='stress'">Load Test +
  • + Custom Marker Icons +
  • +
    +
    +

    Custom Marker Icons

    + + + + +
    + + + + + + + + + + + + + + + + + +
    {{ customText }}
    + +
    +
    + +
    +
    + + + + + diff --git a/src/components/LIcon.vue b/src/components/LIcon.vue new file mode 100644 index 00000000..9be089f7 --- /dev/null +++ b/src/components/LIcon.vue @@ -0,0 +1,120 @@ + + + diff --git a/src/main.js b/src/main.js index ae15d57b..78bf58c6 100644 --- a/src/main.js +++ b/src/main.js @@ -10,6 +10,7 @@ exports.LControlScale = require('./components/LControlScale').default; exports.LControlZoom = require('./components/LControlZoom').default; exports.LFeatureGroup = require('./components/LFeatureGroup').default; exports.LGeoJson = require('./components/LGeoJson').default; +exports.LIcon = require('./components/LIcon').default; exports.LIconDefault = require('./components/LIconDefault').default; exports.LImageOverlay = require('./components/LImageOverlay').default; exports.LLayerGroup = require('./components/LLayerGroup').default; diff --git a/types/index.d.ts b/types/index.d.ts index ecb73e74..56e1f2cd 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -3,7 +3,7 @@ // Definitions by: Matthew Meehan /** - * TODO: + * TODO: * create test cases for types * type parentContainer in components * type findRealParent @@ -452,6 +452,26 @@ declare module "vue2-leaflet" { oldVal?: object | Function | null ): void; } + class LIcon extends Mixins(Options) { + // props + iconUrl: String; + iconRetinaUrl: String; + iconSize: L.Point; + iconAnchor: L.Point; + popupAnchor: L.Point; + tooltipAnchor: L.Point; + shadowUrl: String; + shadowRetinaUrl: String; + shadowSize: L.Point; + shadowAnchor: L.Point; + bgPos: L.Point; + className: String; + + // data + iconObject: L.Icon; + parentContainer: L.Marker; + } + class LIconDefault extends Vue { // props /** From 005de8a2d4cea252197b9eb50abe3cc0eccf8946 Mon Sep 17 00:00:00 2001 From: Michael Wolf Date: Sun, 4 Nov 2018 01:05:42 +0100 Subject: [PATCH 2/8] Cleanup --- examples/src/components/Icon.vue | 4 +++- src/components/LIcon.vue | 37 ++++++++++++++++---------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/examples/src/components/Icon.vue b/examples/src/components/Icon.vue index 684438db..2d30cba5 100644 --- a/examples/src/components/Icon.vue +++ b/examples/src/components/Icon.vue @@ -56,6 +56,7 @@ export default { center: L.latLng(47.413220, -1.219482), url: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png', attribution: '© OpenStreetMap contributors', + icon: L.icon({ iconUrl: 'static/images/baseball-marker.png', iconSize: [32, 37], @@ -75,7 +76,8 @@ export default { background-color: aqua; padding: 10px; border: 1px solid #333; - border-radius: 0 5px 5px 5px; + border-radius: 0 20px 20px 20px; + box-shadow: 5px 3px 10px rgba(0,0,0,0.2); text-align: center; width: auto !important; height: auto !important; diff --git a/src/components/LIcon.vue b/src/components/LIcon.vue index 9be089f7..bd122ee8 100644 --- a/src/components/LIcon.vue +++ b/src/components/LIcon.vue @@ -1,5 +1,7 @@ From c10d2a4a2f5e351dcec07abfa3db4266688f6f34 Mon Sep 17 00:00:00 2001 From: Michael Wolf Date: Sun, 4 Nov 2018 18:49:08 +0100 Subject: [PATCH 5/8] More debugging --- src/components/LIcon.vue | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/components/LIcon.vue b/src/components/LIcon.vue index 4ea1d24c..8aa5a957 100644 --- a/src/components/LIcon.vue +++ b/src/components/LIcon.vue @@ -95,14 +95,14 @@ export default { propsBinder(this, null, this.$options.props); this.observer = new MutationObserver(() => { - this.createIcon(); + this.createIcon('html slot'); }); this.observer.observe( this.$el, { attributes: true, childList: true, characterData: true, subtree: true } ); - this.createIcon(); + this.createIcon('initial'); }, beforeDestroy () { @@ -114,8 +114,8 @@ export default { }, methods: { - createIcon () { - console.log(Date.now() + ' - recreate ' + this.tempName); + createIcon (reason) { + console.log(Date.now() + ' - recreate ' + this.tempName + ' (' + reason + ')'); if (this.iconObject) { L.DomEvent.off(this.iconObject, this.$listeners); @@ -149,40 +149,40 @@ export default { this.parentContainer.mapObject.setIcon(this.iconObject); }, setIconUrl () { - this.createIcon(); + this.createIcon('iconUrl'); }, setIconRetinaUrl () { - this.createIcon(); + this.createIcon('iconRetinaUrl'); }, setIconSize () { - this.createIcon(); + this.createIcon('iconSize'); }, setIconAnchor () { - this.createIcon(); + this.createIcon('iconAnchor'); }, setPopupAnchor () { - this.createIcon(); + this.createIcon('popupAnchor'); }, setTooltipAnchor () { - this.createIcon(); + this.createIcon('tooltipAnchor'); }, setShadowUrl () { - this.createIcon(); + this.createIcon('shadowUrl'); }, setShadowRetinaUrl () { - this.createIcon(); + this.createIcon('shadowRetinaUrl'); }, setShadowAnchor () { - this.createIcon(); + this.createIcon('shadowAnchor'); }, setBgPos () { - this.createIcon(); + this.createIcon('bgPos'); }, setClassName () { - this.createIcon(); + this.createIcon('className'); }, setHtml () { - this.createIcon(); + this.createIcon('html'); } }, From 27c8aaefc7a97456fc058b9eed0ae0588d111c47 Mon Sep 17 00:00:00 2001 From: Michael Wolf Date: Sun, 4 Nov 2018 19:55:21 +0100 Subject: [PATCH 6/8] Fixed typehinting --- types/index.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/types/index.d.ts b/types/index.d.ts index 56e1f2cd..205a4d22 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -716,6 +716,7 @@ declare module "vue2-leaflet" { LControlZoom, LFeatureGroup, LGeoJson, + LIcon, LIconDefault, LImageOverlay, LLayerGroup, From 03887ec6e4c7b6f107869df26c53f23be75b05d4 Mon Sep 17 00:00:00 2001 From: byWulf Date: Tue, 6 Nov 2018 01:19:33 +0100 Subject: [PATCH 7/8] Fixed performance issue, when the icon was recreated too often. --- examples/src/components/Icon.vue | 17 +++++--- src/components/LIcon.vue | 72 +++++++++++++++++++++----------- 2 files changed, 60 insertions(+), 29 deletions(-) diff --git a/examples/src/components/Icon.vue b/examples/src/components/Icon.vue index d4fa52a1..73a42c3b 100644 --- a/examples/src/components/Icon.vue +++ b/examples/src/components/Icon.vue @@ -35,17 +35,15 @@
    {{ customText }}
    @@ -80,10 +78,19 @@ export default { iconSize: [32, 37], iconAnchor: [16, 37] }), + staticAnchor: [16, 37], customText: 'Foobar', iconSize: 64 }; }, + computed: { + dynamicSize () { + return [this.iconSize, this.iconSize * 1.15]; + }, + dynamicAnchor () { + return [this.iconSize / 2, this.iconSize * 1.15]; + } + }, methods: { } }; diff --git a/src/components/LIcon.vue b/src/components/LIcon.vue index 8aa5a957..bd9605db 100644 --- a/src/components/LIcon.vue +++ b/src/components/LIcon.vue @@ -76,33 +76,32 @@ export default { type: Object, custom: true, default: () => ({}) - }, - // TODO: Remove tempName here (and from the example) - tempName: { - type: String, - custom: true, - default: null } }, data () { return { - observer: null + parentContainer: null, + observer: null, + recreationNeeded: false, + swapHtmlNeeded: false }; }, mounted () { + this.parentContainer = findRealParent(this.$parent); + propsBinder(this, null, this.$options.props); this.observer = new MutationObserver(() => { - this.createIcon('html slot'); + this.scheduleHtmlSwap(); }); this.observer.observe( this.$el, { attributes: true, childList: true, characterData: true, subtree: true } ); - this.createIcon('initial'); + this.scheduleCreateIcon(); }, beforeDestroy () { @@ -114,8 +113,30 @@ export default { }, methods: { - createIcon (reason) { - console.log(Date.now() + ' - recreate ' + this.tempName + ' (' + reason + ')'); + scheduleCreateIcon () { + this.recreationNeeded = true; + + this.$nextTick(this.createIcon); + }, + + scheduleHtmlSwap () { + this.htmlSwapNeeded = true; + + this.$nextTick(this.createIcon); + }, + + createIcon () { + // If only html of a divIcon changed, we can just replace the DOM without the need of recreating the whole icon + if (this.htmlSwapNeeded && !this.recreationNeeded && this.iconObject) { + this.parentContainer.mapObject.getElement().innerHTML = this.$el.innerHTML; + + this.htmlSwapNeeded = false; + return; + } + + if (!this.recreationNeeded) { + return; + } if (this.iconObject) { L.DomEvent.off(this.iconObject, this.$listeners); @@ -145,44 +166,47 @@ export default { L.DomEvent.on(this.iconObject, this.$listeners); - this.parentContainer = findRealParent(this.$parent); this.parentContainer.mapObject.setIcon(this.iconObject); + + this.recreationNeeded = false; + this.htmlSwapNeeded = false; }, + setIconUrl () { - this.createIcon('iconUrl'); + this.scheduleCreateIcon(); }, setIconRetinaUrl () { - this.createIcon('iconRetinaUrl'); + this.scheduleCreateIcon(); }, setIconSize () { - this.createIcon('iconSize'); + this.scheduleCreateIcon(); }, setIconAnchor () { - this.createIcon('iconAnchor'); + this.scheduleCreateIcon(); }, setPopupAnchor () { - this.createIcon('popupAnchor'); + this.scheduleCreateIcon(); }, setTooltipAnchor () { - this.createIcon('tooltipAnchor'); + this.scheduleCreateIcon(); }, setShadowUrl () { - this.createIcon('shadowUrl'); + this.scheduleCreateIcon(); }, setShadowRetinaUrl () { - this.createIcon('shadowRetinaUrl'); + this.scheduleCreateIcon(); }, setShadowAnchor () { - this.createIcon('shadowAnchor'); + this.scheduleCreateIcon(); }, setBgPos () { - this.createIcon('bgPos'); + this.scheduleCreateIcon(); }, setClassName () { - this.createIcon('className'); + this.scheduleCreateIcon(); }, setHtml () { - this.createIcon('html'); + this.scheduleCreateIcon(); } }, From 0ba003505e4a32b32af1aa5ce54c6d3c31a67883 Mon Sep 17 00:00:00 2001 From: byWulf Date: Tue, 6 Nov 2018 01:29:21 +0100 Subject: [PATCH 8/8] Removed unused import from example --- examples/src/components/Icon.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/src/components/Icon.vue b/examples/src/components/Icon.vue index 73a42c3b..eeafa784 100644 --- a/examples/src/components/Icon.vue +++ b/examples/src/components/Icon.vue @@ -55,7 +55,7 @@