Skip to content

Commit 03887ec

Browse files
committed
Fixed performance issue, when the icon was recreated too often.
1 parent 27c8aae commit 03887ec

File tree

2 files changed

+60
-29
lines changed

2 files changed

+60
-29
lines changed

examples/src/components/Icon.vue

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,15 @@
3535
<!-- Create image icon (L.icon) from l-icon tag -->
3636
<l-marker :lat-lng="[47.413220, -1.199482]">
3737
<l-icon
38-
:icon-size="[iconSize, iconSize*1.15]"
39-
:icon-anchor="[iconSize/2, iconSize*1.15]"
40-
temp-name="icon 1"
38+
:icon-size="dynamicSize"
39+
:icon-anchor="dynamicAnchor"
4140
icon-url="static/images/baseball-marker.png" />
4241
</l-marker>
4342

4443
<!-- Create HTML icon (L.divIcon) by providing content inside the l-icon tag -->
4544
<l-marker :lat-lng="[47.413220, -1.189482]">
4645
<l-icon
47-
:icon-anchor="[16, 37]"
48-
temp-name="icon 2"
46+
:icon-anchor="staticAnchor"
4947
class-name="someExtraClass">
5048
<div class="headline">{{ customText }}</div>
5149
<img src="static/images/layers.png">
@@ -80,10 +78,19 @@ export default {
8078
iconSize: [32, 37],
8179
iconAnchor: [16, 37]
8280
}),
81+
staticAnchor: [16, 37],
8382
customText: 'Foobar',
8483
iconSize: 64
8584
};
8685
},
86+
computed: {
87+
dynamicSize () {
88+
return [this.iconSize, this.iconSize * 1.15];
89+
},
90+
dynamicAnchor () {
91+
return [this.iconSize / 2, this.iconSize * 1.15];
92+
}
93+
},
8794
methods: {
8895
}
8996
};

src/components/LIcon.vue

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -76,33 +76,32 @@ export default {
7676
type: Object,
7777
custom: true,
7878
default: () => ({})
79-
},
80-
// TODO: Remove tempName here (and from the example)
81-
tempName: {
82-
type: String,
83-
custom: true,
84-
default: null
8579
}
8680
},
8781
8882
data () {
8983
return {
90-
observer: null
84+
parentContainer: null,
85+
observer: null,
86+
recreationNeeded: false,
87+
swapHtmlNeeded: false
9188
};
9289
},
9390
9491
mounted () {
92+
this.parentContainer = findRealParent(this.$parent);
93+
9594
propsBinder(this, null, this.$options.props);
9695
9796
this.observer = new MutationObserver(() => {
98-
this.createIcon('html slot');
97+
this.scheduleHtmlSwap();
9998
});
10099
this.observer.observe(
101100
this.$el,
102101
{ attributes: true, childList: true, characterData: true, subtree: true }
103102
);
104103
105-
this.createIcon('initial');
104+
this.scheduleCreateIcon();
106105
},
107106
108107
beforeDestroy () {
@@ -114,8 +113,30 @@ export default {
114113
},
115114
116115
methods: {
117-
createIcon (reason) {
118-
console.log(Date.now() + ' - recreate ' + this.tempName + ' (' + reason + ')');
116+
scheduleCreateIcon () {
117+
this.recreationNeeded = true;
118+
119+
this.$nextTick(this.createIcon);
120+
},
121+
122+
scheduleHtmlSwap () {
123+
this.htmlSwapNeeded = true;
124+
125+
this.$nextTick(this.createIcon);
126+
},
127+
128+
createIcon () {
129+
// If only html of a divIcon changed, we can just replace the DOM without the need of recreating the whole icon
130+
if (this.htmlSwapNeeded && !this.recreationNeeded && this.iconObject) {
131+
this.parentContainer.mapObject.getElement().innerHTML = this.$el.innerHTML;
132+
133+
this.htmlSwapNeeded = false;
134+
return;
135+
}
136+
137+
if (!this.recreationNeeded) {
138+
return;
139+
}
119140
120141
if (this.iconObject) {
121142
L.DomEvent.off(this.iconObject, this.$listeners);
@@ -145,44 +166,47 @@ export default {
145166
146167
L.DomEvent.on(this.iconObject, this.$listeners);
147168
148-
this.parentContainer = findRealParent(this.$parent);
149169
this.parentContainer.mapObject.setIcon(this.iconObject);
170+
171+
this.recreationNeeded = false;
172+
this.htmlSwapNeeded = false;
150173
},
174+
151175
setIconUrl () {
152-
this.createIcon('iconUrl');
176+
this.scheduleCreateIcon();
153177
},
154178
setIconRetinaUrl () {
155-
this.createIcon('iconRetinaUrl');
179+
this.scheduleCreateIcon();
156180
},
157181
setIconSize () {
158-
this.createIcon('iconSize');
182+
this.scheduleCreateIcon();
159183
},
160184
setIconAnchor () {
161-
this.createIcon('iconAnchor');
185+
this.scheduleCreateIcon();
162186
},
163187
setPopupAnchor () {
164-
this.createIcon('popupAnchor');
188+
this.scheduleCreateIcon();
165189
},
166190
setTooltipAnchor () {
167-
this.createIcon('tooltipAnchor');
191+
this.scheduleCreateIcon();
168192
},
169193
setShadowUrl () {
170-
this.createIcon('shadowUrl');
194+
this.scheduleCreateIcon();
171195
},
172196
setShadowRetinaUrl () {
173-
this.createIcon('shadowRetinaUrl');
197+
this.scheduleCreateIcon();
174198
},
175199
setShadowAnchor () {
176-
this.createIcon('shadowAnchor');
200+
this.scheduleCreateIcon();
177201
},
178202
setBgPos () {
179-
this.createIcon('bgPos');
203+
this.scheduleCreateIcon();
180204
},
181205
setClassName () {
182-
this.createIcon('className');
206+
this.scheduleCreateIcon();
183207
},
184208
setHtml () {
185-
this.createIcon('html');
209+
this.scheduleCreateIcon();
186210
}
187211
},
188212

0 commit comments

Comments
 (0)