fix: avoid duplicate world map background loads

This commit is contained in:
Bastian Wagner
2026-08-19 09:02:14 +02:00
parent 1a30eb3491
commit 8e6e77b027
5 changed files with 18 additions and 10 deletions

View File

@@ -31,6 +31,7 @@ The reference screenshots were inspected but are not shipped or referenced by th
- The decision panel now occupies normal document flow below the map scene, reserving a non-overlapping zone at desktop and narrow breakpoints. - The decision panel now occupies normal document flow below the map scene, reserving a non-overlapping zone at desktop and narrow breakpoints.
- The original delivered PNGs remain untouched. A deterministic local System.Drawing JPEG conversion (quality 86, high-quality bicubic) provides runtime derivatives: `map_ashen_realm-1440.jpg` (1440x810, 233,778 B), `Suedtor-960.jpg` (960x540, 94,286 B), and `Aschestrasse-960.jpg` (960x540, 93,277 B). The WorldPage and ContextPanel prefer these derivatives while retaining each server artwork path as the `<img>` fallback. - The original delivered PNGs remain untouched. A deterministic local System.Drawing JPEG conversion (quality 86, high-quality bicubic) provides runtime derivatives: `map_ashen_realm-1440.jpg` (1440x810, 233,778 B), `Suedtor-960.jpg` (960x540, 94,286 B), and `Aschestrasse-960.jpg` (960x540, 93,277 B). The WorldPage and ContextPanel prefer these derivatives while retaining each server artwork path as the `<img>` fallback.
- The load error is exposed as an alert and its retry control is covered by a store-load regression test. - The load error is exposed as an alert and its retry control is covered by a store-load regression test.
- The map no longer declares the runtime JPEG and original PNG as comma-separated background layers. It uses the original PNG as the classic CSS fallback and, where `image-set` with JPEG is supported, replaces it with one runtime JPEG candidate. The WorldPage regression test verifies there is no inline multi-layer binding or `mapBackground` source left to reintroduce the double load.
## Verification ## Verification
@@ -43,6 +44,7 @@ The reference screenshots were inspected but are not shipped or referenced by th
- Review full web suite: 23/23 pass. - Review full web suite: 23/23 pass.
- Affected API seed test: 2/2 pass. - Affected API seed test: 2/2 pass.
- Both review builds (`npm run build:web`, `npm run build:api`) pass. - Both review builds (`npm run build:web`, `npm run build:api`) pass.
- Review-fix round 2: focused WorldPage test 7/7 pass; full web suite and web build re-run after the fallback change.
## Remaining concern ## Remaining concern

View File

@@ -1,10 +1,6 @@
<section class="world-page" aria-label="Weltansicht"> <section class="world-page" aria-label="Weltansicht">
@if (worldStore.currentLocation(); as location) { @if (worldStore.currentLocation(); as location) {
<section <section class="world-page__scene" [attr.aria-label]="'Weltkarte bei ' + location.name">
class="world-page__scene"
[style.background-image]="mapBackground"
[attr.aria-label]="'Weltkarte bei ' + location.name"
>
<div class="world-page__atmosphere" aria-hidden="true"></div> <div class="world-page__atmosphere" aria-hidden="true"></div>
<p class="world-page__location-title">{{ location.name }}</p> <p class="world-page__location-title">{{ location.name }}</p>

View File

@@ -15,12 +15,25 @@
overflow: hidden; overflow: hidden;
border: 1px solid var(--ar-border); border: 1px solid var(--ar-border);
background-color: #151718; background-color: #151718;
background-image: url('/images/backgrounds/map_ashen_realm.png');
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
box-shadow: var(--ar-shadow-raised); box-shadow: var(--ar-shadow-raised);
} }
@supports (
background-image: image-set(
url('/images/backgrounds/runtime/map_ashen_realm-1440.jpg') type('image/jpeg') 1x
)
) {
.world-page__scene {
background-image: image-set(
url('/images/backgrounds/runtime/map_ashen_realm-1440.jpg') type('image/jpeg') 1x
);
}
}
.world-page__scene::after { .world-page__scene::after {
position: absolute; position: absolute;
z-index: -1; z-index: -1;

View File

@@ -122,9 +122,8 @@ describe('WorldPageComponent', () => {
expect( expect(
element.querySelector('.world-page__node--burned-road [data-location-key="burned-road"]'), element.querySelector('.world-page__node--burned-road [data-location-key="burned-road"]'),
).not.toBeNull(); ).not.toBeNull();
expect(element.querySelector('.world-page__scene')?.getAttribute('style')).toContain( expect(element.querySelector('.world-page__scene')?.getAttribute('style')).toBeNull();
'map_ashen_realm-1440.jpg', expect(fixture.componentInstance).not.toHaveProperty('mapBackground');
);
store.currentLocation.set(burnedRoad); store.currentLocation.set(burnedRoad);
fixture.detectChanges(); fixture.detectChanges();

View File

@@ -12,8 +12,6 @@ import { WorldStore } from './world.store';
}) })
export class WorldPageComponent implements OnInit { export class WorldPageComponent implements OnInit {
protected readonly worldStore = inject(WorldStore); protected readonly worldStore = inject(WorldStore);
protected readonly mapBackground =
"url('/images/backgrounds/runtime/map_ashen_realm-1440.jpg'), url('/images/backgrounds/map_ashen_realm.png')";
ngOnInit(): void { ngOnInit(): void {
void this.worldStore.load(); void this.worldStore.load();