细长甘特图 - 按月分隔

Svelte Gantt Chart - Separate via months

我正在尝试制作一个包含所有 12 个月的甘特图。我通过将 from & to 值设置为 currentDate.clone().endOf('year') & currentDate.clone().endOf('year') 来实现这一点。但是甘特图在设置这些值时停止出现,如果我打印出它们有效的日期,奇怪的是,如果我将值更改为 startOf('week') & endOf('week)`,它会很好地呈现图表。这可能吗?

我正在使用的包:https://github.com/ANovokmet/svelte-gantt

编辑: 我的代码基于这个 index.js 文件:https://github.com/ANovokmet/svelte-gantt/blob/gh-pages/index.js

问题可能更简单,我如何修改它以显示月份而不是 hours/days?

function time(input) {
  return moment(input, "MMMM DD YYYY");
}

const currentStart = time(responseData.currentDate);
const currentEnd = time(responseData.currentDate);

gantt.$set({
   fitWidth: false,
   columnUnit: 'month',
   rowPadding: 6,
   rowHeight: 52,
   columnOffset: 28.8,
   magnetOffset: 15,
   from: currentStart.clone().startOf('year'),
   to: currentStart.clone().endOf('year'),
   minWidth: 800,
   headers: [{ unit: 'month', format: 'MMMM YYYY' }, { unit: 'day', format: 'ddd DD' }]
});

TL;DR: Svelte Gantt Year + Months example

(注意:svelte-gantt 在 REPL 中的行为有点挑剔,您可能需要调整渲染面板的宽度以显示默认的 10 rows/tasks)。

重要更新

我注意到月份列 headers 中存在一个问题,一月和五月被重复,二月被跳过,最终从五月开始出现 one-month 偏移(导致十二月也会消失)。这是因为 svelte-gantt 在内部处理月份持续时间的方式:所有月份都设置为 30 天 (!!)。你可以在第118行看到这个in this source file。作者甚至评论说这是不正确的...

知道这一点,您可能想重新考虑使用此模块来准确表示 yearly/monthly 甘特图,除非您分叉该项目并自己实现对可变月份持续时间的正确处理!

我是怎么到那里的

我使用 svelte-gantt large dataset demo 源作为起点,删除了 GanttOptions 导入和组件(与此问题无关)。我剩下的是一天的甘特图、每小时列和 100 个生成的行和任务(我缩短为 10)。那里的关键信息显然是 options object 作为 props:

传递给 SvelteGantt 构造函数
let options = {
    dateAdapter: new MomentSvelteGanttDateAdapter(moment),
    rows: data.rows,
    tasks: data.tasks,
    timeRanges,
    columnOffset: 15,
    magnetOffset: 15,
    rowHeight: 52,
    rowPadding: 6,
    headers: [{ unit: 'day', format: 'MMMM Do' }, { unit: 'hour', format: 'H:mm' }],
    fitWidth: true,
    minWidth: 800,
    from: currentStart,
    to: currentEnd,
    tableHeaders: [{ title: 'Label', property: 'label', width: 140, type: 'tree' }],
    tableWidth: 240,
    ganttTableModules: [SvelteGanttTable]
}

从包含小时列的单日图表到包含月列的单年图表所需的更改非常简单。

我删除了 timeRanges 选项(用于在每日图表中设置午餐和晚餐时间范围,但在年度图表中不再有用 - 尽管您 可能 想在银行假期或暑假期间再次使用它们)和相关数据。

然后我添加了columnUnit选项,将其设置为'month',并更改了columnOffset选项,将其设置为1,以便有1列每月。

最后我调整了 headers 选项,在第一行显示年份,在第二行(第 headers 列)显示缩写月份:headers: [{ unit: 'year', format: 'YYYY' }, { unit: 'month', format: 'MMM' }].

最终,修改options object:

let options = {
    dateAdapter: new MomentSvelteGanttDateAdapter(moment),
    rows: data.rows,
    tasks: data.tasks,
    columnUnit: 'month',
    columnOffset: 1,
    magnetOffset: 15,
    rowHeight: 52,
    rowPadding: 6,
    headers: [{ unit: 'year', format: 'YYYY' }, { unit: 'month', format: 'MMM' }],
    fitWidth: true,
    minWidth: 800,
    from: currentStart,
    to: currentEnd,
    tableHeaders: [{ title: 'Label', property: 'label', width: 140, type: 'tree' }],
    tableWidth: 240,
    ganttTableModules: [SvelteGanttTable]
}

然后我修改了 currentStartcurrentEnd 值以反映图表的新范围(一整年),分别将它们设置为当年的开始和结束:

const currentStart = moment().clone().startOf('year');
const currentEnd = moment().clone().endOf('year');

最后,我不得不修改任务生成过程,以便随机生成对图表的新 scale/range 足够有意义的任务:

// start of task (random day (1-20) + month (1-12))
const rand_d = (Math.random() * 20) | 0 + 1
const rand_m = (Math.random() * 12) | 0 + 1
const from = moment(`${rand_d} ${rand_m}`, 'D M')
// duration of task (random, 5 to 60 days)
const rand_l = (Math.random() * 55) | 0 + 5
const to = from.clone().add(rand_l, 'days')
tasks.push({
    type: 'task',
    id: ids[i],
    resourceId: i,
    label: 'Task #' + ids[i],
    from,
    to,
    classes: colors[(Math.random() * colors.length) | 0],
    generation
});

作为最后的清理,因为现在我不再使用 time() 效用函数,而是完全依赖 moment,所以我还删除了 import { time } from '../utils'; 语句。