Rewrite handling of pan/zoom across map changes. Fixes various timing issues.
This commit is contained in:
parent
572fc64b7d
commit
d79a5a0a36
@ -81,9 +81,9 @@ export default defineComponent({
|
|||||||
followTarget = computed(() => store.state.followTarget),
|
followTarget = computed(() => store.state.followTarget),
|
||||||
panTarget = computed(() => store.state.panTarget),
|
panTarget = computed(() => store.state.panTarget),
|
||||||
|
|
||||||
//Animation frame callbacks for panning after projection change
|
//Location and zoom to pan to upon next projection change
|
||||||
followFrame = ref(0),
|
scheduledPan = ref<Coordinate|null>(null),
|
||||||
worldChangeFrame = ref(0);
|
scheduledZoom = ref<number|null>(null);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
leaflet,
|
leaflet,
|
||||||
@ -98,12 +98,12 @@ export default defineComponent({
|
|||||||
logoControls,
|
logoControls,
|
||||||
followTarget,
|
followTarget,
|
||||||
panTarget,
|
panTarget,
|
||||||
followFrame,
|
|
||||||
worldChangeFrame,
|
|
||||||
mapBackground,
|
mapBackground,
|
||||||
currentWorld,
|
currentWorld,
|
||||||
currentMap,
|
currentMap,
|
||||||
currentProjection
|
currentProjection,
|
||||||
|
scheduledPan,
|
||||||
|
scheduledZoom
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -128,24 +128,28 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
currentProjection(newValue, oldValue) {
|
currentProjection(newValue, oldValue) {
|
||||||
if(this.leaflet && newValue && oldValue) {
|
if(this.leaflet && newValue && oldValue) {
|
||||||
this.leaflet.panTo(newValue.locationToLatLng(oldValue.latLngToLocation(this.leaflet.getCenter(), 64)), {
|
const panTarget = this.scheduledPan || oldValue.latLngToLocation(this.leaflet.getCenter(), 64);
|
||||||
|
|
||||||
|
if(this.scheduledZoom) {
|
||||||
|
this.leaflet!.setZoom(this.scheduledZoom, {
|
||||||
|
animate: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.leaflet.panTo(newValue.locationToLatLng(panTarget), {
|
||||||
animate: false,
|
animate: false,
|
||||||
noMoveStart: true,
|
noMoveStart: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.scheduledZoom = null;
|
||||||
|
this.scheduledPan = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
currentWorld(newValue, oldValue) {
|
currentWorld(newValue, oldValue) {
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
|
|
||||||
//Cancel any pending pan frame
|
|
||||||
if(this.worldChangeFrame) {
|
|
||||||
cancelAnimationFrame(this.worldChangeFrame);
|
|
||||||
this.worldChangeFrame = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(newValue) {
|
if(newValue) {
|
||||||
let location: Coordinate;
|
let location: Coordinate | null = this.scheduledPan;
|
||||||
let zoom: number;
|
|
||||||
|
|
||||||
store.dispatch(ActionTypes.GET_MARKER_SETS, undefined);
|
store.dispatch(ActionTypes.GET_MARKER_SETS, undefined);
|
||||||
|
|
||||||
@ -166,35 +170,15 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!oldValue) {
|
if(!oldValue) {
|
||||||
zoom = typeof store.state.parsedUrl.zoom !== 'undefined' ?
|
this.scheduledZoom = typeof store.state.parsedUrl.zoom !== 'undefined' ?
|
||||||
store.state.parsedUrl.zoom : store.state.configuration.defaultZoom;
|
store.state.parsedUrl.zoom : store.state.configuration.defaultZoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Delay the pan by a frame, to allow the projection to be updated by the new world
|
//Set pan location for when the projection changes
|
||||||
this.worldChangeFrame = requestAnimationFrame(() => {
|
this.scheduledPan = location;
|
||||||
this.leaflet!.panTo(this.currentProjection.locationToLatLng(location), {
|
|
||||||
animate: false,
|
|
||||||
noMoveStart: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.leaflet!.setZoom(zoom, {
|
|
||||||
animate: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
configuration: {
|
|
||||||
handler(newValue) {
|
|
||||||
if(this.leaflet) {
|
|
||||||
this.leaflet.setZoom(newValue.defaultZoom, {
|
|
||||||
animate: false,
|
|
||||||
noMoveStart: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deep: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.leaflet = new DynmapMap(this.$el, Object.freeze({
|
this.leaflet = new DynmapMap(this.$el, Object.freeze({
|
||||||
@ -230,13 +214,10 @@ export default defineComponent({
|
|||||||
methods: {
|
methods: {
|
||||||
updateFollow(player: DynmapPlayer, newFollow: boolean) {
|
updateFollow(player: DynmapPlayer, newFollow: boolean) {
|
||||||
const store = useStore(),
|
const store = useStore(),
|
||||||
|
followMapName = store.state.configuration.followMap,
|
||||||
currentWorld = store.state.currentWorld;
|
currentWorld = store.state.currentWorld;
|
||||||
|
|
||||||
//Cancel any pending pan frame
|
let targetWorld = null;
|
||||||
if(this.followFrame) {
|
|
||||||
cancelAnimationFrame(this.followFrame);
|
|
||||||
this.followFrame = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!this.leaflet) {
|
if(!this.leaflet) {
|
||||||
console.warn(`Cannot follow ${player.account}. Map not yet initialized.`);
|
console.warn(`Cannot follow ${player.account}. Map not yet initialized.`);
|
||||||
@ -254,33 +235,38 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!currentWorld || currentWorld.name !== player.location.world) {
|
if(!currentWorld || currentWorld.name !== player.location.world) {
|
||||||
const followMapName = store.state.configuration.followMap,
|
targetWorld = store.state.worlds.get(player.location.world);
|
||||||
world = store.state.worlds.get(player.location.world);
|
} else {
|
||||||
|
targetWorld = currentWorld;
|
||||||
|
}
|
||||||
|
|
||||||
if(!world) {
|
if (!targetWorld) {
|
||||||
console.warn(`Cannot follow ${player.account}. Player isn't in a known world.`);
|
console.warn(`Cannot follow ${player.account}. Player isn't in a known world.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let map = followMapName && world.maps.has(followMapName)
|
let map = followMapName && targetWorld.maps.has(followMapName)
|
||||||
? world.maps.get(followMapName)
|
? targetWorld.maps.get(followMapName)
|
||||||
: world.maps.entries().next().value[1]
|
: targetWorld.maps.entries().next().value[1]
|
||||||
|
|
||||||
if(map !== store.state.currentMap) {
|
if(map !== store.state.currentMap) {
|
||||||
console.log(`Switching map to match player ${world.name} ${map.name}`);
|
this.scheduledPan = player.location;
|
||||||
store.commit(MutationTypes.SET_CURRENT_MAP, {worldName: world.name, mapName: map.name});
|
|
||||||
}
|
if(newFollow) {
|
||||||
|
console.log(`Setting zoom for new follow ${store.state.configuration.followZoom}`);
|
||||||
|
this.scheduledZoom = store.state.configuration.followZoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Delay the pan by a frame, to allow the projection to be updated by the new world
|
console.log(`Switching map to match player ${targetWorld.name} ${map.name}`);
|
||||||
this.followFrame = requestAnimationFrame(() => {
|
store.commit(MutationTypes.SET_CURRENT_MAP, {worldName: targetWorld.name, mapName: map.name});
|
||||||
|
} else {
|
||||||
this.leaflet!.panTo(store.state.currentProjection.locationToLatLng(player.location));
|
this.leaflet!.panTo(store.state.currentProjection.locationToLatLng(player.location));
|
||||||
|
|
||||||
if(newFollow) {
|
if(newFollow) {
|
||||||
console.log(`Setting zoom for new follow ${store.state.configuration.followZoom}`);
|
console.log(`Setting zoom for new follow ${store.state.configuration.followZoom}`);
|
||||||
this.leaflet!.setZoom(store.state.configuration.followZoom);
|
this.leaflet!.setZoom(store.state.configuration.followZoom);
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user