@@ -54,7 +54,6 @@ import {
5454} from './gantt-helper' ;
5555import { EventTarget } from './event/EventTarget' ;
5656import {
57- computeCountToTimeScale ,
5857 createDateAtLastHour ,
5958 createDateAtLastMillisecond ,
6059 createDateAtLastMinute ,
@@ -220,6 +219,10 @@ export class Gantt extends EventTarget {
220219 // 时间缩放基准 - 每像素代表多少毫秒
221220 private millisecondsPerPixel : number ;
222221 zoomScaleManager ?: ZoomScaleManager ;
222+ private _timelineColWidths : number [ ] = [ ] ;
223+ private _timelineColX : number [ ] = [ ] ;
224+ private _timelineColStartTimes : number [ ] = [ ] ;
225+ private _timelineColEndTimes : number [ ] = [ ] ;
223226
224227 /**
225228 * 重新计算时间相关的尺寸参数
@@ -749,6 +752,156 @@ export class Gantt extends EventTarget {
749752 ) ;
750753 }
751754 }
755+ this . _rebuildTimelineColXMap ( ) ;
756+ }
757+
758+ private _rebuildTimelineColXMap ( ) {
759+ const minScale = this . parsedOptions . reverseSortedTimelineScales ?. [ 0 ] ;
760+ const timelineDates = minScale ?. timelineDates ?? [ ] ;
761+ const baseWidth = this . parsedOptions . timelineColWidth ?? 0 ;
762+
763+ const hideWeekend = this . options ?. timelineHeader ?. hideWeekend === true ;
764+ const weekendColWidth = this . options ?. timelineHeader ?. weekendColWidth ;
765+ const enableWeekendWidth =
766+ minScale ?. unit === 'day' && minScale ?. step === 1 && ( hideWeekend || weekendColWidth !== undefined ) ;
767+
768+ this . _timelineColWidths = new Array ( timelineDates . length ) ;
769+ this . _timelineColX = new Array ( timelineDates . length + 1 ) ;
770+ this . _timelineColStartTimes = new Array ( timelineDates . length ) ;
771+ this . _timelineColEndTimes = new Array ( timelineDates . length ) ;
772+ this . _timelineColX [ 0 ] = 0 ;
773+
774+ let sumX = 0 ;
775+ for ( let i = 0 ; i < timelineDates . length ; i ++ ) {
776+ const d = timelineDates [ i ] ;
777+ const startTime = d . startDate ?. getTime ?.( ) ?? 0 ;
778+ const endTime = d . endDate ?. getTime ?.( ) ?? startTime ;
779+ this . _timelineColStartTimes [ i ] = startTime ;
780+ this . _timelineColEndTimes [ i ] = endTime ;
781+
782+ let w = baseWidth ;
783+ if ( enableWeekendWidth ) {
784+ const day = d . startDate . getDay ( ) ;
785+ const isWeekend = day === 0 || day === 6 ;
786+ if ( isWeekend ) {
787+ if ( hideWeekend ) {
788+ w = 0 ;
789+ } else if ( typeof weekendColWidth === 'number' ) {
790+ w = weekendColWidth ;
791+ } else if ( typeof weekendColWidth === 'function' ) {
792+ w = weekendColWidth ( baseWidth ) ;
793+ }
794+ }
795+ }
796+
797+ w = Math . max ( 0 , Number . isFinite ( w ) ? w : baseWidth ) ;
798+ this . _timelineColWidths [ i ] = w ;
799+ sumX += w ;
800+ this . _timelineColX [ i + 1 ] = sumX ;
801+ }
802+ }
803+
804+ getXByTime ( time : number ) {
805+ const startTimes = this . _timelineColStartTimes ;
806+ const endTimes = this . _timelineColEndTimes ;
807+ const widths = this . _timelineColWidths ;
808+ const xPrefix = this . _timelineColX ;
809+ if ( ! startTimes ?. length || ! endTimes ?. length || ! widths ?. length || ! xPrefix ?. length ) {
810+ return 0 ;
811+ }
812+ if ( time <= startTimes [ 0 ] ) {
813+ return 0 ;
814+ }
815+ const lastIndex = endTimes . length - 1 ;
816+ if ( time > endTimes [ lastIndex ] ) {
817+ return xPrefix [ lastIndex + 1 ] ?? 0 ;
818+ }
819+
820+ let low = 0 ;
821+ let high = lastIndex ;
822+ while ( low <= high ) {
823+ const mid = ( low + high ) >> 1 ;
824+ const st = startTimes [ mid ] ;
825+ const et = endTimes [ mid ] ;
826+ if ( time < st ) {
827+ high = mid - 1 ;
828+ } else if ( time > et ) {
829+ low = mid + 1 ;
830+ } else {
831+ const duration = Math . max ( 1 , et - st + 1 ) ;
832+ const offset = ( time - st ) / duration ;
833+ return ( xPrefix [ mid ] ?? 0 ) + ( widths [ mid ] ?? 0 ) * offset ;
834+ }
835+ }
836+
837+ const idx = Math . max ( 0 , Math . min ( lastIndex , high ) ) ;
838+ const st = startTimes [ idx ] ;
839+ const et = endTimes [ idx ] ;
840+ const duration = Math . max ( 1 , et - st + 1 ) ;
841+ const offset = Math . max ( 0 , Math . min ( 1 , ( time - st ) / duration ) ) ;
842+ return ( xPrefix [ idx ] ?? 0 ) + ( widths [ idx ] ?? 0 ) * offset ;
843+ }
844+
845+ getDateIndexByTime ( time : number ) {
846+ const startTimes = this . _timelineColStartTimes ;
847+ const endTimes = this . _timelineColEndTimes ;
848+ if ( ! startTimes ?. length || ! endTimes ?. length ) {
849+ return 0 ;
850+ }
851+ if ( time <= startTimes [ 0 ] ) {
852+ return 0 ;
853+ }
854+ const lastIndex = endTimes . length - 1 ;
855+ if ( time > endTimes [ lastIndex ] ) {
856+ return lastIndex ;
857+ }
858+ let low = 0 ;
859+ let high = lastIndex ;
860+ while ( low <= high ) {
861+ const mid = ( low + high ) >> 1 ;
862+ const st = startTimes [ mid ] ;
863+ const et = endTimes [ mid ] ;
864+ if ( time < st ) {
865+ high = mid - 1 ;
866+ } else if ( time > et ) {
867+ low = mid + 1 ;
868+ } else {
869+ return mid ;
870+ }
871+ }
872+ return Math . max ( 0 , Math . min ( lastIndex , high ) ) ;
873+ }
874+
875+ getDateIndexByX ( x : number ) {
876+ const totalX = x + this . stateManager . scroll . horizontalBarPos ;
877+ const xPrefix = this . _timelineColX ;
878+ if ( ! xPrefix ?. length ) {
879+ return 0 ;
880+ }
881+ if ( totalX <= 0 ) {
882+ return 0 ;
883+ }
884+ const lastIndex = xPrefix . length - 2 ;
885+ const totalWidth = xPrefix [ lastIndex + 1 ] ?? 0 ;
886+ if ( totalX >= totalWidth ) {
887+ return Math . max ( 0 , lastIndex ) ;
888+ }
889+
890+ let low = 0 ;
891+ let high = lastIndex ;
892+ while ( low <= high ) {
893+ const mid = ( low + high ) >> 1 ;
894+ const left = xPrefix [ mid ] ?? 0 ;
895+ const right = xPrefix [ mid + 1 ] ?? left ;
896+ if ( totalX < left ) {
897+ high = mid - 1 ;
898+ } else if ( totalX >= right ) {
899+ low = mid + 1 ;
900+ } else {
901+ return mid ;
902+ }
903+ }
904+ return Math . max ( 0 , Math . min ( lastIndex , low ) ) ;
752905 }
753906 getRowHeightByIndex ( index : number ) {
754907 if ( this . taskListTableInstance ) {
@@ -783,6 +936,10 @@ export class Gantt extends EventTarget {
783936 // return (this.parsedOptions.timeLineHeaderRowHeights as number) * this.timeLineHeaderLevel;
784937 }
785938 getAllDateColsWidth ( ) {
939+ const xPrefix = this . _timelineColX ;
940+ if ( xPrefix ?. length ) {
941+ return xPrefix [ xPrefix . length - 1 ] ?? 0 ;
942+ }
786943 return (
787944 this . parsedOptions . timelineColWidth *
788945 ( this . parsedOptions . reverseSortedTimelineScales [ 0 ] . timelineDates ?. length ?? 0 )
@@ -1389,10 +1546,7 @@ export class Gantt extends EventTarget {
13891546 /** 滚动到scrollToMarkLineDate所指向的日期 */
13901547 _scrollToMarkLine ( ) {
13911548 if ( this . parsedOptions . scrollToMarkLineDate && this . parsedOptions . minDate ) {
1392- const minDate = this . parsedOptions . minDate ;
1393- const { unit, step } = this . parsedOptions . reverseSortedTimelineScales [ 0 ] ;
1394- const count = computeCountToTimeScale ( this . parsedOptions . scrollToMarkLineDate , minDate , unit , step ) ;
1395- const targetDayDistance = count * this . parsedOptions . timelineColWidth ;
1549+ const targetDayDistance = this . getXByTime ( this . parsedOptions . scrollToMarkLineDate . getTime ( ) ) ;
13961550 const left = targetDayDistance - this . tableNoFrameWidth / 2 ;
13971551 this . stateManager . setScrollLeft ( left ) ;
13981552 }
@@ -1402,10 +1556,7 @@ export class Gantt extends EventTarget {
14021556 if ( ! date || ! this . parsedOptions . minDate ) {
14031557 return ;
14041558 }
1405- const minDate = this . parsedOptions . minDate ;
1406- const { unit, step } = this . parsedOptions . reverseSortedTimelineScales [ 0 ] ;
1407- const count = computeCountToTimeScale ( date , minDate , unit , step ) ;
1408- const targetDayDistance = count * this . parsedOptions . timelineColWidth ;
1559+ const targetDayDistance = this . getXByTime ( date . getTime ( ) ) ;
14091560 const left = targetDayDistance - this . tableNoFrameWidth / 2 ;
14101561 this . stateManager . setScrollLeft ( left ) ;
14111562 }
@@ -1487,9 +1638,22 @@ export class Gantt extends EventTarget {
14871638 // }
14881639
14891640 getDateColWidth ( dateIndex : number ) {
1641+ const widths = this . _timelineColWidths ;
1642+ if ( widths ?. length && dateIndex >= 0 && dateIndex < widths . length ) {
1643+ return widths [ dateIndex ] ?? 0 ;
1644+ }
14901645 return this . parsedOptions . timelineColWidth ;
14911646 }
14921647 getDateColsWidth ( startDateIndex : number , endDateIndex : number ) {
1648+ const xPrefix = this . _timelineColX ;
1649+ if ( xPrefix ?. length ) {
1650+ const start = Math . max ( 0 , Math . min ( startDateIndex , xPrefix . length - 1 ) ) ;
1651+ const end = Math . max ( 0 , Math . min ( endDateIndex + 1 , xPrefix . length - 1 ) ) ;
1652+ if ( end <= start ) {
1653+ return 0 ;
1654+ }
1655+ return ( xPrefix [ end ] ?? 0 ) - ( xPrefix [ start ] ?? 0 ) ;
1656+ }
14931657 return ( endDateIndex - startDateIndex + 1 ) * this . parsedOptions . timelineColWidth ;
14941658 }
14951659
0 commit comments