Delay follow panning by a frame to account for projection changes

This commit is contained in:
James Lyne 2020-12-18 15:46:34 +00:00
parent 38476266b0
commit 217028e044

View File

@ -29,7 +29,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import {computed, defineComponent} from "@vue/runtime-core"; import {computed, ref, defineComponent} from "@vue/runtime-core";
import {CRS, LatLng} from 'leaflet'; import {CRS, LatLng} from 'leaflet';
import {useStore} from '@/store'; import {useStore} from '@/store';
import MapLayer from "@/components/map/layer/MapLayer.vue"; import MapLayer from "@/components/map/layer/MapLayer.vue";
@ -79,7 +79,11 @@ export default defineComponent({
mapBackground = computed(() => store.getters.mapBackground), mapBackground = computed(() => store.getters.mapBackground),
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
followFrame = ref(0),
worldChangeFrame = ref(0);
return { return {
leaflet, leaflet,
@ -94,6 +98,8 @@ export default defineComponent({
logoControls, logoControls,
followTarget, followTarget,
panTarget, panTarget,
followFrame,
worldChangeFrame,
mapBackground, mapBackground,
currentWorld, currentWorld,
currentMap, currentMap,
@ -123,6 +129,12 @@ export default defineComponent({
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;
let zoom: number; let zoom: number;
@ -149,8 +161,8 @@ export default defineComponent({
zoom = store.state.parsedUrl.zoom || store.state.configuration.defaultZoom; zoom = store.state.parsedUrl.zoom || store.state.configuration.defaultZoom;
} }
//Delay the pan a frame, to allow the projection to be updated by the new world //Delay the pan by a frame, to allow the projection to be updated by the new world
requestAnimationFrame(() => { this.worldChangeFrame = requestAnimationFrame(() => {
this.leaflet!.panTo(this.currentProjection.locationToLatLng(location), { this.leaflet!.panTo(this.currentProjection.locationToLatLng(location), {
animate: false, animate: false,
noMoveStart: true, noMoveStart: true,
@ -209,12 +221,19 @@ export default defineComponent({
const store = useStore(), const store = useStore(),
currentWorld = store.state.currentWorld; currentWorld = store.state.currentWorld;
//Cancel any pending pan frame
if(this.followFrame) {
cancelAnimationFrame(this.followFrame);
this.followFrame = 0;
}
if(!this.leaflet) { if(!this.leaflet) {
console.warn('Map isn\'t initialized yet. Ignoring follow'); console.warn(`Cannot follow ${player.name}. Map not yet initialized.`);
return;
} }
if(!player.location.world) { if(!player.location.world) {
console.error('Player isn\'t in a world somehow'); console.warn(`Cannot follow ${player.name}. Player isn't in a known world.`);
return; return;
} }
@ -223,7 +242,7 @@ export default defineComponent({
world = store.state.worlds.get(player.location.world); world = store.state.worlds.get(player.location.world);
if(!world) { if(!world) {
console.error('Player isn\'t in a known world somehow'); console.warn(`Cannot follow ${player.name}. Player isn't in a known world.`);
return; return;
} }
@ -237,12 +256,15 @@ export default defineComponent({
} }
} }
this.leaflet!.panTo(store.state.currentProjection.locationToLatLng(player.location)); //Delay the pan by a frame, to allow the projection to be updated by the new world
this.followFrame = requestAnimationFrame(() => {
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);
} }
})
} }
} }
}) })