Problemet: Multi-dokument arbeidsflyt i en nettleser NEMKO Norlab er et av Norges største test- og sertifiseringslaboratorier. Deres analytikere trengte å sammenligne flere laboratorieprøver side om side - undersøke testresultater, grafer og samsvardata samtidig. Det tradisjonelle web-paradigmet med én-side-om-gangen-navigasjon var utilstrekkelig for denne arbeidsflyten.
Designeren ga meg en utfordring: Å skape en 'desktop OS'-opplevelse i en nettleser, med flere vinduer. Ingen eksisterende React-biblioteker ga det kontrollnivået som var nødvendig, så jeg bygde vindussystemet fra bunnen av ved bruk av nettleserens native Drag & Drop API og CSS-transforms.
Tilpasset vindussystem-arkitektur Jeg designet et tilstandshåndteringssystem som sporer hvert vindus posisjon (x, y), størrelse (bredde, høyde), z-index (for stablingsrekkefølge) og tilstand (maksimert, minimert, normal). Hvert vindu er representert som en React-komponent som rendrer absolutt posisjonert innenfor en 'desktop'-container.
Et stort problem var at brukere ofte dro vinduer nær kanten av skjermen og ikke fikk tak i dem igjen. Jeg implementerte derfor en sperre som hindrer vinduer i å bli dratt utenfor synsfeltet.
Z-index-håndtering var kritisk for å sikre at det aktive vinduet alltid vises på toppen. Jeg landet på et stack-basert system hvor klikking på et vindu flytter det til fronten av stacken og beregner z-indekser på nytt for alle vinduer. Dette krevde nøye hendelseshåndtering for å forhindre z-index-thrashing når brukere raskt bytter mellom vinduer.
For vindus-minimering bygde jeg en tilpasset oppgavelinje-komponent som viser minimerte vinduer som klikkbare 'tiles'. Klikking på en tile gjenoppretter vinduet til sin forrige posisjon og størrelse, som jeg persisterer ved bruk av en referanse lagret i state. Dette etterligner oppførselen til Windows/macOS-oppgavehåndtering.
Selv om det ikke var spesifisert i designet, føltes skalering som en selvfølge, så jeg implementerte det - og det ble en høyt verdsatt funksjon. Vindusskalering ble løst ved å lage drabare 'håndtak' i hjørner og kanter, hvor jeg beregnet nye dimensjoner i sanntid med begrensninger for minimum/maksimum størrelse for å hindre ubrukelige vindustilstander.
D3.js-visualisering med interaktive tooltips Laboratorieprøvedata inkluderer ofte tidsseriedata (f.eks. temperatur over tid under stresstesting). Jeg brukte D3.js til å bygge interaktive linjediagrammer med hover-tooltips som viser presise verdier ved hvert datapunkt.
Noen prøver hadde tusenvis av datapunkter, og rendering av alle ga en dårlig brukeropplevelse. Jeg implementerte en adaptiv rendringsstrategi hvor startvisningen fokuserer på de viktigste nylige dataene. Jeg bygde også et dynamisk system for aksemarkering som automatisk beregner optimale intervaller for å forhindre tekstoverlapping, uavhengig av om brukeren ser på 15 prøver eller et år med historiske data.
Tooltips var spesielt vanskelige i et vindus-miljø. D3-tooltips bruker vanligvis absolutt posisjonering i forhold til dokument-body, men inne i et drabart vindu, bryter dette. Jeg omskrev tooltip-posisjoneringslogikken for å beregne posisjoner i forhold til vinduets container, for å sikre at tooltips forblir festet til datapunkter selv når vinduet beveger seg.
PNG-eksport for rapportering En kritisk funksjon var å generere offisielle PDF-rapporter som inkluderer D3.js-grafene nøyaktig som vist i nettleseren. Klienten trengte piksel-perfekt reproduksjon fordi disse rapportene går til reguleringsmyndigheter.
Nettleser-native skjermbildeAPIer (som `html2canvas`) slet med SVG-innhold rendret av D3, og produserte ofte uskarpe eller feil-justerte output. Jeg bygde et tilpasset eksportsystem som serialiserer D3 SVG til en string, injiserer den i et offscreen-canvas og bruker Canvas API til å rendre den som en høy-DPI PNG.
Prosessen: (1) Serialiser D3 SVG med alle beregnede stiler inline (eksterne stylesheets overføres ikke), (2) Konverter SVG-strengen til en Blob, (3) Opprett et Image-element fra Blob-URL-en, (4) Tegn Image'et på et Canvas med 2x-skalering for Retina-skjermer, (5) Eksporter Canvas som en PNG via `toBlob()`. Dette produserer et 300 DPI-bilde egnet for print.
Tilstandspersistering og økt-gjenoppretting Analytikere jobber ofte med prøver over flere økter. Jeg implementerte et persistenslag som lagrer hele vindus-tilstanden (posisjoner, størrelser, åpne vinduer, scroll-posisjoner innenfor hvert vindu) til LocalStorage ved hver tilstandsendring.
Når brukeren returnerer, gjenoppretter appen deres eksakte arbeidsområde-konfigurasjon. Dette krevde nøye serialisering av kompleks tilstand - React-refs og funksjons-callbacks kan ikke serialiseres, så jeg implementerte et mønster hvor bare serialiserbar data persisteres, og komponentinstanser rekonstrueres ved lasting.
Jeg la også til en 'Save Workspace'-funksjon som lar brukere opprette navngitte arbeidsområde-presets (f.eks. 'Elektrisk testing', 'Materialanalyse'). Disse presetene lagrer hvilke vinduer som skal åpnes som standard og deres foretrukne posisjoner, slik at analytikere kan bytte mellom forskjellige arbeidsflyter umiddelbart.