Timeline: era and historical-event click-to-zoom, event markers from historical-events.ts. Movement flow: shared zoom/pan, viewport-fit layout, curved lineage streams, hover-to-reveal artist lifespans on stacked lanes. Docs updated. Includes batch-fetched paintings and regenerated thumbs. Co-authored-by: Cursor <cursoragent@cursor.com>
52 lines
1.5 KiB
TypeScript
52 lines
1.5 KiB
TypeScript
/** Shared timeline zoom/pan math for Timeline and MovementBands. */
|
|
export function zoomTimelineView(
|
|
clientX: number,
|
|
rectLeft: number,
|
|
rectWidth: number,
|
|
deltaY: number,
|
|
viewStart: number,
|
|
viewEnd: number,
|
|
absoluteMin: number,
|
|
absoluteMax: number
|
|
): { start: number; end: number } {
|
|
const span = viewEnd - viewStart;
|
|
const ratio = (clientX - rectLeft) / rectWidth;
|
|
const centerYear = viewStart + ratio * span;
|
|
const factor = deltaY > 0 ? 1.15 : 0.85;
|
|
const newSpan = Math.max(10, Math.min(absoluteMax - absoluteMin, span * factor));
|
|
let newStart = centerYear - ratio * newSpan;
|
|
let newEnd = centerYear + (1 - ratio) * newSpan;
|
|
if (newStart < absoluteMin) {
|
|
newEnd += absoluteMin - newStart;
|
|
newStart = absoluteMin;
|
|
}
|
|
if (newEnd > absoluteMax) {
|
|
newStart -= newEnd - absoluteMax;
|
|
newEnd = absoluteMax;
|
|
}
|
|
return { start: Math.round(newStart), end: Math.round(newEnd) };
|
|
}
|
|
|
|
export function panTimelineView(
|
|
deltaX: number,
|
|
rectWidth: number,
|
|
viewStart: number,
|
|
viewEnd: number,
|
|
absoluteMin: number,
|
|
absoluteMax: number
|
|
): { start: number; end: number } {
|
|
const span = viewEnd - viewStart;
|
|
const yearDelta = (deltaX / rectWidth) * span;
|
|
let newStart = viewStart - yearDelta;
|
|
let newEnd = viewEnd - yearDelta;
|
|
if (newStart < absoluteMin) {
|
|
newEnd += absoluteMin - newStart;
|
|
newStart = absoluteMin;
|
|
}
|
|
if (newEnd > absoluteMax) {
|
|
newStart -= newEnd - absoluteMax;
|
|
newEnd = absoluteMax;
|
|
}
|
|
return { start: Math.round(newStart), end: Math.round(newEnd) };
|
|
}
|