Improve movement label placement and lane corridor clearing
Label priority: center, right-end inside, overflow right/left (prefer side with fewer transition-line overlaps), adjacent gap, hover-only. Exclude own portraits from collision. Min stream height 25px. Corridor clearing: 20 passes, prefer above, re-attract after move. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
8111cd0163
commit
ad1572b3aa
@@ -241,16 +241,17 @@ Major world events appear on the era bar as pin markers (single years) or shaded
|
||||
|
||||
### Movement flow
|
||||
|
||||
Each visible movement is drawn as a **portrait-width curved stream** (~54 px stroke, compressed when many rows are visible) from its start year to its end year.
|
||||
Each visible movement is drawn as a **portrait-width curved stream** (~54 px stroke, compressed when many rows are visible) in a **solid vivid colour** from its start year to its end year.
|
||||
|
||||
| Feature | Implementation |
|
||||
|---------|----------------|
|
||||
| Lineage layout | `client/src/data/movement-lineage.ts` — curated predecessor→successor pairs (Met / ArtStory / museum essays); multiple parents allowed |
|
||||
| Vertical lanes | Movements share a horizontal lane only when one ends at least **10 years** before the next starts (in the current zoom); closer or overlapping spans stack into extra rows (`assignTemporalLanes`). A follow-up pass (`refineLanesForLineageCorridors`) pulls linked parent/child movements onto nearby or shared lanes when years allow, then displaces unrelated streams out of thick lineage branch corridors |
|
||||
| Vertical lanes | Movements share a horizontal lane only when one ends at least **10 years** before the next starts (in the current zoom); closer or overlapping spans stack into extra rows (`assignTemporalLanes`). Lane choice **minimizes vertical branch length**: children prefer parent lanes (same row when years allow), corridor clearing (up to 20 passes) evicts unrelated streams preferring **rows above** the parent/child strip, then re-attracts the child toward the parent |
|
||||
| Branch connectors | Smooth curves from fan-out points along a parent stream to the **left edge (start)** of each child stream; origin X is always strictly left of the target (time-forward only — never right→left); stroke thickness matches the **target** (child) band height; color gradients from parent → child at constant opacity; a stream-shaped mask hides branch ink under movements so translucent overlaps do not brighten the bands; pan/zoom layout changes **animate** (streams + branches chase new geometry) so shifts stay trackable |
|
||||
| Band thickness | Stream height is **proportional to `influence_link_count`** (edges on paintings by artists in that movement): thicker bands for denser influence graphs; lane rows share vertical space weighted by the thickest band in each lane |
|
||||
| Filtering | A movement is drawn when its **span overlaps** the visible year range **and** it has at least one catalogued artist — artists whose lifespan falls outside the window still keep their movement visible (their portraits simply do not render). Filtered client-side after initial load |
|
||||
| Viewport layout | Row height and stream width scale from measured canvas size so every visible movement row fits in the remaining screen space |
|
||||
| Name labels | On-band **movement name** only. Label placement priority: **(1)** center of movement if label fits and no portrait collision; **(2)** right end inside band borders; **(3)** overflow right or left (up to 100% outside the band border), choosing the side with less transition-line overlap; **(4)** adjacent free gap before/after the band; **(5)** hidden until hover. Collision checks exclude the movement's own portraits (labels may overlap their own band's artists). Movements with overflow labels are packed onto **exclusive horizontal lanes** before vertical stacking so they never share a row with other movements. Minimum movement height = 125% of label height |
|
||||
|
||||
### Artists on movement streams
|
||||
|
||||
@@ -273,7 +274,7 @@ Each artist appears as a **portrait circle** on their movement’s stream row:
|
||||
| Click portrait | Open artist biography |
|
||||
| Click **movement name** (label on stream) | Open **movement gallery** for that movement |
|
||||
|
||||
**Zoom/pan performance:** The movement canvas uses a **capture-phase** wheel listener so scroll zoom works even when the cursor is over a portrait. While scrolling or dragging, a short **interaction mode** (~120 ms after the last input) draws simplified solid SVG strokes and temporarily hides portrait/label DOM so zoom stays responsive; full gradients and portraits return when you stop.
|
||||
**Zoom/pan performance:** The movement canvas uses a **capture-phase** wheel listener so scroll zoom works even when the cursor is over a portrait. While scrolling or dragging, a short **interaction mode** (~120 ms after the last input) draws simplified solid SVG strokes and temporarily hides portrait/label DOM so zoom stays responsive; full stream styling and portraits return when you stop.
|
||||
|
||||
Only **mousedown** on portraits and movement labels stops propagation (so drag-to-pan does not start when clicking them). Hovering a portrait highlights the artist’s lifespan on the era bar and brightens their segment on the movement stream.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user