The Plan Model and Timeline Positioning
AnyTool Gantt Chart Maker keeps a single plan object as its source of truth: a plan has a name and an ordered array of tasks, and each task carries a name, an ISO start date, an ISO end date, a 0–100 percent-complete, a colour, an optional assignee, an isMilestone flag and an array of predecessor task ids. The project date range is derived automatically as the earliest start to the latest end, padded by two days on each side, and a per-day pixel width set by the day/week/month zoom converts dates to positions. Each task row’s bar is placed at left = daysBetween(projectStart, task.start) × dayWidth and given width = (durationDays + 1) × dayWidth so the span is inclusive of both end days; the progress fill is simply that width × progress ÷ 100. A milestone is a zero-duration task drawn as a diamond centred on its date instead of a bar. The same date maths drives the header ticks (day numbers, week-start dates or month names depending on zoom), a red dashed today line when the current date is in range, and optional weekend shading in day view.
- Plan → tasks (ordered array); each task has start, end, progress, colour, milestone flag and predecessor ids
- Project range = earliest start → latest end (padded); a per-day pixel width is set by the zoom
- Bar left = daysBetween(projectStart, start) × dayWidth; width = (duration + 1) × dayWidth (inclusive)
- Progress fill width = bar width × progress ÷ 100; a milestone is a zero-duration diamond
- Editing a date or duration repositions and resizes the bar live
