gantt-canvas-chart 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +36 -14
- package/dist/index.css +1 -1
- package/dist/{main.d.ts → index.d.ts} +8 -1
- package/dist/index.es.js +36 -14
- package/dist/index.umd.js +36 -14
- package/package.json +10 -3
package/dist/index.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* gantt-canvas-chart v1.0
|
|
2
|
+
* gantt-canvas-chart v1.1.0
|
|
3
3
|
* (c) 2025-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -95,6 +95,8 @@ class GanttChart {
|
|
|
95
95
|
mainCtx;
|
|
96
96
|
timelineStart;
|
|
97
97
|
timelineEnd;
|
|
98
|
+
minDate;
|
|
99
|
+
// private maxDate: Date | null;
|
|
98
100
|
pixelsPerDay;
|
|
99
101
|
scrollLeft;
|
|
100
102
|
scrollTop;
|
|
@@ -163,6 +165,7 @@ class GanttChart {
|
|
|
163
165
|
this.mainCtx = this.mainCanvas.getContext("2d");
|
|
164
166
|
this.timelineStart = /* @__PURE__ */ new Date();
|
|
165
167
|
this.timelineEnd = /* @__PURE__ */ new Date();
|
|
168
|
+
this.minDate = null;
|
|
166
169
|
this.pixelsPerDay = 40;
|
|
167
170
|
this.scrollLeft = 0;
|
|
168
171
|
this.scrollTop = 0;
|
|
@@ -178,6 +181,7 @@ class GanttChart {
|
|
|
178
181
|
this.boundHandleMouseMove = this.handleMouseMove.bind(this);
|
|
179
182
|
this.boundHandleMouseLeave = this.handleMouseLeave.bind(this);
|
|
180
183
|
this.boundHandleScroll = this.handleScroll.bind(this);
|
|
184
|
+
this.scrollToStartDate = this.scrollToStartDate.bind(this);
|
|
181
185
|
this.init();
|
|
182
186
|
}
|
|
183
187
|
init() {
|
|
@@ -218,12 +222,16 @@ class GanttChart {
|
|
|
218
222
|
this.updateDimensions();
|
|
219
223
|
this.render();
|
|
220
224
|
}
|
|
221
|
-
setData(newData) {
|
|
225
|
+
setData(newData, newConfig) {
|
|
222
226
|
this.data = newData;
|
|
223
227
|
this.buildTaskMap();
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
228
|
+
if (newConfig) {
|
|
229
|
+
this.updateConfig(newConfig);
|
|
230
|
+
} else {
|
|
231
|
+
this.calculateFullTimeline();
|
|
232
|
+
this.updateDimensions();
|
|
233
|
+
this.render();
|
|
234
|
+
}
|
|
227
235
|
}
|
|
228
236
|
destroy() {
|
|
229
237
|
if (this.resizeObserver) {
|
|
@@ -254,6 +262,7 @@ class GanttChart {
|
|
|
254
262
|
}
|
|
255
263
|
});
|
|
256
264
|
}
|
|
265
|
+
this.minDate = minDate;
|
|
257
266
|
minDate = DateUtils.addDays(minDate, -7);
|
|
258
267
|
maxDate = DateUtils.addDays(maxDate, 14);
|
|
259
268
|
switch (this.config.viewMode) {
|
|
@@ -289,8 +298,8 @@ class GanttChart {
|
|
|
289
298
|
this.viewportWidth = this.container.clientWidth;
|
|
290
299
|
this.viewportHeight = this.container.clientHeight;
|
|
291
300
|
this.mainCanvas.style.top = `${this.config.headerHeight}px`;
|
|
292
|
-
this.setupCanvas(this.headerCanvas, this.viewportWidth, this.config.headerHeight);
|
|
293
|
-
this.setupCanvas(this.mainCanvas, this.viewportWidth, this.viewportHeight - this.config.headerHeight);
|
|
301
|
+
this.headerCtx = this.setupCanvas(this.headerCanvas, this.viewportWidth, this.config.headerHeight);
|
|
302
|
+
this.mainCtx = this.setupCanvas(this.mainCanvas, this.viewportWidth, this.viewportHeight - this.config.headerHeight);
|
|
294
303
|
this.updateDimensions();
|
|
295
304
|
this.render();
|
|
296
305
|
}
|
|
@@ -328,6 +337,7 @@ class GanttChart {
|
|
|
328
337
|
canvas.style.height = `${height}px`;
|
|
329
338
|
const ctx = canvas.getContext("2d");
|
|
330
339
|
ctx.scale(this.devicePixelRatio, this.devicePixelRatio);
|
|
340
|
+
return ctx;
|
|
331
341
|
}
|
|
332
342
|
calculateAllTaskPositions() {
|
|
333
343
|
this.taskPositions.clear();
|
|
@@ -450,16 +460,16 @@ class GanttChart {
|
|
|
450
460
|
const unitWidth = this.dateToX(nextDate) - x;
|
|
451
461
|
if (upperText !== lastUpperText) {
|
|
452
462
|
ctx.fillStyle = "#333";
|
|
453
|
-
ctx.font = 'bold
|
|
463
|
+
ctx.font = 'bold 14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
|
|
454
464
|
ctx.textRendering = "optimizeLegibility";
|
|
455
465
|
ctx.textAlign = "left";
|
|
456
466
|
ctx.fillText(upperText, x + 5, h * 0.35);
|
|
457
467
|
lastUpperText = upperText;
|
|
458
468
|
}
|
|
459
469
|
ctx.fillStyle = "#000412";
|
|
460
|
-
ctx.font = '
|
|
470
|
+
ctx.font = '14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
|
|
461
471
|
ctx.textAlign = "center";
|
|
462
|
-
ctx.fillText(lowerText, x + unitWidth / 2, h * 0.7);
|
|
472
|
+
ctx.fillText(lowerText, Math.round(x + unitWidth / 2), Math.round(h * 0.7));
|
|
463
473
|
ctx.beginPath();
|
|
464
474
|
ctx.moveTo(x, h * 0.5);
|
|
465
475
|
ctx.lineTo(x, h);
|
|
@@ -693,7 +703,7 @@ class GanttChart {
|
|
|
693
703
|
const aWidth = (pos.x_actual_end ? pos.x_actual_end : this.dateToX(this.today)) - pos.x_actual_start;
|
|
694
704
|
pos.x_actual_start += aWidth * offsetX_actual;
|
|
695
705
|
pos.x_actual_end && (pos.x_actual_end = pos.x_actual_start + aWidth * percent_actual);
|
|
696
|
-
ctx.fillRect(pos.x_actual_start, taskY, aWidth * percent_actual, taskHeight);
|
|
706
|
+
ctx.fillRect(Math.round(pos.x_actual_start), Math.round(taskY + 2), Math.round(aWidth * percent_actual), Math.round(taskHeight - 2));
|
|
697
707
|
}
|
|
698
708
|
if (this.config.showPlan && pos.x_plan_start && pos.x_plan_end) {
|
|
699
709
|
ctx.strokeStyle = task.planBorderColor ? task.planBorderColor : this.config.planBorderColor;
|
|
@@ -708,16 +718,16 @@ class GanttChart {
|
|
|
708
718
|
ctx.fillStyle = "#000";
|
|
709
719
|
if (this.config.showLeftRemark && task.leftRemark) {
|
|
710
720
|
ctx.textAlign = "right";
|
|
711
|
-
ctx.fillText(task.leftRemark, Math.min(...[pos.x_plan_start, pos.x_actual_start].filter((val) => val !== null && val !== void 0)) - 8, textY);
|
|
721
|
+
ctx.fillText(task.leftRemark, Math.round(Math.min(...[pos.x_plan_start, pos.x_actual_start].filter((val) => val !== null && val !== void 0)) - 8), Math.round(textY));
|
|
712
722
|
}
|
|
713
723
|
if (this.config.showRightRemark && task.rightRemark) {
|
|
714
724
|
ctx.textAlign = "left";
|
|
715
|
-
ctx.fillText(task.rightRemark, Math.max(...[pos.x_plan_end, pos.x_actual_end].filter((val) => val !== null && val !== void 0)) + 8, textY);
|
|
725
|
+
ctx.fillText(task.rightRemark, Math.round(Math.max(...[pos.x_plan_end, pos.x_actual_end].filter((val) => val !== null && val !== void 0)) + 8), Math.round(textY));
|
|
716
726
|
}
|
|
717
727
|
if (this.config.showCenterRemark && task.centerRemark) {
|
|
718
728
|
const centerX = pos.x_actual_start + (pos.x_actual_end - pos.x_actual_start) / 2;
|
|
719
729
|
ctx.textAlign = "center";
|
|
720
|
-
ctx.fillText(task.centerRemark, centerX, textY, pos.x_actual_end - pos.x_actual_start);
|
|
730
|
+
ctx.fillText(task.centerRemark, Math.round(centerX), Math.round(textY), Math.round(pos.x_actual_end - pos.x_actual_start));
|
|
721
731
|
}
|
|
722
732
|
}
|
|
723
733
|
getTaskStyles(task) {
|
|
@@ -811,6 +821,18 @@ class GanttChart {
|
|
|
811
821
|
static getTaskWidthPercent(diffMilliseconds, pixelsPerDay) {
|
|
812
822
|
return diffMilliseconds * pixelsPerDay / DateUtils.ONE_DAY_MS;
|
|
813
823
|
}
|
|
824
|
+
/**
|
|
825
|
+
* scroll to specified date position, default to minDate
|
|
826
|
+
*
|
|
827
|
+
* @param date
|
|
828
|
+
*/
|
|
829
|
+
scrollToStartDate(date) {
|
|
830
|
+
const startDate = date ? date : this.minDate;
|
|
831
|
+
if (startDate) {
|
|
832
|
+
const xPosition = this.dateToX(startDate);
|
|
833
|
+
this.container.scrollTo({ left: xPosition - 80 });
|
|
834
|
+
}
|
|
835
|
+
}
|
|
814
836
|
}
|
|
815
837
|
exports.DateUtils = DateUtils;
|
|
816
838
|
exports.GanttChart = GanttChart;
|
package/dist/index.css
CHANGED
|
@@ -33,6 +33,7 @@ export declare class GanttChart {
|
|
|
33
33
|
private mainCtx;
|
|
34
34
|
private timelineStart;
|
|
35
35
|
private timelineEnd;
|
|
36
|
+
private minDate;
|
|
36
37
|
private pixelsPerDay;
|
|
37
38
|
private scrollLeft;
|
|
38
39
|
private scrollTop;
|
|
@@ -54,7 +55,7 @@ export declare class GanttChart {
|
|
|
54
55
|
private buildTaskMap;
|
|
55
56
|
private setupEvents;
|
|
56
57
|
updateConfig(newConfig: GanttConfig): void;
|
|
57
|
-
setData(newData: GanttData): void;
|
|
58
|
+
setData(newData: GanttData, newConfig?: GanttConfig): void;
|
|
58
59
|
destroy(): void;
|
|
59
60
|
private calculateFullTimeline;
|
|
60
61
|
private updatePixelsPerDay;
|
|
@@ -88,6 +89,12 @@ export declare class GanttChart {
|
|
|
88
89
|
* @returns
|
|
89
90
|
*/
|
|
90
91
|
static getTaskWidthPercent(diffMilliseconds: number, pixelsPerDay: number): number;
|
|
92
|
+
/**
|
|
93
|
+
* scroll to specified date position, default to minDate
|
|
94
|
+
*
|
|
95
|
+
* @param date
|
|
96
|
+
*/
|
|
97
|
+
scrollToStartDate(date?: Date): void;
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
declare interface GanttConfig {
|
package/dist/index.es.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* gantt-canvas-chart v1.0
|
|
2
|
+
* gantt-canvas-chart v1.1.0
|
|
3
3
|
* (c) 2025-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -93,6 +93,8 @@ class GanttChart {
|
|
|
93
93
|
mainCtx;
|
|
94
94
|
timelineStart;
|
|
95
95
|
timelineEnd;
|
|
96
|
+
minDate;
|
|
97
|
+
// private maxDate: Date | null;
|
|
96
98
|
pixelsPerDay;
|
|
97
99
|
scrollLeft;
|
|
98
100
|
scrollTop;
|
|
@@ -161,6 +163,7 @@ class GanttChart {
|
|
|
161
163
|
this.mainCtx = this.mainCanvas.getContext("2d");
|
|
162
164
|
this.timelineStart = /* @__PURE__ */ new Date();
|
|
163
165
|
this.timelineEnd = /* @__PURE__ */ new Date();
|
|
166
|
+
this.minDate = null;
|
|
164
167
|
this.pixelsPerDay = 40;
|
|
165
168
|
this.scrollLeft = 0;
|
|
166
169
|
this.scrollTop = 0;
|
|
@@ -176,6 +179,7 @@ class GanttChart {
|
|
|
176
179
|
this.boundHandleMouseMove = this.handleMouseMove.bind(this);
|
|
177
180
|
this.boundHandleMouseLeave = this.handleMouseLeave.bind(this);
|
|
178
181
|
this.boundHandleScroll = this.handleScroll.bind(this);
|
|
182
|
+
this.scrollToStartDate = this.scrollToStartDate.bind(this);
|
|
179
183
|
this.init();
|
|
180
184
|
}
|
|
181
185
|
init() {
|
|
@@ -216,12 +220,16 @@ class GanttChart {
|
|
|
216
220
|
this.updateDimensions();
|
|
217
221
|
this.render();
|
|
218
222
|
}
|
|
219
|
-
setData(newData) {
|
|
223
|
+
setData(newData, newConfig) {
|
|
220
224
|
this.data = newData;
|
|
221
225
|
this.buildTaskMap();
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
226
|
+
if (newConfig) {
|
|
227
|
+
this.updateConfig(newConfig);
|
|
228
|
+
} else {
|
|
229
|
+
this.calculateFullTimeline();
|
|
230
|
+
this.updateDimensions();
|
|
231
|
+
this.render();
|
|
232
|
+
}
|
|
225
233
|
}
|
|
226
234
|
destroy() {
|
|
227
235
|
if (this.resizeObserver) {
|
|
@@ -252,6 +260,7 @@ class GanttChart {
|
|
|
252
260
|
}
|
|
253
261
|
});
|
|
254
262
|
}
|
|
263
|
+
this.minDate = minDate;
|
|
255
264
|
minDate = DateUtils.addDays(minDate, -7);
|
|
256
265
|
maxDate = DateUtils.addDays(maxDate, 14);
|
|
257
266
|
switch (this.config.viewMode) {
|
|
@@ -287,8 +296,8 @@ class GanttChart {
|
|
|
287
296
|
this.viewportWidth = this.container.clientWidth;
|
|
288
297
|
this.viewportHeight = this.container.clientHeight;
|
|
289
298
|
this.mainCanvas.style.top = `${this.config.headerHeight}px`;
|
|
290
|
-
this.setupCanvas(this.headerCanvas, this.viewportWidth, this.config.headerHeight);
|
|
291
|
-
this.setupCanvas(this.mainCanvas, this.viewportWidth, this.viewportHeight - this.config.headerHeight);
|
|
299
|
+
this.headerCtx = this.setupCanvas(this.headerCanvas, this.viewportWidth, this.config.headerHeight);
|
|
300
|
+
this.mainCtx = this.setupCanvas(this.mainCanvas, this.viewportWidth, this.viewportHeight - this.config.headerHeight);
|
|
292
301
|
this.updateDimensions();
|
|
293
302
|
this.render();
|
|
294
303
|
}
|
|
@@ -326,6 +335,7 @@ class GanttChart {
|
|
|
326
335
|
canvas.style.height = `${height}px`;
|
|
327
336
|
const ctx = canvas.getContext("2d");
|
|
328
337
|
ctx.scale(this.devicePixelRatio, this.devicePixelRatio);
|
|
338
|
+
return ctx;
|
|
329
339
|
}
|
|
330
340
|
calculateAllTaskPositions() {
|
|
331
341
|
this.taskPositions.clear();
|
|
@@ -448,16 +458,16 @@ class GanttChart {
|
|
|
448
458
|
const unitWidth = this.dateToX(nextDate) - x;
|
|
449
459
|
if (upperText !== lastUpperText) {
|
|
450
460
|
ctx.fillStyle = "#333";
|
|
451
|
-
ctx.font = 'bold
|
|
461
|
+
ctx.font = 'bold 14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
|
|
452
462
|
ctx.textRendering = "optimizeLegibility";
|
|
453
463
|
ctx.textAlign = "left";
|
|
454
464
|
ctx.fillText(upperText, x + 5, h * 0.35);
|
|
455
465
|
lastUpperText = upperText;
|
|
456
466
|
}
|
|
457
467
|
ctx.fillStyle = "#000412";
|
|
458
|
-
ctx.font = '
|
|
468
|
+
ctx.font = '14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
|
|
459
469
|
ctx.textAlign = "center";
|
|
460
|
-
ctx.fillText(lowerText, x + unitWidth / 2, h * 0.7);
|
|
470
|
+
ctx.fillText(lowerText, Math.round(x + unitWidth / 2), Math.round(h * 0.7));
|
|
461
471
|
ctx.beginPath();
|
|
462
472
|
ctx.moveTo(x, h * 0.5);
|
|
463
473
|
ctx.lineTo(x, h);
|
|
@@ -691,7 +701,7 @@ class GanttChart {
|
|
|
691
701
|
const aWidth = (pos.x_actual_end ? pos.x_actual_end : this.dateToX(this.today)) - pos.x_actual_start;
|
|
692
702
|
pos.x_actual_start += aWidth * offsetX_actual;
|
|
693
703
|
pos.x_actual_end && (pos.x_actual_end = pos.x_actual_start + aWidth * percent_actual);
|
|
694
|
-
ctx.fillRect(pos.x_actual_start, taskY, aWidth * percent_actual, taskHeight);
|
|
704
|
+
ctx.fillRect(Math.round(pos.x_actual_start), Math.round(taskY + 2), Math.round(aWidth * percent_actual), Math.round(taskHeight - 2));
|
|
695
705
|
}
|
|
696
706
|
if (this.config.showPlan && pos.x_plan_start && pos.x_plan_end) {
|
|
697
707
|
ctx.strokeStyle = task.planBorderColor ? task.planBorderColor : this.config.planBorderColor;
|
|
@@ -706,16 +716,16 @@ class GanttChart {
|
|
|
706
716
|
ctx.fillStyle = "#000";
|
|
707
717
|
if (this.config.showLeftRemark && task.leftRemark) {
|
|
708
718
|
ctx.textAlign = "right";
|
|
709
|
-
ctx.fillText(task.leftRemark, Math.min(...[pos.x_plan_start, pos.x_actual_start].filter((val) => val !== null && val !== void 0)) - 8, textY);
|
|
719
|
+
ctx.fillText(task.leftRemark, Math.round(Math.min(...[pos.x_plan_start, pos.x_actual_start].filter((val) => val !== null && val !== void 0)) - 8), Math.round(textY));
|
|
710
720
|
}
|
|
711
721
|
if (this.config.showRightRemark && task.rightRemark) {
|
|
712
722
|
ctx.textAlign = "left";
|
|
713
|
-
ctx.fillText(task.rightRemark, Math.max(...[pos.x_plan_end, pos.x_actual_end].filter((val) => val !== null && val !== void 0)) + 8, textY);
|
|
723
|
+
ctx.fillText(task.rightRemark, Math.round(Math.max(...[pos.x_plan_end, pos.x_actual_end].filter((val) => val !== null && val !== void 0)) + 8), Math.round(textY));
|
|
714
724
|
}
|
|
715
725
|
if (this.config.showCenterRemark && task.centerRemark) {
|
|
716
726
|
const centerX = pos.x_actual_start + (pos.x_actual_end - pos.x_actual_start) / 2;
|
|
717
727
|
ctx.textAlign = "center";
|
|
718
|
-
ctx.fillText(task.centerRemark, centerX, textY, pos.x_actual_end - pos.x_actual_start);
|
|
728
|
+
ctx.fillText(task.centerRemark, Math.round(centerX), Math.round(textY), Math.round(pos.x_actual_end - pos.x_actual_start));
|
|
719
729
|
}
|
|
720
730
|
}
|
|
721
731
|
getTaskStyles(task) {
|
|
@@ -809,6 +819,18 @@ class GanttChart {
|
|
|
809
819
|
static getTaskWidthPercent(diffMilliseconds, pixelsPerDay) {
|
|
810
820
|
return diffMilliseconds * pixelsPerDay / DateUtils.ONE_DAY_MS;
|
|
811
821
|
}
|
|
822
|
+
/**
|
|
823
|
+
* scroll to specified date position, default to minDate
|
|
824
|
+
*
|
|
825
|
+
* @param date
|
|
826
|
+
*/
|
|
827
|
+
scrollToStartDate(date) {
|
|
828
|
+
const startDate = date ? date : this.minDate;
|
|
829
|
+
if (startDate) {
|
|
830
|
+
const xPosition = this.dateToX(startDate);
|
|
831
|
+
this.container.scrollTo({ left: xPosition - 80 });
|
|
832
|
+
}
|
|
833
|
+
}
|
|
812
834
|
}
|
|
813
835
|
export {
|
|
814
836
|
DateUtils,
|
package/dist/index.umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* gantt-canvas-chart v1.0
|
|
2
|
+
* gantt-canvas-chart v1.1.0
|
|
3
3
|
* (c) 2025-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -97,6 +97,8 @@
|
|
|
97
97
|
mainCtx;
|
|
98
98
|
timelineStart;
|
|
99
99
|
timelineEnd;
|
|
100
|
+
minDate;
|
|
101
|
+
// private maxDate: Date | null;
|
|
100
102
|
pixelsPerDay;
|
|
101
103
|
scrollLeft;
|
|
102
104
|
scrollTop;
|
|
@@ -165,6 +167,7 @@
|
|
|
165
167
|
this.mainCtx = this.mainCanvas.getContext("2d");
|
|
166
168
|
this.timelineStart = /* @__PURE__ */ new Date();
|
|
167
169
|
this.timelineEnd = /* @__PURE__ */ new Date();
|
|
170
|
+
this.minDate = null;
|
|
168
171
|
this.pixelsPerDay = 40;
|
|
169
172
|
this.scrollLeft = 0;
|
|
170
173
|
this.scrollTop = 0;
|
|
@@ -180,6 +183,7 @@
|
|
|
180
183
|
this.boundHandleMouseMove = this.handleMouseMove.bind(this);
|
|
181
184
|
this.boundHandleMouseLeave = this.handleMouseLeave.bind(this);
|
|
182
185
|
this.boundHandleScroll = this.handleScroll.bind(this);
|
|
186
|
+
this.scrollToStartDate = this.scrollToStartDate.bind(this);
|
|
183
187
|
this.init();
|
|
184
188
|
}
|
|
185
189
|
init() {
|
|
@@ -220,12 +224,16 @@
|
|
|
220
224
|
this.updateDimensions();
|
|
221
225
|
this.render();
|
|
222
226
|
}
|
|
223
|
-
setData(newData) {
|
|
227
|
+
setData(newData, newConfig) {
|
|
224
228
|
this.data = newData;
|
|
225
229
|
this.buildTaskMap();
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
230
|
+
if (newConfig) {
|
|
231
|
+
this.updateConfig(newConfig);
|
|
232
|
+
} else {
|
|
233
|
+
this.calculateFullTimeline();
|
|
234
|
+
this.updateDimensions();
|
|
235
|
+
this.render();
|
|
236
|
+
}
|
|
229
237
|
}
|
|
230
238
|
destroy() {
|
|
231
239
|
if (this.resizeObserver) {
|
|
@@ -256,6 +264,7 @@
|
|
|
256
264
|
}
|
|
257
265
|
});
|
|
258
266
|
}
|
|
267
|
+
this.minDate = minDate;
|
|
259
268
|
minDate = DateUtils.addDays(minDate, -7);
|
|
260
269
|
maxDate = DateUtils.addDays(maxDate, 14);
|
|
261
270
|
switch (this.config.viewMode) {
|
|
@@ -291,8 +300,8 @@
|
|
|
291
300
|
this.viewportWidth = this.container.clientWidth;
|
|
292
301
|
this.viewportHeight = this.container.clientHeight;
|
|
293
302
|
this.mainCanvas.style.top = `${this.config.headerHeight}px`;
|
|
294
|
-
this.setupCanvas(this.headerCanvas, this.viewportWidth, this.config.headerHeight);
|
|
295
|
-
this.setupCanvas(this.mainCanvas, this.viewportWidth, this.viewportHeight - this.config.headerHeight);
|
|
303
|
+
this.headerCtx = this.setupCanvas(this.headerCanvas, this.viewportWidth, this.config.headerHeight);
|
|
304
|
+
this.mainCtx = this.setupCanvas(this.mainCanvas, this.viewportWidth, this.viewportHeight - this.config.headerHeight);
|
|
296
305
|
this.updateDimensions();
|
|
297
306
|
this.render();
|
|
298
307
|
}
|
|
@@ -330,6 +339,7 @@
|
|
|
330
339
|
canvas.style.height = `${height}px`;
|
|
331
340
|
const ctx = canvas.getContext("2d");
|
|
332
341
|
ctx.scale(this.devicePixelRatio, this.devicePixelRatio);
|
|
342
|
+
return ctx;
|
|
333
343
|
}
|
|
334
344
|
calculateAllTaskPositions() {
|
|
335
345
|
this.taskPositions.clear();
|
|
@@ -452,16 +462,16 @@
|
|
|
452
462
|
const unitWidth = this.dateToX(nextDate) - x;
|
|
453
463
|
if (upperText !== lastUpperText) {
|
|
454
464
|
ctx.fillStyle = "#333";
|
|
455
|
-
ctx.font = 'bold
|
|
465
|
+
ctx.font = 'bold 14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
|
|
456
466
|
ctx.textRendering = "optimizeLegibility";
|
|
457
467
|
ctx.textAlign = "left";
|
|
458
468
|
ctx.fillText(upperText, x + 5, h * 0.35);
|
|
459
469
|
lastUpperText = upperText;
|
|
460
470
|
}
|
|
461
471
|
ctx.fillStyle = "#000412";
|
|
462
|
-
ctx.font = '
|
|
472
|
+
ctx.font = '14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
|
|
463
473
|
ctx.textAlign = "center";
|
|
464
|
-
ctx.fillText(lowerText, x + unitWidth / 2, h * 0.7);
|
|
474
|
+
ctx.fillText(lowerText, Math.round(x + unitWidth / 2), Math.round(h * 0.7));
|
|
465
475
|
ctx.beginPath();
|
|
466
476
|
ctx.moveTo(x, h * 0.5);
|
|
467
477
|
ctx.lineTo(x, h);
|
|
@@ -695,7 +705,7 @@
|
|
|
695
705
|
const aWidth = (pos.x_actual_end ? pos.x_actual_end : this.dateToX(this.today)) - pos.x_actual_start;
|
|
696
706
|
pos.x_actual_start += aWidth * offsetX_actual;
|
|
697
707
|
pos.x_actual_end && (pos.x_actual_end = pos.x_actual_start + aWidth * percent_actual);
|
|
698
|
-
ctx.fillRect(pos.x_actual_start, taskY, aWidth * percent_actual, taskHeight);
|
|
708
|
+
ctx.fillRect(Math.round(pos.x_actual_start), Math.round(taskY + 2), Math.round(aWidth * percent_actual), Math.round(taskHeight - 2));
|
|
699
709
|
}
|
|
700
710
|
if (this.config.showPlan && pos.x_plan_start && pos.x_plan_end) {
|
|
701
711
|
ctx.strokeStyle = task.planBorderColor ? task.planBorderColor : this.config.planBorderColor;
|
|
@@ -710,16 +720,16 @@
|
|
|
710
720
|
ctx.fillStyle = "#000";
|
|
711
721
|
if (this.config.showLeftRemark && task.leftRemark) {
|
|
712
722
|
ctx.textAlign = "right";
|
|
713
|
-
ctx.fillText(task.leftRemark, Math.min(...[pos.x_plan_start, pos.x_actual_start].filter((val) => val !== null && val !== void 0)) - 8, textY);
|
|
723
|
+
ctx.fillText(task.leftRemark, Math.round(Math.min(...[pos.x_plan_start, pos.x_actual_start].filter((val) => val !== null && val !== void 0)) - 8), Math.round(textY));
|
|
714
724
|
}
|
|
715
725
|
if (this.config.showRightRemark && task.rightRemark) {
|
|
716
726
|
ctx.textAlign = "left";
|
|
717
|
-
ctx.fillText(task.rightRemark, Math.max(...[pos.x_plan_end, pos.x_actual_end].filter((val) => val !== null && val !== void 0)) + 8, textY);
|
|
727
|
+
ctx.fillText(task.rightRemark, Math.round(Math.max(...[pos.x_plan_end, pos.x_actual_end].filter((val) => val !== null && val !== void 0)) + 8), Math.round(textY));
|
|
718
728
|
}
|
|
719
729
|
if (this.config.showCenterRemark && task.centerRemark) {
|
|
720
730
|
const centerX = pos.x_actual_start + (pos.x_actual_end - pos.x_actual_start) / 2;
|
|
721
731
|
ctx.textAlign = "center";
|
|
722
|
-
ctx.fillText(task.centerRemark, centerX, textY, pos.x_actual_end - pos.x_actual_start);
|
|
732
|
+
ctx.fillText(task.centerRemark, Math.round(centerX), Math.round(textY), Math.round(pos.x_actual_end - pos.x_actual_start));
|
|
723
733
|
}
|
|
724
734
|
}
|
|
725
735
|
getTaskStyles(task) {
|
|
@@ -813,6 +823,18 @@
|
|
|
813
823
|
static getTaskWidthPercent(diffMilliseconds, pixelsPerDay) {
|
|
814
824
|
return diffMilliseconds * pixelsPerDay / DateUtils.ONE_DAY_MS;
|
|
815
825
|
}
|
|
826
|
+
/**
|
|
827
|
+
* scroll to specified date position, default to minDate
|
|
828
|
+
*
|
|
829
|
+
* @param date
|
|
830
|
+
*/
|
|
831
|
+
scrollToStartDate(date) {
|
|
832
|
+
const startDate = date ? date : this.minDate;
|
|
833
|
+
if (startDate) {
|
|
834
|
+
const xPosition = this.dateToX(startDate);
|
|
835
|
+
this.container.scrollTo({ left: xPosition - 80 });
|
|
836
|
+
}
|
|
837
|
+
}
|
|
816
838
|
}
|
|
817
839
|
exports2.DateUtils = DateUtils;
|
|
818
840
|
exports2.GanttChart = GanttChart;
|
package/package.json
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gantt-canvas-chart",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "High performance Gantt chart component based on Canvas, can be applied to any framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.es.js",
|
|
7
7
|
"module": "dist/index.es.js",
|
|
8
|
-
"types": "dist/
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
9
|
"unpkg": "dist/index.umd.js",
|
|
10
10
|
"jsdelivr": "dist/index.umd.js",
|
|
11
|
+
"typesVersions": {
|
|
12
|
+
"*": {
|
|
13
|
+
".": [
|
|
14
|
+
"./dist/index.d.ts"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
11
18
|
"exports": {
|
|
12
19
|
".": {
|
|
13
|
-
"types": "./dist/
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
14
21
|
"import": "./dist/index.es.js",
|
|
15
22
|
"require": "./dist/index.umd.cjs"
|
|
16
23
|
},
|