diff options
| -rw-r--r-- | src/components/TimeLine.vue | 40 | ||||
| -rw-r--r-- | src/lib.ts | 65 |
2 files changed, 74 insertions, 31 deletions
diff --git a/src/components/TimeLine.vue b/src/components/TimeLine.vue index 5f39dae..1e78a87 100644 --- a/src/components/TimeLine.vue +++ b/src/components/TimeLine.vue @@ -54,6 +54,10 @@ {{idToEvent.get(id)!.title}} </div> </div> + <!-- Timeline position label --> + <div class="absolute top-2 left-2 z-20 text-lg text-stone-50"> + {{timelinePosStr}} + </div> <!-- Buttons --> <icon-button v-if="closeable" :size="30" class="absolute top-2 right-2 z-20" :style="{color: store.color.text, backgroundColor: store.color.altDark2}" @@ -70,7 +74,7 @@ import IconButton from './IconButton.vue'; // Icons import CloseIcon from './icon/CloseIcon.vue'; // Other -import {WRITING_MODE_HORZ, MIN_DATE, MAX_DATE, MONTH_SCALE, DAY_SCALE, SCALES, MIN_CAL_DATE, +import {WRITING_MODE_HORZ, MIN_DATE, MAX_DATE, MONTH_SCALE, DAY_SCALE, SCALES, MONTH_NAMES, MIN_CAL_DATE, getDaysInMonth, HistDate, stepDate, getScaleRatio, getNumSubUnits, getUnitDiff, getEventPrecision, dateToUnit, moduloPositive, TimelineState, HistEvent, getImagePath} from '../lib'; @@ -387,6 +391,21 @@ const lastIdx = computed((): number => { // Index of last major tick before whic return idx; }); const lastDate = computed(() => lastIdx.value < 0 ? endDate.value : ticks.value[lastIdx.value]!.date); +const startIsFirstVisible = computed(() => { + if (ticks.value.length == 0){ + return true; + } else { + return ticks.value.find((tick: Tick) => tick.offset >= 0)!.date.equals(startDate.value); + } +}); +const endIsLastVisible = computed(() => { + if (ticks.value.length == 0){ + return true; + } else { + let numUnits = getNumDisplayUnits(); + return ticks.value.findLast((tick: Tick) => tick.offset <= numUnits)!.date.equals(endDate.value); + } +}); // For displayed events function dateToOffset(date: HistDate){ // Assumes 'date' is >=firstDate and <=lastDate @@ -671,6 +690,25 @@ const tickToCount = computed((): Map<number, number> => { return tickToCount; }); +// For timeline position label +const timelinePosStr = computed((): string => { + const date1 = startIsFirstVisible.value ? startDate.value : firstDate.value; + const date2 = endIsLastVisible.value ? endDate.value : lastDate.value; + if (minorScale.value == DAY_SCALE){ + const multiMonth = date1.month != date2.month; + return `${date1.toYearString()} ${MONTH_NAMES[date1.month - 1]}${multiMonth ? ' >' : ''}`; + } else if (minorScale.value == MONTH_SCALE){ + const multiYear = date1.year != date2.year; + return `${date1.toYearString()}${multiYear ? ' >' : ''}`; + } else { + if (date1.year > 0){ + return `${date1.toYearString()} - ${date2.toYearString()}`; + } else { + return `${date1.toYearString()} >`; + } + } +}); + // For panning/zooming function panTimeline(scrollRatio: number){ let numUnits = getNumDisplayUnits(); @@ -80,6 +80,7 @@ export function getDaysInMonth(year: number, month: number){ // For date representation export const MIN_CAL_YEAR = -4713; // Earliest year where months/day scales are usable +export const MONTH_NAMES = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; export class HistDate { gcal: boolean | null; year: number; @@ -161,40 +162,44 @@ export class HistDate { return `${this.year}`; } } - toDisplayString(){ - if (this.month == 1 && this.day == 1){ - if (this.year > 0){ - return String(this.year); - } else if (this.year > -1e3){ + toYearString(){ + if (this.year >= 1000){ + return String(this.year); + } else if (this.year > 0){ + return String(this.year) + ' AD'; + } else if (this.year > -1e3){ + return String(-this.year) + ' BC'; + } else if (this.year > -1e6){ + if (this.year % 1e3 == 0){ + return String(Math.floor(-this.year / 1e3)) + 'k BC'; + } else if (this.year % 100 == 0){ + return String(Math.floor(-this.year / 100) / 10) + 'k BC'; + } else { return String(-this.year) + ' BC'; - } else if (this.year > -1e6){ - if (this.year % 1e3 == 0){ - return String(Math.floor(-this.year / 1e3)) + 'k BC'; - } else if (this.year % 100 == 0){ - return String(Math.floor(-this.year / 100) / 10) + 'k BC'; - } else { - return String(-this.year) + ' BC'; - } - } else if (this.year > -1e9){ - if (this.year % 1e6 == 0){ - return String(Math.floor(-this.year / 1e6)) + ' mya'; - } else if (this.year % 1e3 == 0){ - return String(Math.floor(-this.year / 1e3) / 1e3) + ' mya'; - } else { - return String(-this.year.toLocaleString()); - } + } + } else if (this.year > -1e9){ + if (this.year % 1e6 == 0){ + return String(Math.floor(-this.year / 1e6)) + ' mya'; + } else if (this.year % 1e3 == 0){ + return String(Math.floor(-this.year / 1e3) / 1e3) + ' mya'; } else { - if (this.year % 1e9 == 0){ - return String(Math.floor(-this.year / 1e9)) + ' bya'; - } else if (this.year % 1e6 == 0){ - return String(Math.floor(-this.year / 1e6) / 1e3) + ' bya'; - } else { - return String(this.year.toLocaleString()); - } + return String(this.year.toLocaleString()); + } + } else { + if (this.year % 1e9 == 0){ + return String(Math.floor(-this.year / 1e9)) + ' bya'; + } else if (this.year % 1e6 == 0){ + return String(Math.floor(-this.year / 1e6) / 1e3) + ' bya'; + } else { + return String(this.year.toLocaleString()); } + } + } + toDisplayString(){ + if (this.month == 1 && this.day == 1){ + return this.toYearString(); } else if (this.day == 1){ - const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; - return monthNames[this.month - 1]; + return MONTH_NAMES[this.month - 1]; } else { if (this.day == 1){ return '1st'; |
