diff options
| author | Terry Truong <terry06890@gmail.com> | 2023-01-07 19:48:36 +1100 |
|---|---|---|
| committer | Terry Truong <terry06890@gmail.com> | 2023-01-07 19:50:09 +1100 |
| commit | 5d25f637119f1560ce8f8171cd46123c0bba56b4 (patch) | |
| tree | 9e846f7ad1a677ae0f268ed3a927e1c4f15120ec | |
| parent | 4b323024f51a8de755e4fb6cab301c36d52132a3 (diff) | |
Throttle relayouting of eventsthrottle-relayout
Reduces CPU drain, but adds noticeable gap between panning and
event movement.
| -rw-r--r-- | src/components/TimeLine.vue | 96 |
1 files changed, 55 insertions, 41 deletions
diff --git a/src/components/TimeLine.vue b/src/components/TimeLine.vue index 9e0a48c..2f58328 100644 --- a/src/components/TimeLine.vue +++ b/src/components/TimeLine.vue @@ -435,7 +435,14 @@ function dateToOffset(date: HistDate){ // Assumes 'date' is >=firstDate and <=la return tick.offset + getUnitDiff(tick.date, date, minorScale.value) / getNumSubUnits(tick.date, scaleIdx.value); } } -const idToEvent = computed(() => { // Maps visible event IDs to HistEvents +const idToEvent: Ref<Map<number, HistEvent>> = ref(new Map()); // Maps visible event IDs to HistEvents +const idToPos: Ref<Map<number, [number, number, number, number]>> = ref(new Map()); // Maps event IDs to x/y/w/h +const idsToSkipTransition: Ref<Set<number>> = ref(new Set()); // Used to prevent events moving across mainline +type LineCoords = [number, number, number, number]; // x, y, length, angle +const eventLines: Ref<Map<number, LineCoords>> = ref(new Map()); // Maps event ID to event line data +const UPDATE_TIMEOUT = 100; // Used to throttle relayouting +let layoutUpdateHdlr = 0; +function updateIdToEvent(){ let map: Map<number, HistEvent> = new Map(); // Find events to display let itr = props.eventTree.lowerBound(new HistEvent(0, '', firstDate.value)); @@ -450,17 +457,8 @@ const idToEvent = computed(() => { // Maps visible event IDs to HistEvents } map.set(event.id, event); } - return map; -}); -watch(idToEvent, () => { // Remove highlighting of search results that have become out of range - if (searchEvent.value != null && !idToEvent.value.has(searchEvent.value.id)){ - searchEvent.value = null; - } -}); -const idToPos: Ref<Map<number, [number, number, number, number]>> = ref(new Map()); // Maps event IDs to x/y/w/h -const idsToSkipTransition: Ref<Set<number>> = ref(new Set()); // Used to prevent events moving across mainline -type LineCoords = [number, number, number, number]; // x, y, length, angle -const eventLines: Ref<Map<number, LineCoords>> = ref(new Map()); // Maps event ID to event line data + idToEvent.value = map; +} function getEventLayout(): Map<number, [number, number, number, number]> { let map: Map<number, [number, number, number, number]> = new Map(); if (!mounted.value){ @@ -633,36 +631,10 @@ function getEventLayout(): Map<number, [number, number, number, number]> { } return map; } -watch(idToEvent, () => { // Updates idToPos and eventLines - let map = getEventLayout(); - // Check for events that cross mainline - idsToSkipTransition.value.clear(); - for (let [eventId, [x, y, , ]] of map.entries()){ - if (idToPos.value.has(eventId)){ - let [oldX, oldY, , ] = idToPos.value.get(eventId)!; - if (props.vert && (oldX - mainlineOffset.value) * (x - mainlineOffset.value) < 0 - || !props.vert && (oldY - mainlineOffset.value) * (y - mainlineOffset.value) < 0){ - idsToSkipTransition.value.add(eventId); - } - } - } - // Update idToPos // Note: For some reason, if the map is assigned directly, events won't consistently transition - let toDelete = []; - for (let eventId of idToPos.value.keys()){ - if (!map.has(eventId)){ - toDelete.push(eventId); - } - } - for (let eventId of toDelete){ - idToPos.value.delete(eventId); - } - for (let [eventId, pos] of map.entries()){ - idToPos.value.set(eventId, pos); - } - // Update event lines +function updateEventLines(){ let newEventLines: Map<number, LineCoords> = new Map(); let numUnits = getNumDisplayUnits(); - for (let [id, [eventX, eventY, eventW, eventH]] of map){ + for (let [id, [eventX, eventY, eventW, eventH]] of idToPos.value.entries()){ let x: number; // For line end on mainline let y: number; let x2: number; // For line end at event @@ -700,9 +672,51 @@ watch(idToEvent, () => { // Updates idToPos and eventLines newEventLines.set(id, [x, y, l, a]); } eventLines.value = newEventLines; +} +function updateLayoutData(){ // Updates idToEvent, idToPos, idsToSkipTransition, and eventLines + // Update idToEvent + updateIdToEvent() + // Remove highlighting of search results that have become out of range + if (searchEvent.value != null && !idToEvent.value.has(searchEvent.value.id)){ + searchEvent.value = null; + } + // Get layout + let map = getEventLayout(); + // Check for events that cross mainline + idsToSkipTransition.value.clear(); + for (let [eventId, [x, y, , ]] of map.entries()){ + if (idToPos.value.has(eventId)){ + let [oldX, oldY, , ] = idToPos.value.get(eventId)!; + if (props.vert && (oldX - mainlineOffset.value) * (x - mainlineOffset.value) < 0 + || !props.vert && (oldY - mainlineOffset.value) * (y - mainlineOffset.value) < 0){ + idsToSkipTransition.value.add(eventId); + } + } + } + // Update idToPos // Note: For some reason, if the map is assigned directly, events won't consistently transition + let toDelete = []; + for (let eventId of idToPos.value.keys()){ + if (!map.has(eventId)){ + toDelete.push(eventId); + } + } + for (let eventId of toDelete){ + idToPos.value.delete(eventId); + } + for (let [eventId, pos] of map.entries()){ + idToPos.value.set(eventId, pos); + } + // Update event lines + updateEventLines(); // Notify parent emit('event-display', ID, [...map.keys()], firstDate.value, lastDate.value, minorScaleIdx.value); -}); +} +function updateLayoutDataThrottled(){ + clearTimeout(layoutUpdateHdlr); + layoutUpdateHdlr = window.setTimeout(updateLayoutData, UPDATE_TIMEOUT); +} +watch(firstDate, updateLayoutDataThrottled); +watch(() => props.eventTree, updateLayoutDataThrottled); // For event-count indicators const tickToCount = computed((): Map<number, number> => { |
