refactor: rename map feature types and improve path animation trajectory using flyTo and dynamic timing
This commit is contained in:
@@ -284,7 +284,7 @@ export function useMapInteraction({
|
|||||||
type: "Feature",
|
type: "Feature",
|
||||||
properties: {
|
properties: {
|
||||||
id,
|
id,
|
||||||
type: "attack_route",
|
type: "military_route",
|
||||||
geometry_preset: "line",
|
geometry_preset: "line",
|
||||||
entity_id: null,
|
entity_id: null,
|
||||||
entity_ids: [],
|
entity_ids: [],
|
||||||
@@ -306,7 +306,7 @@ export function useMapInteraction({
|
|||||||
type: "Feature",
|
type: "Feature",
|
||||||
properties: {
|
properties: {
|
||||||
id,
|
id,
|
||||||
type: "war",
|
type: "battle",
|
||||||
geometry_preset: "circle-area",
|
geometry_preset: "circle-area",
|
||||||
entity_id: null,
|
entity_id: null,
|
||||||
entity_ids: [],
|
entity_ids: [],
|
||||||
|
|||||||
@@ -259,8 +259,11 @@ export function createReplayMapEffects() {
|
|||||||
const path = removeDuplicateCoordinates(coordinates);
|
const path = removeDuplicateCoordinates(coordinates);
|
||||||
if (path.length === 0) return;
|
if (path.length === 0) return;
|
||||||
if (path.length === 1) {
|
if (path.length === 1) {
|
||||||
map.easeTo({
|
map.flyTo({
|
||||||
center: path[0],
|
center: path[0],
|
||||||
|
zoom: typeof zoom === "number" ? zoom : map.getZoom(),
|
||||||
|
pitch: map.getPitch(),
|
||||||
|
bearing: map.getBearing(),
|
||||||
duration: clampNumber(duration, 250, 60000, 5000),
|
duration: clampNumber(duration, 250, 60000, 5000),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@@ -272,35 +275,73 @@ export function createReplayMapEffects() {
|
|||||||
if (totalDistance <= 0) return;
|
if (totalDistance <= 0) return;
|
||||||
|
|
||||||
const totalDuration = clampNumber(duration, 250, 60000, 5000);
|
const totalDuration = clampNumber(duration, 250, 60000, 5000);
|
||||||
const startedAt = performance.now();
|
|
||||||
|
// Allocate flyDuration dynamically based on the total step duration
|
||||||
|
let flyDuration = 1500;
|
||||||
|
if (totalDuration < 3000) {
|
||||||
|
flyDuration = Math.round(totalDuration * 0.4);
|
||||||
|
} else if (totalDuration < 4500) {
|
||||||
|
flyDuration = 1200;
|
||||||
|
}
|
||||||
|
const followDuration = Math.max(100, totalDuration - flyDuration);
|
||||||
|
|
||||||
let rafId = 0;
|
let rafId = 0;
|
||||||
|
let flyTimeoutId: NodeJS.Timeout | null = null;
|
||||||
let unregister: Cleanup | null = null;
|
let unregister: Cleanup | null = null;
|
||||||
|
let onMoveStart: ((e: any) => void) | null = null;
|
||||||
|
|
||||||
const stop = () => {
|
const stop = () => {
|
||||||
|
if (flyTimeoutId) {
|
||||||
|
clearTimeout(flyTimeoutId);
|
||||||
|
flyTimeoutId = null;
|
||||||
|
}
|
||||||
if (rafId) {
|
if (rafId) {
|
||||||
cancelAnimationFrame(rafId);
|
cancelAnimationFrame(rafId);
|
||||||
rafId = 0;
|
rafId = 0;
|
||||||
}
|
}
|
||||||
|
if (onMoveStart) {
|
||||||
|
map.off("movestart", onMoveStart);
|
||||||
|
onMoveStart = null;
|
||||||
|
}
|
||||||
unregister?.();
|
unregister?.();
|
||||||
unregister = null;
|
unregister = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const tick = (now: number) => {
|
onMoveStart = (e: any) => {
|
||||||
const progress = Math.min(1, (now - startedAt) / totalDuration);
|
if (e && e.isFollowPath) {
|
||||||
const targetDistance = totalDistance * progress;
|
|
||||||
const center = interpolateMeasuredPath(measured, targetDistance);
|
|
||||||
map.jumpTo({
|
|
||||||
center,
|
|
||||||
});
|
|
||||||
if (progress >= 1) {
|
|
||||||
stop();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rafId = requestAnimationFrame(tick);
|
stop();
|
||||||
};
|
};
|
||||||
|
map.on("movestart", onMoveStart);
|
||||||
|
|
||||||
|
map.flyTo({
|
||||||
|
center: path[0],
|
||||||
|
zoom: typeof zoom === "number" ? zoom : map.getZoom(),
|
||||||
|
pitch: map.getPitch(),
|
||||||
|
bearing: map.getBearing(),
|
||||||
|
duration: flyDuration,
|
||||||
|
}, { isFollowPath: true });
|
||||||
|
|
||||||
|
flyTimeoutId = setTimeout(() => {
|
||||||
|
const startedAt = performance.now();
|
||||||
|
const tick = (now: number) => {
|
||||||
|
const progress = Math.min(1, (now - startedAt) / followDuration);
|
||||||
|
const targetDistance = totalDistance * progress;
|
||||||
|
const center = interpolateMeasuredPath(measured, targetDistance);
|
||||||
|
map.jumpTo({
|
||||||
|
center,
|
||||||
|
}, { isFollowPath: true });
|
||||||
|
if (progress >= 1) {
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rafId = requestAnimationFrame(tick);
|
||||||
|
};
|
||||||
|
rafId = requestAnimationFrame(tick);
|
||||||
|
}, flyDuration);
|
||||||
|
|
||||||
unregister = registerCleanup(stop);
|
unregister = registerCleanup(stop);
|
||||||
rafId = requestAnimationFrame(tick);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user