Compare commits
1
Commits
v2026.11.12.3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
209ee8c2ea |
@@ -82,6 +82,21 @@ describe("map layer visibility fades", () => {
|
|||||||
expect(frames.size).toBe(0);
|
expect(frames.size).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("keeps opacity in range when the first frame timestamp precedes the fade start", () => {
|
||||||
|
const fixture = createMap();
|
||||||
|
now = 100;
|
||||||
|
setMapLayersVisibility(fixture.map, ["simulation-backend-analysis-label", "pipes"], false);
|
||||||
|
// RAF reports the frame start, which can precede performance.now() sampled
|
||||||
|
// later in that frame when a visibility change begins.
|
||||||
|
advance(75.8);
|
||||||
|
expect(fixture.paint.get("simulation-backend-analysis-label:text-opacity")).toBe(1);
|
||||||
|
expect(fixture.paint.get("pipes:line-opacity")).toBe(0.92);
|
||||||
|
advance(260);
|
||||||
|
expect(fixture.paint.get("simulation-backend-analysis-label:text-opacity")).toBe(0.5);
|
||||||
|
advance(420);
|
||||||
|
expect(fixture.visibility.get("simulation-backend-analysis-label")).toBe("none");
|
||||||
|
});
|
||||||
|
|
||||||
it("starts fading in after vector tiles are ready", () => {
|
it("starts fading in after vector tiles are ready", () => {
|
||||||
const fixture = createMap();
|
const fixture = createMap();
|
||||||
let loaded = false;
|
let loaded = false;
|
||||||
@@ -102,7 +117,8 @@ describe("map layer visibility fades", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function createMap() {
|
function createMap() {
|
||||||
const layers = new Map([ ["pipes", { type: "line", source: "pipes" }], ["pipes-hit", { type: "line", source: "pipes" }] ]);
|
const layers = new Map([ ["pipes", { type: "line", source: "pipes" }], ["pipes-hit", { type: "line", source: "pipes" }],
|
||||||
|
["simulation-backend-analysis-label", { type: "symbol", source: "simulation-backend-analysis" }] ]);
|
||||||
const visibility = new Map([ ["pipes", "visible"], ["pipes-hit", "visible"] ]);
|
const visibility = new Map([ ["pipes", "visible"], ["pipes-hit", "visible"] ]);
|
||||||
const paint = new Map<string, unknown>([
|
const paint = new Map<string, unknown>([
|
||||||
["pipes:line-opacity", 0.92], ["pipes:line-opacity-transition", { duration: 120 }],
|
["pipes:line-opacity", 0.92], ["pipes:line-opacity-transition", { duration: 120 }],
|
||||||
|
|||||||
@@ -110,7 +110,8 @@ export function setMapLayersVisibility(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
startedAt ??= now;
|
startedAt ??= now;
|
||||||
const progress = Math.min(1, (now - startedAt) / LAYER_VISIBILITY_FADE_MS);
|
// RAF's frame timestamp may precede performance.now() at the fade start.
|
||||||
|
const progress = Math.max(0, Math.min(1, (now - startedAt) / LAYER_VISIBILITY_FADE_MS));
|
||||||
fade.opacity = startOpacity + (targetOpacity - startOpacity) * progress;
|
fade.opacity = startOpacity + (targetOpacity - startOpacity) * progress;
|
||||||
if (progress >= 1) finish();
|
if (progress >= 1) finish();
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -48,6 +48,27 @@ async function openLayerFixture(page: Page, vectorPipes = false) {
|
|||||||
await page.getByRole("button", { name: /图层:管理地图图层/ }).click();
|
await page.getByRole("button", { name: /图层:管理地图图层/ }).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("analysis label fade accepts a frame timestamp earlier than the visibility change", async ({ page }) => {
|
||||||
|
await openLayerFixture(page);
|
||||||
|
await page.evaluate(async () => {
|
||||||
|
const modulePath = "/src/features/workbench/map/layer-visibility.ts";
|
||||||
|
const { setMapLayersVisibility } = await import(modulePath);
|
||||||
|
const map = window.__waterNetworkMap!;
|
||||||
|
const errors: string[] = [];
|
||||||
|
map.on("error", (event) => {
|
||||||
|
if (event.error.message.includes("simulation-backend-analysis-label")) errors.push(event.error.message);
|
||||||
|
});
|
||||||
|
Object.assign(window, { analysisFadeErrors: errors });
|
||||||
|
const nativeFrame = window.requestAnimationFrame.bind(window);
|
||||||
|
window.requestAnimationFrame = (callback) => nativeFrame((time) => callback(time - 100));
|
||||||
|
try { setMapLayersVisibility(map, ["simulation-backend-analysis-label"], false); }
|
||||||
|
finally { window.requestAnimationFrame = nativeFrame; }
|
||||||
|
});
|
||||||
|
await expect.poll(() => page.evaluate(() => window.__waterNetworkMap!
|
||||||
|
.getLayoutProperty("simulation-backend-analysis-label", "visibility"))).toBe("none");
|
||||||
|
expect(await page.evaluate(() => (window as unknown as { analysisFadeErrors: string[] }).analysisFadeErrors)).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
for (const [label, layerId, property] of [
|
for (const [label, layerId, property] of [
|
||||||
["管线", "pipes-flow", "line-opacity"],
|
["管线", "pipes-flow", "line-opacity"],
|
||||||
["水库", "reservoirs-symbol", "icon-opacity"],
|
["水库", "reservoirs-symbol", "icon-opacity"],
|
||||||
|
|||||||
Reference in New Issue
Block a user