82 lines
3.0 KiB
JavaScript
82 lines
3.0 KiB
JavaScript
// TimeCalculator:时间轴计算器,负责时间与像素的转换、生成时间刻度等
|
||
export default class TimeCalculator {
|
||
constructor(config) {
|
||
this.config = config;
|
||
this.scaleMap = { day: 40, week: 80, month: 200, quarter: 600 }; // 每单位像素宽度
|
||
}
|
||
// 日期转像素坐标
|
||
dateToPixel(date) {
|
||
const start = new Date(this.config.startDate);
|
||
const d = new Date(date);
|
||
const scale = this.scaleMap[this.config.timeScale] || 80;
|
||
let diff = 0;
|
||
if (this.config.timeScale === 'day') {
|
||
diff = (d - start) / (1000 * 3600 * 24);
|
||
} else if (this.config.timeScale === 'week') {
|
||
diff = (d - start) / (1000 * 3600 * 24 * 7);
|
||
} else if (this.config.timeScale === 'month') {
|
||
diff = (d.getFullYear() - start.getFullYear()) * 12 + (d.getMonth() - start.getMonth());
|
||
} else if (this.config.timeScale === 'quarter') {
|
||
diff = ((d.getFullYear() - start.getFullYear()) * 12 + (d.getMonth() - start.getMonth())) / 3;
|
||
}
|
||
return diff * scale;
|
||
}
|
||
// 像素转日期(仅简单实现,实际可扩展)
|
||
pixelToDate(pixel) {
|
||
const start = new Date(this.config.startDate);
|
||
const scale = this.scaleMap[this.config.timeScale] || 80;
|
||
let d = new Date(start);
|
||
if (this.config.timeScale === 'day') {
|
||
d.setDate(start.getDate() + pixel / scale);
|
||
} else if (this.config.timeScale === 'week') {
|
||
d.setDate(start.getDate() + (pixel / scale) * 7);
|
||
} else if (this.config.timeScale === 'month') {
|
||
d.setMonth(start.getMonth() + pixel / scale);
|
||
} else if (this.config.timeScale === 'quarter') {
|
||
d.setMonth(start.getMonth() + (pixel / scale) * 3);
|
||
}
|
||
return d;
|
||
}
|
||
// 生成时间轴刻度
|
||
getTimelineTicks() {
|
||
const ticks = [];
|
||
const start = new Date(this.config.startDate);
|
||
const end = new Date(this.config.endDate);
|
||
let cur = new Date(start);
|
||
while (cur <= end) {
|
||
ticks.push({
|
||
label: this.formatTick(cur),
|
||
date: new Date(cur)
|
||
});
|
||
if (this.config.timeScale === 'day') {
|
||
cur.setDate(cur.getDate() + 1);
|
||
} else if (this.config.timeScale === 'week') {
|
||
cur.setDate(cur.getDate() + 7);
|
||
} else if (this.config.timeScale === 'month') {
|
||
cur.setMonth(cur.getMonth() + 1);
|
||
} else if (this.config.timeScale === 'quarter') {
|
||
cur.setMonth(cur.getMonth() + 3);
|
||
}
|
||
}
|
||
return ticks;
|
||
}
|
||
// 格式化刻度
|
||
formatTick(date) {
|
||
if (this.config.timeScale === 'day') {
|
||
return date.toISOString().slice(5, 10);
|
||
} else if (this.config.timeScale === 'week') {
|
||
return 'W' + this.getWeekNumber(date);
|
||
} else if (this.config.timeScale === 'month') {
|
||
return date.getFullYear() + '-' + (date.getMonth() + 1);
|
||
} else if (this.config.timeScale === 'quarter') {
|
||
return date.getFullYear() + ' Q' + (Math.floor(date.getMonth() / 3) + 1);
|
||
}
|
||
return '';
|
||
}
|
||
// 获取周数
|
||
getWeekNumber(date) {
|
||
const firstDay = new Date(date.getFullYear(), 0, 1);
|
||
const dayOfYear = ((date - firstDay) / 86400000) + 1;
|
||
return Math.ceil(dayOfYear / 7);
|
||
}
|
||
}
|