Reuse player marker icons when removing and readding to map

This commit is contained in:
James Lyne 2022-02-06 12:29:43 +00:00
parent b3e593897b
commit b75d1022b7
2 changed files with 36 additions and 10 deletions

View File

@ -17,7 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
import {BaseIconOptions, DomUtil, Icon, Layer, LayerOptions, Util} from 'leaflet'; import {BaseIconOptions, Icon, Layer, LayerOptions, Util} from 'leaflet';
import {getImagePixelSize, getMinecraftHead} from '@/util'; import {getImagePixelSize, getMinecraftHead} from '@/util';
import defaultImage from '@/assets/images/player_face.png'; import defaultImage from '@/assets/images/player_face.png';
import {LiveAtlasPlayer, LiveAtlasPlayerImageSize} from "@/index"; import {LiveAtlasPlayer, LiveAtlasPlayerImageSize} from "@/index";
@ -57,9 +57,11 @@ export class PlayerIcon extends Layer implements Icon<PlayerIconOptions> {
this._player = player; this._player = player;
} }
createIcon(oldIcon: HTMLElement) { createIcon() {
if (oldIcon) { // Reuse detached icon if it exists
DomUtil.remove(oldIcon); if (this._container) {
this.update();
return this._container;
} }
this._currentName = undefined; this._currentName = undefined;
@ -80,10 +82,7 @@ export class PlayerIcon extends Layer implements Icon<PlayerIconOptions> {
this._playerImage = playerImage.cloneNode() as HTMLImageElement; this._playerImage = playerImage.cloneNode() as HTMLImageElement;
this._playerImage.height = this._playerImage.width = getImagePixelSize(this.options.imageSize); this._playerImage.height = this._playerImage.width = getImagePixelSize(this.options.imageSize);
getMinecraftHead(this._player, this.options.imageSize).then(head => { this.updateImage();
this._playerImage!.src = head.src;
}).catch(() => {});
this._playerInfo.appendChild(this._playerImage); this._playerInfo.appendChild(this._playerImage);
} }
@ -126,6 +125,12 @@ export class PlayerIcon extends Layer implements Icon<PlayerIconOptions> {
return null; return null;
} }
updateImage() {
getMinecraftHead(this._player, this.options.imageSize).then(head => {
this._playerImage!.src = head.src;
}).catch(() => {});
}
update() { update() {
if(!this._container) { if(!this._container) {
return; return;
@ -163,4 +168,10 @@ export class PlayerIcon extends Layer implements Icon<PlayerIconOptions> {
} }
} }
} }
detach() {
if(this._container && this._container.parentNode) {
this._container = this._container.parentNode.removeChild(this._container);
}
}
} }

View File

@ -17,8 +17,9 @@
import {LatLng, MarkerOptions, Marker, Map, Util} from 'leaflet'; import {LatLng, MarkerOptions, Marker, Map, Util} from 'leaflet';
import {PlayerIcon} from "@/leaflet/icon/PlayerIcon"; import {PlayerIcon} from "@/leaflet/icon/PlayerIcon";
import {LiveAtlasPlayer, LiveAtlasPlayerImageSize} from "@/index"; import {LiveAtlasPlayer, LiveAtlasPlayerImageSize} from "@/index";
import {watch} from "@vue/runtime-core"; import {computed, watch} from "@vue/runtime-core";
import {WatchStopHandle} from "vue"; import {nextTick, WatchStopHandle} from "vue";
import {useStore} from "@/store";
export interface PlayerMarkerOptions extends MarkerOptions { export interface PlayerMarkerOptions extends MarkerOptions {
imageSize: LiveAtlasPlayerImageSize, imageSize: LiveAtlasPlayerImageSize,
@ -30,10 +31,12 @@ export interface PlayerMarkerOptions extends MarkerOptions {
export class PlayerMarker extends Marker { export class PlayerMarker extends Marker {
declare options: PlayerMarkerOptions; declare options: PlayerMarkerOptions;
declare _icon: HTMLElement | null;
private readonly _PlayerIcon: PlayerIcon; private readonly _PlayerIcon: PlayerIcon;
private readonly _player: LiveAtlasPlayer; private readonly _player: LiveAtlasPlayer;
private _playerUnwatch?: WatchStopHandle; private _playerUnwatch?: WatchStopHandle;
private _imageUrlUnwatch?: WatchStopHandle;
constructor(player: LiveAtlasPlayer, options: PlayerMarkerOptions) { constructor(player: LiveAtlasPlayer, options: PlayerMarkerOptions) {
super(new LatLng(0, 0), options); super(new LatLng(0, 0), options);
@ -51,7 +54,11 @@ export class PlayerMarker extends Marker {
} }
onAdd(map: Map) { onAdd(map: Map) {
const imageUrl = computed(() => useStore().state.components.players.imageUrl);
this._playerUnwatch = watch(this._player, () => this._PlayerIcon.update(), {deep: true}); this._playerUnwatch = watch(this._player, () => this._PlayerIcon.update(), {deep: true});
this._imageUrlUnwatch = watch(imageUrl, () => nextTick(() => this._PlayerIcon.updateImage()));
return super.onAdd(map); return super.onAdd(map);
} }
@ -60,6 +67,14 @@ export class PlayerMarker extends Marker {
this._playerUnwatch(); this._playerUnwatch();
} }
if(this._imageUrlUnwatch) {
this._imageUrlUnwatch();
}
if(this._icon) {
this._PlayerIcon.detach();
}
return super.onRemove(map); return super.onRemove(map);
} }