diff options
| author | Terry Truong <terry06890@gmail.com> | 2023-01-07 12:37:05 +1100 |
|---|---|---|
| committer | Terry Truong <terry06890@gmail.com> | 2023-01-07 12:37:05 +1100 |
| commit | e5d4b142f6f7eb21c2b55edfbd472f503e7f3b89 (patch) | |
| tree | 7a91ccd3d970dfc9e154ca498c36a7870d4b8d39 | |
| parent | cd890bc47df00f16c54755549314cd7e15ec3219 (diff) | |
At each scale, always display a unit that includes MAX_DATEunit-after-max
Without this, with a MAX_DATE of, say 2000/1/1, zooming out to
scale 1e9 won't show events after 1 AD.
| -rw-r--r-- | src/components/TimeLine.vue | 21 | ||||
| -rw-r--r-- | src/lib.ts | 23 | ||||
| -rw-r--r-- | tests/lib.test.ts | 5 |
3 files changed, 36 insertions, 13 deletions
diff --git a/src/components/TimeLine.vue b/src/components/TimeLine.vue index 3172e80..823fe86 100644 --- a/src/components/TimeLine.vue +++ b/src/components/TimeLine.vue @@ -26,7 +26,7 @@ <line :stroke="store.color.alt" stroke-width="2px" x1="-1" y1="0" x2="2" y2="0" :style="mainlineStyles"/> <!-- Tick markers --> <template v-for="tick in ticks" :key="tick.date.toInt()"> - <line v-if="tick.major && (tick.date.equals(MIN_DATE, scale) || tick.date.equals(MAX_DATE, scale))" + <line v-if="tick.major && (tick.date.equals(MIN_DATE, scale) || tick.date.equals(maxDateOnScale, scale))" :x1="vert ? -store.endTickSz / 2 : 0" :y1="vert ? 0 : -store.endTickSz / 2" :x2="vert ? store.endTickSz / 2 : 0" :y2="vert ? 0 : store.endTickSz / 2" :stroke="store.color.alt" :stroke-width="`${store.endTickSz}px`" @@ -235,6 +235,7 @@ function initScale(){ // Initialises to smallest usable scale // Tick data const tickLabelMargin = computed(() => props.vert ? 20 : 30); // Distance from label to mainline const tickLabelWidth = computed(() => store.mainlineBreadth - store.largeTickLen / 2 - tickLabelMargin.value); +const maxDateOnScale = computed(() => dateToScaleDate(MAX_DATE, scale.value, true)); class Tick { date: HistDate; major: boolean; // False if tick is on the minor scale @@ -314,7 +315,7 @@ const ticks = computed((): Tick[] => { // Get after-endDate ticks (including end-offset ticks and hidden ticks) let endDateOffset = ticks[ticks.length - 1].offset; for (let i = 0; i < panUnits + Math.ceil(endOffset.value); i++){ - if (MAX_DATE.equals(date, scale.value)){ + if (maxDateOnScale.value.equals(date, scale.value)){ break; } // Add minor ticks @@ -349,7 +350,7 @@ const ticks = computed((): Tick[] => { offset = ticks[ticks.length - 1].offset; for (let i = 0; i < (zoomUnits - panUnits) / unitsPerZoomedUnit; i++){ date = stepDate(date, zoomedScale); - if (MAX_DATE.isEarlier(date, scale.value)){ + if (maxDateOnScale.value.isEarlier(date, scale.value)){ break; } ticksAfter.push(new Tick(date, true, offset + (i + 1) * unitsPerZoomedUnit)); @@ -731,7 +732,7 @@ function panTimeline(scrollRatio: number){ getMovedBounds(startOffset.value, endOffset.value, chgUnits, chgUnits); if (scrollRatio > 0){ while (true){ - if (newEnd.equals(MAX_DATE, scale.value)){ + if (newEnd.equals(maxDateOnScale.value, scale.value)){ // Pan up to an offset of store.defaultEndTickOffset if (store.defaultEndTickOffset == endOffset.value){ console.log('Reached maximum date limit'); @@ -824,7 +825,7 @@ function panTimeline(scrollRatio: number){ function zoomTimeline(zoomRatio: number, ignorePointer=false){ if (zoomRatio > 1 && startDate.value.equals(MIN_DATE, scale.value) - && endDate.value.equals(MAX_DATE, scale.value)){ + && endDate.value.equals(maxDateOnScale.value, scale.value)){ console.log('Reached upper scale limit'); return; } @@ -875,7 +876,7 @@ function zoomTimeline(zoomRatio: number, ignorePointer=false){ newNumUnits += 1; } while (numEndSteps > 0){ - if (MAX_DATE.equals(newEnd, scale.value)){ + if (maxDateOnScale.value.equals(newEnd, scale.value)){ newEndOffset = store.defaultEndTickOffset; break; } @@ -975,7 +976,7 @@ function zoomTimeline(zoomRatio: number, ignorePointer=false){ console.log('Unable to zoom into range where month/day scale is invalid'); return; } - if (newStart.isEarlier(MIN_DATE, newScale) || MAX_DATE.isEarlier(newEnd, newScale)){ + if (newStart.isEarlier(MIN_DATE, newScale) || maxDateOnScale.value.isEarlier(newEnd, newScale)){ console.log('Disallowing zooming in beyond min/max dates'); return; } @@ -1146,15 +1147,15 @@ watch(() => props.searchTarget, () => { targetStart = MIN_DATE; } let targetEnd = stepDate(targetStart, tempScale, {count: startEndDiff}); - if (MAX_DATE.isEarlier(targetEnd)){ + if (maxDateOnScale.value.isEarlier(targetEnd)){ if (targetStart != MIN_DATE){ targetStart = stepDate(targetStart, tempScale, - {forward: false, count: getUnitDiff(targetEnd, MAX_DATE, tempScale)}); + {forward: false, count: getUnitDiff(targetEnd, maxDateOnScale.value, tempScale)}); if (targetStart.isEarlier(MIN_DATE)){ targetStart = MIN_DATE; } } - targetEnd = MAX_DATE; + targetEnd = maxDateOnScale.value; } // Jump to range startDate.value = targetStart; @@ -582,14 +582,31 @@ export function dateToUnit(date: HistDate, scale: number): number { } } } -export function dateToScaleDate(date: HistDate, scale: number): HistDate { +export function dateToScaleDate(date: HistDate, scale: number, upward=false): HistDate { // Returns a date representing the unit on 'scale' that 'date' is within if (scale == DAY_SCALE){ return new CalDate(date.year, date.month, date.day); } else if (scale == MONTH_SCALE){ - return new CalDate(date.year, date.month, 1); + if (upward && date.day > 1){ + return stepDate(new CalDate(date.year, date.month, 1), MONTH_SCALE); + } else { + return new CalDate(date.year, date.month, 1); + } + } else if (scale == 1){ + if (upward && date.month > 1){ + return stepDate(new CalDate(date.year, 1, 1), 1); + } else { + if (date.year < MIN_CAL_YEAR){ + return new YearDate(date.year); + } else { + return new CalDate(date.year == 0 ? 1 : date.year, 1, 1); + } + } } else { - const year = Math.floor(date.year / scale) * scale; + let year = Math.floor(date.year / scale) * scale; + if (upward && moduloPositive(date.year, scale) > 0){ + year += scale; + } if (year < MIN_CAL_YEAR){ return new YearDate(year); } else { diff --git a/tests/lib.test.ts b/tests/lib.test.ts index c87627c..6bf3d89 100644 --- a/tests/lib.test.ts +++ b/tests/lib.test.ts @@ -156,11 +156,16 @@ test('dateToUnit', () => { }) test('dateToScaleDate', () => { expect(dateToScaleDate(new CalDate(2013, 10, 3), DAY_SCALE)).toEqual(new CalDate(2013, 10, 3)) + expect(dateToScaleDate(new CalDate(2013, 10, 3), DAY_SCALE, true)).toEqual(new CalDate(2013, 10, 3)) expect(dateToScaleDate(new CalDate(2013, 10, 3, false), MONTH_SCALE)).toEqual(new CalDate(2013, 10, 1)) + expect(dateToScaleDate(new CalDate(2013, 10, 3), MONTH_SCALE, true)).toEqual(new CalDate(2013, 11, 1)) expect(dateToScaleDate(new CalDate(2013, 10, 3), 1)).toEqual(new CalDate(2013, 1, 1)) + expect(dateToScaleDate(new CalDate(2013, 10, 3), 1, true)).toEqual(new CalDate(2014, 1, 1)) expect(dateToScaleDate(new CalDate(2013, 10, 3), 1e3)).toEqual(new CalDate(2000, 1, 1)) + expect(dateToScaleDate(new CalDate(2013, 10, 3), 1e3, true)).toEqual(new CalDate(3000, 1, 1)) expect(dateToScaleDate(new CalDate(2013, 10, 3), 1e4)).toEqual(new CalDate(1, 1, 1)) expect(dateToScaleDate(new YearDate(-1222333), 1e6)).toEqual(new YearDate(-2000000)) + expect(dateToScaleDate(new YearDate(-1222333), 1e6, true)).toEqual(new YearDate(-1000000)) }) test('DateRangeTree', () => { |
