gantt-canvas-chart 1.3.0 → 1.3.1

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * gantt-canvas-chart v1.3.0
2
+ * gantt-canvas-chart v1.3.1
3
3
  * (c) 2025-present chandq
4
4
  * Released under the MIT License.
5
5
  */
@@ -196,6 +196,7 @@ class GanttChart {
196
196
  this.handleScroll = this.handleScroll.bind(this);
197
197
  this.horizontalScrollTo = this.horizontalScrollTo.bind(this);
198
198
  this.verticalScrollTo = this.verticalScrollTo.bind(this);
199
+ this.handleResize = this.handleResize.bind(this);
199
200
  this.init();
200
201
  }
201
202
  init() {
@@ -218,7 +219,6 @@ class GanttChart {
218
219
  }
219
220
  setupEvents() {
220
221
  this.container.addEventListener("scroll", this.handleScroll);
221
- this.handleResize = this.handleResize.bind(this);
222
222
  if (window.ResizeObserver) {
223
223
  this.resizeObserver = new ResizeObserver(this.handleResize);
224
224
  setTimeout(() => {
@@ -260,6 +260,9 @@ class GanttChart {
260
260
  this.container.removeEventListener("scroll", this.handleScroll);
261
261
  this.mainCanvas.removeEventListener("mousemove", this.handleMouseMove);
262
262
  this.mainCanvas.removeEventListener("mouseleave", this.handleMouseLeave);
263
+ this.data = [];
264
+ this.taskMap.clear();
265
+ this.taskPositions.clear();
263
266
  this.container.remove();
264
267
  }
265
268
  calculateFullTimeline() {
@@ -375,13 +378,10 @@ class GanttChart {
375
378
  try {
376
379
  if (this.hasMoreDataLeft && atLeftEdge && scrollLeft < this.lastScrollLeft) {
377
380
  await this.loadMoreData("left");
378
- console.log("left-loadMoreData::", this.data);
379
381
  } else if (this.hasMoreDataRight && atRightEdge && scrollLeft > this.lastScrollLeft) {
380
382
  await this.loadMoreData("right");
381
- console.log("right-loadMoreData::", this.data);
382
383
  } else if (this.hasMoreDataBottom && atBottomEdge && scrollTop > this.lastScrollTop) {
383
384
  await this.loadMoreData("bottom");
384
- console.log("bottom-loadMoreData::", this.data);
385
385
  }
386
386
  } finally {
387
387
  this.lastScrollLeft = scrollLeft;
@@ -510,17 +510,39 @@ class GanttChart {
510
510
  const x_plan_start = this.dateToX(new Date(task.planStart));
511
511
  const x_plan_end = this.dateToX(DateUtils.addDays(task.planEnd, 1));
512
512
  let x_actual_start = null, x_actual_end = null;
513
+ let offset_x_plan_start = NaN, offset_x_plan_end = NaN;
514
+ let offset_x_actual_start = null, offset_x_actual_end = null;
515
+ let x_plan_width = 0;
516
+ let x_actual_width = 0;
517
+ const [offsetX_actual, percent_actual] = this.config.viewMode === "Day" && task.actualOffsetPercent ? task.actualOffsetPercent : [0, 1];
518
+ const [offsetX, percent_plan] = this.config.viewMode === "Day" && task.planOffsetPercent ? task.planOffsetPercent : [0, 1];
519
+ if (x_plan_start && x_plan_end) {
520
+ x_plan_width = x_plan_end - x_plan_start;
521
+ offset_x_plan_start = x_plan_start + x_plan_width * offsetX;
522
+ x_plan_end && (offset_x_plan_end = offset_x_plan_start + x_plan_width * percent_plan);
523
+ }
513
524
  if (task.actualStart) {
514
525
  x_actual_start = this.dateToX(new Date(task.actualStart));
515
526
  }
516
527
  if (task.actualEnd) {
517
528
  x_actual_end = this.dateToX(DateUtils.addDays(task.actualEnd, 1));
518
529
  }
530
+ if (x_actual_start) {
531
+ x_actual_width = (x_actual_end ? x_actual_end : this.dateToX(this.today)) - x_actual_start;
532
+ offset_x_actual_start = Math.round(x_actual_start + x_actual_width * offsetX_actual);
533
+ x_actual_end && (offset_x_actual_end = offset_x_actual_start + x_actual_width * percent_actual);
534
+ }
519
535
  this.taskPositions.set(task.id, {
520
536
  x_plan_start,
521
537
  x_plan_end,
522
538
  x_actual_start,
523
539
  x_actual_end,
540
+ offset_x_plan_start,
541
+ offset_x_plan_end,
542
+ offset_x_actual_start,
543
+ offset_x_actual_end,
544
+ x_plan_width,
545
+ x_actual_width,
524
546
  y: y + this.config.rowHeight * 0.5,
525
547
  row: i
526
548
  });
@@ -765,9 +787,9 @@ class GanttChart {
765
787
  if (!fromPos) return;
766
788
  const fromRowIndex = this.taskMap.get(depId).row;
767
789
  const isAdjacent = Math.abs(toRowIndex - fromRowIndex) === 1;
768
- const fromX = Math.max(fromPos.x_plan_end, fromPos.x_actual_end || fromPos.x_plan_end);
790
+ const fromX = Math.max(fromPos.offset_x_plan_end, fromPos.offset_x_actual_end || fromPos.offset_x_plan_end);
769
791
  const fromY = fromPos.y;
770
- const toX = Math.min(toPos.x_plan_start, toPos.x_actual_start || toPos.x_plan_start);
792
+ const toX = Math.min(toPos.offset_x_plan_start, toPos.offset_x_actual_start || toPos.offset_x_plan_start);
771
793
  const toY = toPos.y;
772
794
  ctx.beginPath();
773
795
  if (isAdjacent) {
@@ -922,42 +944,35 @@ class GanttChart {
922
944
  }
923
945
  drawTask(ctx, task, y, pos) {
924
946
  const offset = 4;
925
- const width = pos.x_plan_end - pos.x_plan_start;
926
947
  const taskY = y + this.config.rowHeight * 0.15 + offset;
927
948
  const taskHeight = this.config.rowHeight * 0.7 - offset;
928
949
  const textY = y + this.config.rowHeight / 2 + offset;
929
950
  const [offsetX_actual, percent_actual] = this.config.viewMode === "Day" && task.actualOffsetPercent ? task.actualOffsetPercent : [0, 1];
930
- const [offsetX, percent_plan] = this.config.viewMode === "Day" && task.planOffsetPercent ? task.planOffsetPercent : [0, 1];
931
951
  if (this.config.showActual && pos.x_actual_start) {
932
952
  ctx.fillStyle = task.actualBgColor ? task.actualBgColor : this.config.actualBgColor;
933
- const aWidth = (pos.x_actual_end ? pos.x_actual_end : this.dateToX(this.today)) - pos.x_actual_start;
934
- pos.x_actual_start += aWidth * offsetX_actual;
935
- pos.x_actual_end && (pos.x_actual_end = pos.x_actual_start + aWidth * percent_actual);
936
- ctx.fillRect(Math.round(pos.x_actual_start), Math.round(taskY + 2), Math.round(aWidth * percent_actual), Math.round(taskHeight - 2));
953
+ ctx.fillRect(pos.offset_x_actual_start, Math.round(taskY + 2), Math.round(pos.x_actual_width * percent_actual), Math.round(taskHeight - 2));
937
954
  }
938
955
  if (this.config.showPlan && pos.x_plan_start && pos.x_plan_end) {
939
956
  ctx.strokeStyle = task.planBorderColor ? task.planBorderColor : this.config.planBorderColor;
940
- pos.x_plan_start += width * offsetX;
941
- pos.x_plan_end && (pos.x_plan_end = pos.x_plan_start + width * percent_plan);
942
957
  ctx.lineWidth = 4;
943
958
  ctx.beginPath();
944
- ctx.moveTo(pos.x_plan_start + 2, taskY);
945
- ctx.lineTo(pos.x_plan_start + width * percent_plan - 2, taskY);
959
+ ctx.moveTo(pos.offset_x_plan_start + offset / 2, taskY);
960
+ ctx.lineTo(pos.offset_x_plan_end - offset / 2, taskY);
946
961
  ctx.stroke();
947
962
  }
948
963
  ctx.fillStyle = "#000";
949
964
  if (this.config.showLeftRemark && task.leftRemark) {
950
965
  ctx.textAlign = "right";
951
- 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));
966
+ ctx.fillText(task.leftRemark, Math.round(Math.min(...[pos.offset_x_plan_start, pos.offset_x_actual_start].filter((val) => val !== null && val !== void 0)) - 8), Math.round(textY));
952
967
  }
953
968
  if (this.config.showRightRemark && task.rightRemark) {
954
969
  ctx.textAlign = "left";
955
- 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));
970
+ ctx.fillText(task.rightRemark, Math.round(Math.max(...[pos.offset_x_plan_end, pos.offset_x_actual_end].filter((val) => val !== null && val !== void 0)) + 8), Math.round(textY));
956
971
  }
957
972
  if (this.config.showCenterRemark && task.centerRemark) {
958
- const centerX = pos.x_actual_start + (pos.x_actual_end - pos.x_actual_start) / 2;
973
+ const centerX = pos.offset_x_actual_start + (pos.offset_x_actual_end - pos.offset_x_actual_start) / 2;
959
974
  ctx.textAlign = "center";
960
- ctx.fillText(task.centerRemark, Math.round(centerX), Math.round(textY), Math.round(pos.x_actual_end - pos.x_actual_start));
975
+ ctx.fillText(task.centerRemark, Math.round(centerX), Math.round(textY), Math.round(pos.offset_x_actual_end - pos.offset_x_actual_start));
961
976
  }
962
977
  }
963
978
  getTaskStyles(task) {
package/dist/index.css CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * gantt-canvas-chart v1.3.0
2
+ * gantt-canvas-chart v1.3.1
3
3
  * (c) 2025-present chandq
4
4
  * Released under the MIT License.
5
5
  */
package/dist/index.d.ts CHANGED
@@ -187,6 +187,12 @@ export declare interface TaskPosition {
187
187
  x_plan_end: number;
188
188
  x_actual_start: number | null;
189
189
  x_actual_end: number | null;
190
+ x_plan_width: number;
191
+ x_actual_width: number;
192
+ offset_x_plan_start: number;
193
+ offset_x_plan_end: number;
194
+ offset_x_actual_start: number | null;
195
+ offset_x_actual_end: number | null;
190
196
  y: number;
191
197
  row: number;
192
198
  }
package/dist/index.es.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * gantt-canvas-chart v1.3.0
2
+ * gantt-canvas-chart v1.3.1
3
3
  * (c) 2025-present chandq
4
4
  * Released under the MIT License.
5
5
  */
@@ -194,6 +194,7 @@ class GanttChart {
194
194
  this.handleScroll = this.handleScroll.bind(this);
195
195
  this.horizontalScrollTo = this.horizontalScrollTo.bind(this);
196
196
  this.verticalScrollTo = this.verticalScrollTo.bind(this);
197
+ this.handleResize = this.handleResize.bind(this);
197
198
  this.init();
198
199
  }
199
200
  init() {
@@ -216,7 +217,6 @@ class GanttChart {
216
217
  }
217
218
  setupEvents() {
218
219
  this.container.addEventListener("scroll", this.handleScroll);
219
- this.handleResize = this.handleResize.bind(this);
220
220
  if (window.ResizeObserver) {
221
221
  this.resizeObserver = new ResizeObserver(this.handleResize);
222
222
  setTimeout(() => {
@@ -258,6 +258,9 @@ class GanttChart {
258
258
  this.container.removeEventListener("scroll", this.handleScroll);
259
259
  this.mainCanvas.removeEventListener("mousemove", this.handleMouseMove);
260
260
  this.mainCanvas.removeEventListener("mouseleave", this.handleMouseLeave);
261
+ this.data = [];
262
+ this.taskMap.clear();
263
+ this.taskPositions.clear();
261
264
  this.container.remove();
262
265
  }
263
266
  calculateFullTimeline() {
@@ -373,13 +376,10 @@ class GanttChart {
373
376
  try {
374
377
  if (this.hasMoreDataLeft && atLeftEdge && scrollLeft < this.lastScrollLeft) {
375
378
  await this.loadMoreData("left");
376
- console.log("left-loadMoreData::", this.data);
377
379
  } else if (this.hasMoreDataRight && atRightEdge && scrollLeft > this.lastScrollLeft) {
378
380
  await this.loadMoreData("right");
379
- console.log("right-loadMoreData::", this.data);
380
381
  } else if (this.hasMoreDataBottom && atBottomEdge && scrollTop > this.lastScrollTop) {
381
382
  await this.loadMoreData("bottom");
382
- console.log("bottom-loadMoreData::", this.data);
383
383
  }
384
384
  } finally {
385
385
  this.lastScrollLeft = scrollLeft;
@@ -508,17 +508,39 @@ class GanttChart {
508
508
  const x_plan_start = this.dateToX(new Date(task.planStart));
509
509
  const x_plan_end = this.dateToX(DateUtils.addDays(task.planEnd, 1));
510
510
  let x_actual_start = null, x_actual_end = null;
511
+ let offset_x_plan_start = NaN, offset_x_plan_end = NaN;
512
+ let offset_x_actual_start = null, offset_x_actual_end = null;
513
+ let x_plan_width = 0;
514
+ let x_actual_width = 0;
515
+ const [offsetX_actual, percent_actual] = this.config.viewMode === "Day" && task.actualOffsetPercent ? task.actualOffsetPercent : [0, 1];
516
+ const [offsetX, percent_plan] = this.config.viewMode === "Day" && task.planOffsetPercent ? task.planOffsetPercent : [0, 1];
517
+ if (x_plan_start && x_plan_end) {
518
+ x_plan_width = x_plan_end - x_plan_start;
519
+ offset_x_plan_start = x_plan_start + x_plan_width * offsetX;
520
+ x_plan_end && (offset_x_plan_end = offset_x_plan_start + x_plan_width * percent_plan);
521
+ }
511
522
  if (task.actualStart) {
512
523
  x_actual_start = this.dateToX(new Date(task.actualStart));
513
524
  }
514
525
  if (task.actualEnd) {
515
526
  x_actual_end = this.dateToX(DateUtils.addDays(task.actualEnd, 1));
516
527
  }
528
+ if (x_actual_start) {
529
+ x_actual_width = (x_actual_end ? x_actual_end : this.dateToX(this.today)) - x_actual_start;
530
+ offset_x_actual_start = Math.round(x_actual_start + x_actual_width * offsetX_actual);
531
+ x_actual_end && (offset_x_actual_end = offset_x_actual_start + x_actual_width * percent_actual);
532
+ }
517
533
  this.taskPositions.set(task.id, {
518
534
  x_plan_start,
519
535
  x_plan_end,
520
536
  x_actual_start,
521
537
  x_actual_end,
538
+ offset_x_plan_start,
539
+ offset_x_plan_end,
540
+ offset_x_actual_start,
541
+ offset_x_actual_end,
542
+ x_plan_width,
543
+ x_actual_width,
522
544
  y: y + this.config.rowHeight * 0.5,
523
545
  row: i
524
546
  });
@@ -763,9 +785,9 @@ class GanttChart {
763
785
  if (!fromPos) return;
764
786
  const fromRowIndex = this.taskMap.get(depId).row;
765
787
  const isAdjacent = Math.abs(toRowIndex - fromRowIndex) === 1;
766
- const fromX = Math.max(fromPos.x_plan_end, fromPos.x_actual_end || fromPos.x_plan_end);
788
+ const fromX = Math.max(fromPos.offset_x_plan_end, fromPos.offset_x_actual_end || fromPos.offset_x_plan_end);
767
789
  const fromY = fromPos.y;
768
- const toX = Math.min(toPos.x_plan_start, toPos.x_actual_start || toPos.x_plan_start);
790
+ const toX = Math.min(toPos.offset_x_plan_start, toPos.offset_x_actual_start || toPos.offset_x_plan_start);
769
791
  const toY = toPos.y;
770
792
  ctx.beginPath();
771
793
  if (isAdjacent) {
@@ -920,42 +942,35 @@ class GanttChart {
920
942
  }
921
943
  drawTask(ctx, task, y, pos) {
922
944
  const offset = 4;
923
- const width = pos.x_plan_end - pos.x_plan_start;
924
945
  const taskY = y + this.config.rowHeight * 0.15 + offset;
925
946
  const taskHeight = this.config.rowHeight * 0.7 - offset;
926
947
  const textY = y + this.config.rowHeight / 2 + offset;
927
948
  const [offsetX_actual, percent_actual] = this.config.viewMode === "Day" && task.actualOffsetPercent ? task.actualOffsetPercent : [0, 1];
928
- const [offsetX, percent_plan] = this.config.viewMode === "Day" && task.planOffsetPercent ? task.planOffsetPercent : [0, 1];
929
949
  if (this.config.showActual && pos.x_actual_start) {
930
950
  ctx.fillStyle = task.actualBgColor ? task.actualBgColor : this.config.actualBgColor;
931
- const aWidth = (pos.x_actual_end ? pos.x_actual_end : this.dateToX(this.today)) - pos.x_actual_start;
932
- pos.x_actual_start += aWidth * offsetX_actual;
933
- pos.x_actual_end && (pos.x_actual_end = pos.x_actual_start + aWidth * percent_actual);
934
- ctx.fillRect(Math.round(pos.x_actual_start), Math.round(taskY + 2), Math.round(aWidth * percent_actual), Math.round(taskHeight - 2));
951
+ ctx.fillRect(pos.offset_x_actual_start, Math.round(taskY + 2), Math.round(pos.x_actual_width * percent_actual), Math.round(taskHeight - 2));
935
952
  }
936
953
  if (this.config.showPlan && pos.x_plan_start && pos.x_plan_end) {
937
954
  ctx.strokeStyle = task.planBorderColor ? task.planBorderColor : this.config.planBorderColor;
938
- pos.x_plan_start += width * offsetX;
939
- pos.x_plan_end && (pos.x_plan_end = pos.x_plan_start + width * percent_plan);
940
955
  ctx.lineWidth = 4;
941
956
  ctx.beginPath();
942
- ctx.moveTo(pos.x_plan_start + 2, taskY);
943
- ctx.lineTo(pos.x_plan_start + width * percent_plan - 2, taskY);
957
+ ctx.moveTo(pos.offset_x_plan_start + offset / 2, taskY);
958
+ ctx.lineTo(pos.offset_x_plan_end - offset / 2, taskY);
944
959
  ctx.stroke();
945
960
  }
946
961
  ctx.fillStyle = "#000";
947
962
  if (this.config.showLeftRemark && task.leftRemark) {
948
963
  ctx.textAlign = "right";
949
- 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));
964
+ ctx.fillText(task.leftRemark, Math.round(Math.min(...[pos.offset_x_plan_start, pos.offset_x_actual_start].filter((val) => val !== null && val !== void 0)) - 8), Math.round(textY));
950
965
  }
951
966
  if (this.config.showRightRemark && task.rightRemark) {
952
967
  ctx.textAlign = "left";
953
- 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));
968
+ ctx.fillText(task.rightRemark, Math.round(Math.max(...[pos.offset_x_plan_end, pos.offset_x_actual_end].filter((val) => val !== null && val !== void 0)) + 8), Math.round(textY));
954
969
  }
955
970
  if (this.config.showCenterRemark && task.centerRemark) {
956
- const centerX = pos.x_actual_start + (pos.x_actual_end - pos.x_actual_start) / 2;
971
+ const centerX = pos.offset_x_actual_start + (pos.offset_x_actual_end - pos.offset_x_actual_start) / 2;
957
972
  ctx.textAlign = "center";
958
- ctx.fillText(task.centerRemark, Math.round(centerX), Math.round(textY), Math.round(pos.x_actual_end - pos.x_actual_start));
973
+ ctx.fillText(task.centerRemark, Math.round(centerX), Math.round(textY), Math.round(pos.offset_x_actual_end - pos.offset_x_actual_start));
959
974
  }
960
975
  }
961
976
  getTaskStyles(task) {
package/dist/index.umd.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * gantt-canvas-chart v1.3.0
2
+ * gantt-canvas-chart v1.3.1
3
3
  * (c) 2025-present chandq
4
4
  * Released under the MIT License.
5
5
  */
@@ -198,6 +198,7 @@
198
198
  this.handleScroll = this.handleScroll.bind(this);
199
199
  this.horizontalScrollTo = this.horizontalScrollTo.bind(this);
200
200
  this.verticalScrollTo = this.verticalScrollTo.bind(this);
201
+ this.handleResize = this.handleResize.bind(this);
201
202
  this.init();
202
203
  }
203
204
  init() {
@@ -220,7 +221,6 @@
220
221
  }
221
222
  setupEvents() {
222
223
  this.container.addEventListener("scroll", this.handleScroll);
223
- this.handleResize = this.handleResize.bind(this);
224
224
  if (window.ResizeObserver) {
225
225
  this.resizeObserver = new ResizeObserver(this.handleResize);
226
226
  setTimeout(() => {
@@ -262,6 +262,9 @@
262
262
  this.container.removeEventListener("scroll", this.handleScroll);
263
263
  this.mainCanvas.removeEventListener("mousemove", this.handleMouseMove);
264
264
  this.mainCanvas.removeEventListener("mouseleave", this.handleMouseLeave);
265
+ this.data = [];
266
+ this.taskMap.clear();
267
+ this.taskPositions.clear();
265
268
  this.container.remove();
266
269
  }
267
270
  calculateFullTimeline() {
@@ -377,13 +380,10 @@
377
380
  try {
378
381
  if (this.hasMoreDataLeft && atLeftEdge && scrollLeft < this.lastScrollLeft) {
379
382
  await this.loadMoreData("left");
380
- console.log("left-loadMoreData::", this.data);
381
383
  } else if (this.hasMoreDataRight && atRightEdge && scrollLeft > this.lastScrollLeft) {
382
384
  await this.loadMoreData("right");
383
- console.log("right-loadMoreData::", this.data);
384
385
  } else if (this.hasMoreDataBottom && atBottomEdge && scrollTop > this.lastScrollTop) {
385
386
  await this.loadMoreData("bottom");
386
- console.log("bottom-loadMoreData::", this.data);
387
387
  }
388
388
  } finally {
389
389
  this.lastScrollLeft = scrollLeft;
@@ -512,17 +512,39 @@
512
512
  const x_plan_start = this.dateToX(new Date(task.planStart));
513
513
  const x_plan_end = this.dateToX(DateUtils.addDays(task.planEnd, 1));
514
514
  let x_actual_start = null, x_actual_end = null;
515
+ let offset_x_plan_start = NaN, offset_x_plan_end = NaN;
516
+ let offset_x_actual_start = null, offset_x_actual_end = null;
517
+ let x_plan_width = 0;
518
+ let x_actual_width = 0;
519
+ const [offsetX_actual, percent_actual] = this.config.viewMode === "Day" && task.actualOffsetPercent ? task.actualOffsetPercent : [0, 1];
520
+ const [offsetX, percent_plan] = this.config.viewMode === "Day" && task.planOffsetPercent ? task.planOffsetPercent : [0, 1];
521
+ if (x_plan_start && x_plan_end) {
522
+ x_plan_width = x_plan_end - x_plan_start;
523
+ offset_x_plan_start = x_plan_start + x_plan_width * offsetX;
524
+ x_plan_end && (offset_x_plan_end = offset_x_plan_start + x_plan_width * percent_plan);
525
+ }
515
526
  if (task.actualStart) {
516
527
  x_actual_start = this.dateToX(new Date(task.actualStart));
517
528
  }
518
529
  if (task.actualEnd) {
519
530
  x_actual_end = this.dateToX(DateUtils.addDays(task.actualEnd, 1));
520
531
  }
532
+ if (x_actual_start) {
533
+ x_actual_width = (x_actual_end ? x_actual_end : this.dateToX(this.today)) - x_actual_start;
534
+ offset_x_actual_start = Math.round(x_actual_start + x_actual_width * offsetX_actual);
535
+ x_actual_end && (offset_x_actual_end = offset_x_actual_start + x_actual_width * percent_actual);
536
+ }
521
537
  this.taskPositions.set(task.id, {
522
538
  x_plan_start,
523
539
  x_plan_end,
524
540
  x_actual_start,
525
541
  x_actual_end,
542
+ offset_x_plan_start,
543
+ offset_x_plan_end,
544
+ offset_x_actual_start,
545
+ offset_x_actual_end,
546
+ x_plan_width,
547
+ x_actual_width,
526
548
  y: y + this.config.rowHeight * 0.5,
527
549
  row: i
528
550
  });
@@ -767,9 +789,9 @@
767
789
  if (!fromPos) return;
768
790
  const fromRowIndex = this.taskMap.get(depId).row;
769
791
  const isAdjacent = Math.abs(toRowIndex - fromRowIndex) === 1;
770
- const fromX = Math.max(fromPos.x_plan_end, fromPos.x_actual_end || fromPos.x_plan_end);
792
+ const fromX = Math.max(fromPos.offset_x_plan_end, fromPos.offset_x_actual_end || fromPos.offset_x_plan_end);
771
793
  const fromY = fromPos.y;
772
- const toX = Math.min(toPos.x_plan_start, toPos.x_actual_start || toPos.x_plan_start);
794
+ const toX = Math.min(toPos.offset_x_plan_start, toPos.offset_x_actual_start || toPos.offset_x_plan_start);
773
795
  const toY = toPos.y;
774
796
  ctx.beginPath();
775
797
  if (isAdjacent) {
@@ -924,42 +946,35 @@
924
946
  }
925
947
  drawTask(ctx, task, y, pos) {
926
948
  const offset = 4;
927
- const width = pos.x_plan_end - pos.x_plan_start;
928
949
  const taskY = y + this.config.rowHeight * 0.15 + offset;
929
950
  const taskHeight = this.config.rowHeight * 0.7 - offset;
930
951
  const textY = y + this.config.rowHeight / 2 + offset;
931
952
  const [offsetX_actual, percent_actual] = this.config.viewMode === "Day" && task.actualOffsetPercent ? task.actualOffsetPercent : [0, 1];
932
- const [offsetX, percent_plan] = this.config.viewMode === "Day" && task.planOffsetPercent ? task.planOffsetPercent : [0, 1];
933
953
  if (this.config.showActual && pos.x_actual_start) {
934
954
  ctx.fillStyle = task.actualBgColor ? task.actualBgColor : this.config.actualBgColor;
935
- const aWidth = (pos.x_actual_end ? pos.x_actual_end : this.dateToX(this.today)) - pos.x_actual_start;
936
- pos.x_actual_start += aWidth * offsetX_actual;
937
- pos.x_actual_end && (pos.x_actual_end = pos.x_actual_start + aWidth * percent_actual);
938
- ctx.fillRect(Math.round(pos.x_actual_start), Math.round(taskY + 2), Math.round(aWidth * percent_actual), Math.round(taskHeight - 2));
955
+ ctx.fillRect(pos.offset_x_actual_start, Math.round(taskY + 2), Math.round(pos.x_actual_width * percent_actual), Math.round(taskHeight - 2));
939
956
  }
940
957
  if (this.config.showPlan && pos.x_plan_start && pos.x_plan_end) {
941
958
  ctx.strokeStyle = task.planBorderColor ? task.planBorderColor : this.config.planBorderColor;
942
- pos.x_plan_start += width * offsetX;
943
- pos.x_plan_end && (pos.x_plan_end = pos.x_plan_start + width * percent_plan);
944
959
  ctx.lineWidth = 4;
945
960
  ctx.beginPath();
946
- ctx.moveTo(pos.x_plan_start + 2, taskY);
947
- ctx.lineTo(pos.x_plan_start + width * percent_plan - 2, taskY);
961
+ ctx.moveTo(pos.offset_x_plan_start + offset / 2, taskY);
962
+ ctx.lineTo(pos.offset_x_plan_end - offset / 2, taskY);
948
963
  ctx.stroke();
949
964
  }
950
965
  ctx.fillStyle = "#000";
951
966
  if (this.config.showLeftRemark && task.leftRemark) {
952
967
  ctx.textAlign = "right";
953
- 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));
968
+ ctx.fillText(task.leftRemark, Math.round(Math.min(...[pos.offset_x_plan_start, pos.offset_x_actual_start].filter((val) => val !== null && val !== void 0)) - 8), Math.round(textY));
954
969
  }
955
970
  if (this.config.showRightRemark && task.rightRemark) {
956
971
  ctx.textAlign = "left";
957
- 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));
972
+ ctx.fillText(task.rightRemark, Math.round(Math.max(...[pos.offset_x_plan_end, pos.offset_x_actual_end].filter((val) => val !== null && val !== void 0)) + 8), Math.round(textY));
958
973
  }
959
974
  if (this.config.showCenterRemark && task.centerRemark) {
960
- const centerX = pos.x_actual_start + (pos.x_actual_end - pos.x_actual_start) / 2;
975
+ const centerX = pos.offset_x_actual_start + (pos.offset_x_actual_end - pos.offset_x_actual_start) / 2;
961
976
  ctx.textAlign = "center";
962
- ctx.fillText(task.centerRemark, Math.round(centerX), Math.round(textY), Math.round(pos.x_actual_end - pos.x_actual_start));
977
+ ctx.fillText(task.centerRemark, Math.round(centerX), Math.round(textY), Math.round(pos.offset_x_actual_end - pos.offset_x_actual_start));
963
978
  }
964
979
  }
965
980
  getTaskStyles(task) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gantt-canvas-chart",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
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",