@orbcharts/plugins-basic 3.0.0-beta.19 → 3.0.0-beta.20

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.
Files changed (110) hide show
  1. package/LICENSE +200 -200
  2. package/dist/orbcharts-plugins-basic.es.js +60 -22
  3. package/dist/orbcharts-plugins-basic.umd.js +86 -66
  4. package/lib/core-types.ts +7 -7
  5. package/lib/core.ts +6 -6
  6. package/lib/plugins-basic-types.ts +6 -6
  7. package/package.json +44 -44
  8. package/src/base/BaseBars.ts +765 -765
  9. package/src/base/BaseBarsTriangle.ts +676 -676
  10. package/src/base/BaseDots.ts +464 -464
  11. package/src/base/BaseGroupAxis.ts +691 -691
  12. package/src/base/BaseLegend.ts +684 -684
  13. package/src/base/BaseLineAreas.ts +629 -629
  14. package/src/base/BaseLines.ts +706 -706
  15. package/src/base/BaseRacingBars.ts +551 -551
  16. package/src/base/BaseRacingLabels.ts +396 -396
  17. package/src/base/BaseRacingValueLabels.ts +403 -403
  18. package/src/base/BaseStackedBars.ts +782 -782
  19. package/src/base/BaseTooltip.ts +386 -386
  20. package/src/base/BaseValueAxis.ts +600 -600
  21. package/src/base/BaseXAxis.ts +427 -427
  22. package/src/base/BaseYAxis.ts +389 -389
  23. package/src/base/types.ts +2 -2
  24. package/src/const.ts +30 -30
  25. package/src/grid/defaults.ts +213 -213
  26. package/src/grid/gridObservables.ts +612 -612
  27. package/src/grid/index.ts +16 -16
  28. package/src/grid/plugins/Bars.ts +69 -69
  29. package/src/grid/plugins/BarsPN.ts +66 -66
  30. package/src/grid/plugins/BarsTriangle.ts +73 -73
  31. package/src/grid/plugins/Dots.ts +68 -68
  32. package/src/grid/plugins/GridLegend.ts +107 -107
  33. package/src/grid/plugins/GridTooltip.ts +66 -66
  34. package/src/grid/plugins/GroupAux.ts +1120 -1120
  35. package/src/grid/plugins/GroupAxis.ts +73 -73
  36. package/src/grid/plugins/GroupZoom.ts +218 -218
  37. package/src/grid/plugins/LineAreas.ts +65 -65
  38. package/src/grid/plugins/Lines.ts +59 -59
  39. package/src/grid/plugins/StackedBars.ts +64 -64
  40. package/src/grid/plugins/StackedValueAxis.ts +96 -96
  41. package/src/grid/plugins/ValueAxis.ts +94 -94
  42. package/src/index.ts +6 -6
  43. package/src/multiGrid/defaults.ts +244 -244
  44. package/src/multiGrid/index.ts +14 -14
  45. package/src/multiGrid/multiGridObservables.ts +50 -50
  46. package/src/multiGrid/plugins/MultiBars.ts +108 -108
  47. package/src/multiGrid/plugins/MultiBarsTriangle.ts +114 -114
  48. package/src/multiGrid/plugins/MultiDots.ts +102 -102
  49. package/src/multiGrid/plugins/MultiGridLegend.ts +169 -169
  50. package/src/multiGrid/plugins/MultiGridTooltip.ts +66 -66
  51. package/src/multiGrid/plugins/MultiGroupAxis.ts +137 -137
  52. package/src/multiGrid/plugins/MultiLineAreas.ts +107 -107
  53. package/src/multiGrid/plugins/MultiLines.ts +101 -101
  54. package/src/multiGrid/plugins/MultiStackedBars.ts +106 -106
  55. package/src/multiGrid/plugins/MultiStackedValueAxis.ts +134 -134
  56. package/src/multiGrid/plugins/MultiValueAxis.ts +134 -134
  57. package/src/multiGrid/plugins/OverlappingStackedValueAxes.ts +300 -300
  58. package/src/multiGrid/plugins/OverlappingValueAxes.ts +300 -300
  59. package/src/multiValue/defaults.ts +431 -391
  60. package/src/multiValue/index.ts +12 -12
  61. package/src/multiValue/multiValueObservables.ts +666 -666
  62. package/src/multiValue/plugins/MultiValueLegend.ts +107 -107
  63. package/src/multiValue/plugins/MultiValueTooltip.ts +66 -66
  64. package/src/multiValue/plugins/RacingBars.ts +373 -373
  65. package/src/multiValue/plugins/RacingCounterTexts.ts +300 -300
  66. package/src/multiValue/plugins/RacingValueAxis.ts +114 -114
  67. package/src/multiValue/plugins/RankingAxis_legacy.ts +109 -109
  68. package/src/multiValue/plugins/Scatter.ts +426 -426
  69. package/src/multiValue/plugins/ScatterBubbles.ts +554 -554
  70. package/src/multiValue/plugins/XAxis.ts +107 -107
  71. package/src/multiValue/plugins/XYAux.ts +682 -682
  72. package/src/multiValue/plugins/XYAxes.ts +194 -194
  73. package/src/multiValue/plugins/XYAxes_legacy.ts +683 -683
  74. package/src/multiValue/plugins/XZoom.ts +299 -299
  75. package/src/noneData/defaults.ts +102 -102
  76. package/src/noneData/index.ts +3 -3
  77. package/src/noneData/plugins/Container.ts +27 -27
  78. package/src/noneData/plugins/Tooltip.ts +373 -373
  79. package/src/relationship/defaults.ts +221 -221
  80. package/src/relationship/index.ts +5 -5
  81. package/src/relationship/plugins/ForceDirected.ts +1173 -1173
  82. package/src/relationship/plugins/ForceDirectedBubbles.ts +1411 -1411
  83. package/src/relationship/plugins/RelationshipLegend.ts +100 -100
  84. package/src/relationship/plugins/RelationshipTooltip.ts +66 -66
  85. package/src/relationship/relationshipObservables.ts +49 -49
  86. package/src/series/defaults.ts +221 -221
  87. package/src/series/index.ts +9 -9
  88. package/src/series/plugins/Bubbles.ts +636 -636
  89. package/src/series/plugins/Pie.ts +623 -623
  90. package/src/series/plugins/PieEventTexts.ts +284 -284
  91. package/src/series/plugins/PieLabels.ts +640 -640
  92. package/src/series/plugins/Rose.ts +516 -516
  93. package/src/series/plugins/RoseLabels.ts +600 -600
  94. package/src/series/plugins/SeriesLegend.ts +107 -107
  95. package/src/series/plugins/SeriesTooltip.ts +66 -66
  96. package/src/series/seriesObservables.ts +145 -145
  97. package/src/series/seriesUtils.ts +51 -51
  98. package/src/tree/defaults.ts +102 -102
  99. package/src/tree/index.ts +4 -4
  100. package/src/tree/plugins/TreeLegend.ts +100 -100
  101. package/src/tree/plugins/TreeMap.ts +341 -341
  102. package/src/tree/plugins/TreeTooltip.ts +66 -66
  103. package/src/utils/commonUtils.ts +31 -31
  104. package/src/utils/d3Graphics.ts +176 -176
  105. package/src/utils/d3Utils.ts +92 -92
  106. package/src/utils/observables.ts +14 -14
  107. package/src/utils/orbchartsUtils.ts +129 -129
  108. package/tsconfig.base.json +13 -13
  109. package/tsconfig.json +2 -2
  110. package/vite.config.js +22 -22
@@ -1,300 +1,300 @@
1
- import * as d3 from 'd3'
2
- import {
3
- Observable,
4
- combineLatest,
5
- switchMap,
6
- distinctUntilChanged,
7
- first,
8
- map,
9
- takeUntil,
10
- debounceTime,
11
- Subject } from 'rxjs'
12
- import type { DefinePluginConfig } from '../../../lib/core-types'
13
- import type { DataFormatterMultiValue } from '../../../lib/core-types'
14
- import {
15
- defineMultiValuePlugin, createValueToAxisScale } from '../../../lib/core'
16
- import { DEFAULT_X_ZOOM_PARAMS } from '../defaults'
17
- import { getClassName, getUniID } from '../../utils/orbchartsUtils'
18
- import { LAYER_INDEX_OF_ROOT } from '../../const'
19
-
20
- const pluginName = 'XZoom'
21
- const rectClassName = getClassName(pluginName, 'rect')
22
-
23
- const pluginConfig: DefinePluginConfig<typeof pluginName, typeof DEFAULT_X_ZOOM_PARAMS> = {
24
- name: pluginName,
25
- defaultParams: DEFAULT_X_ZOOM_PARAMS,
26
- layerIndex: LAYER_INDEX_OF_ROOT,
27
- validator: (params, { validateColumns }) => {
28
- return {
29
- status: 'success',
30
- columnName: '',
31
- expectToBe: ''
32
- }
33
- }
34
- }
35
-
36
- export const XZoom = defineMultiValuePlugin(pluginConfig)(({ selection, rootSelection, name, observer, subject }) => {
37
-
38
- const destroy$ = new Subject()
39
-
40
- // const rootRectSelection: d3.Selection<SVGRectElement, any, any, any> = rootSelection
41
- // .append('rect')
42
- // .classed(rectClassName, true)
43
- // .attr('opacity', 0)
44
-
45
- // 紀錄zoom最後一次的transform
46
- let lastTransform = {
47
- k: 1,
48
- x: 0,
49
- y: 0
50
- }
51
- // let lastDomain: [number, number] = [0, 0]
52
-
53
- // observer.layout$.pipe(
54
- // takeUntil(destroy$),
55
- // ).subscribe(d => {
56
- // rootRectSelection
57
- // .attr('width', d.width)
58
- // .attr('height', d.height)
59
- // .attr('x', d.left)
60
- // .attr('y', d.top)
61
- // })
62
-
63
- // const groupMax$ = observer.computedData$.pipe(
64
- // map(d => d[0] ? d[0].length - 1 : 0),
65
- // distinctUntilChanged()
66
- // )
67
-
68
- // const fullDataFormatterEvent$: Subject<DataFormatterMultiValue> = new Subject()
69
- // fullDataFormatterEvent$
70
- // .pipe(
71
- // takeUntil(destroy$),
72
- // debounceTime(50)
73
- // )
74
- // .subscribe(fullDataFormatter => {
75
- // store.fullDataFormatter$.next(fullDataFormatter)
76
- // })
77
-
78
- const initXAxis$ = observer.fullDataFormatter$.pipe(
79
- map(d => d.xAxis),
80
- // 只用第一次資料來計算scale才不會造成每次變動都受到影響
81
- first()
82
- )
83
-
84
- const initYAxis$ = observer.fullDataFormatter$.pipe(
85
- map(d => d.yAxis),
86
- // 只用第一次資料來計算scale才不會造成每次變動都受到影響
87
- first()
88
- )
89
-
90
-
91
- // const groupScale$ = combineLatest({
92
- // initXAxis: initXAxis$,
93
- // fullDataFormatter: observer.fullDataFormatter$,
94
- // groupMax: groupMax$,
95
- // layout: observer.layout$,
96
- // // axisSize: observer.gridAxesSize$
97
- // }).pipe(
98
- // takeUntil(destroy$),
99
- // switchMap(async (d) => d),
100
- // map(data => {
101
- // // const groupMin = 0
102
- // const groupScaleDomainMin = data.initXAxis.scaleDomain[0] - data.initXAxis.scalePadding
103
- // const groupScaleDomainMax = data.initXAxis.scaleDomain[1] === 'max'
104
- // ? data.groupMax + data.initXAxis.scalePadding
105
- // : data.initXAxis.scaleDomain[1] as number + data.initXAxis.scalePadding
106
-
107
- // const groupScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
108
- // maxValue: data.groupMax,
109
- // minValue: 0,
110
- // axisWidth: data.layout.width,
111
- // scaleDomain: [groupScaleDomainMin, groupScaleDomainMax],
112
- // scaleRange: [0, 1]
113
- // })
114
-
115
- // return groupScale
116
- // })
117
- // )
118
- const initXScale$: Observable<d3.ScaleLinear<number, number>> = new Observable(subscriber => {
119
- combineLatest({
120
- initXAxis: initXAxis$,
121
- layout: observer.layout$,
122
- xyMinMax: observer.xyMinMax$
123
- }).pipe(
124
- takeUntil(destroy$),
125
- switchMap(async (d) => d),
126
- ).subscribe(data => {
127
-
128
- const xScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
129
- maxValue: data.xyMinMax.maxX,
130
- minValue: data.xyMinMax.minX,
131
- axisWidth: data.layout.width,
132
- scaleDomain: data.initXAxis.scaleDomain,
133
- scaleRange: data.initXAxis.scaleRange,
134
- })
135
-
136
- subscriber.next(xScale)
137
- })
138
- })
139
-
140
- const initYScale$: Observable<d3.ScaleLinear<number, number>> = new Observable(subscriber => {
141
- combineLatest({
142
- initYAxis: initYAxis$,
143
- layout: observer.layout$,
144
- xyMinMax: observer.xyMinMax$
145
- }).pipe(
146
- takeUntil(destroy$),
147
- switchMap(async (d) => d),
148
- ).subscribe(data => {
149
-
150
- const yScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
151
- maxValue: data.xyMinMax.maxY,
152
- minValue: data.xyMinMax.minY,
153
- axisWidth: data.layout.height,
154
- scaleDomain: data.initYAxis.scaleDomain,
155
- scaleRange: data.initYAxis.scaleRange,
156
- reverse: true
157
- })
158
-
159
- subscriber.next(yScale)
160
- })
161
- })
162
-
163
- const minMaxScaleDomain$ = combineLatest({
164
- initXAxis: initXAxis$,
165
- initYAxis: initYAxis$,
166
- xyMinMax: observer.xyMinMax$
167
- }).pipe(
168
- takeUntil(destroy$),
169
- switchMap(async (d) => d),
170
- map(data => {
171
- let minX = data.xyMinMax.minX
172
- let maxX = data.xyMinMax.maxX
173
- let minY = data.xyMinMax.minY
174
- let maxY = data.xyMinMax.maxY
175
-
176
- // 原始設定為auto時要額外判斷
177
- if (data.initXAxis.scaleDomain[0] === 'auto' && minX > 0) {
178
- minX = 0
179
- }
180
- if (data.initXAxis.scaleDomain[1] === 'auto' && maxX < 0) {
181
- maxX = 0
182
- }
183
- if (data.initYAxis.scaleDomain[0] === 'auto' && minY > 0) {
184
- minY = 0
185
- }
186
- if (data.initYAxis.scaleDomain[1] === 'auto' && maxY < 0) {
187
- maxY = 0
188
- }
189
-
190
- return {
191
- minX,
192
- maxX,
193
- minY,
194
- maxY
195
- }
196
- }),
197
- )
198
-
199
- combineLatest({
200
- initXScale: initXScale$,
201
- // initXAxis: initXAxis$,
202
- // fullDataFormatter: fullDataFormatter$.pipe(first()), // 只用第一次資料來計算scale才不會造成每次變動都受到影響
203
- fullDataFormatter: observer.fullDataFormatter$,
204
- // groupMax: groupMax$,
205
- // xyMinMax: observer.xyMinMax$,
206
- minMaxScaleDomain: minMaxScaleDomain$,
207
- // layout: observer.layout$,
208
- // axisSize: observer.gridAxesSize$
209
- }).pipe(
210
- takeUntil(destroy$),
211
- switchMap(async (d) => d),
212
- ).subscribe(data => {
213
- // const groupMin = 0
214
-
215
- const shadowScale = data.initXScale.copy()
216
-
217
- const zoom = d3.zoom()
218
- // .scaleExtent([1, data.groupMaxIndex])
219
- // .translateExtent([[0, 0], [data.layout.rootWidth, data.layout.rootWidth]])
220
- .on("zoom", function zoomed(event) {
221
- // debugger
222
- // console.log('event', event)
223
- const t = event.transform;
224
-
225
- // if (event.sourceEvent.type === 'mousemove') {
226
- // // 當進行平移時,反向計算 x 軸
227
- // const dx = event.transform.x - currentTransform.x; // 本次平移增量
228
- // const reversedX = currentTransform.x - dx; // 反向累積平移
229
- // // 更新變換狀態
230
- // currentTransform = d3.zoomIdentity
231
- // .translate(reversedX, event.transform.y)
232
- // .scale(event.transform.k);
233
- // } else {
234
- // // 縮放操作:只更新縮放比例
235
- // currentTransform = d3.zoomIdentity
236
- // .translate(currentTransform.x, currentTransform.y)
237
- // .scale(event.transform.k);
238
- // }
239
- // console.log('currentTransform', currentTransform)
240
-
241
- // console.log('t.x', t.x)
242
- const mapGroupindex = (d: number) => {
243
- const n = Math.round(d)
244
- return Math.min(data.minMaxScaleDomain.maxX, Math.max(data.minMaxScaleDomain.minX, n));
245
- }
246
-
247
- const zoomedDomain = t.rescaleX(shadowScale)
248
- .domain()
249
- .map(mapGroupindex)
250
-
251
-
252
- // domain超過極限值
253
- if (zoomedDomain[0] <= data.minMaxScaleDomain.minX && zoomedDomain[1] >= data.minMaxScaleDomain.maxX) {
254
- // 繼續縮小
255
- if (t.k < lastTransform.k) {
256
- // 維持前一次的transform
257
- t.k = lastTransform.k
258
- t.x = lastTransform.x
259
- t.y = lastTransform.y
260
- }
261
- // domain間距小於1
262
- } else if ((zoomedDomain[1] - zoomedDomain[0]) <= 1) {
263
- // 繼續放大
264
- if (t.k > lastTransform.k) {
265
- // 維持前一次的transform
266
- t.k = lastTransform.k
267
- t.x = lastTransform.x
268
- t.y = lastTransform.y
269
- }
270
- }
271
-
272
- // 紀錄transform
273
- lastTransform.k = t.k
274
- lastTransform.x = t.x
275
- lastTransform.y = t.y
276
-
277
- // console.log(zoomedDomain)
278
- const newDataFormatter: DataFormatterMultiValue = {
279
- ...data.fullDataFormatter,
280
- xAxis: {
281
- ...data.fullDataFormatter.xAxis,
282
- scaleDomain: zoomedDomain
283
- }
284
- }
285
- subject.dataFormatter$.next(newDataFormatter)
286
- })
287
-
288
- // 傳入外層selection
289
- // subject.selection.call(zoom as any)
290
- rootSelection.call(zoom)
291
-
292
- })
293
-
294
- return () => {
295
- destroy$.next(undefined)
296
- // rootRectSelection.remove()
297
-
298
- rootSelection.call(d3.zoom().on('zoom', null))
299
- }
1
+ import * as d3 from 'd3'
2
+ import {
3
+ Observable,
4
+ combineLatest,
5
+ switchMap,
6
+ distinctUntilChanged,
7
+ first,
8
+ map,
9
+ takeUntil,
10
+ debounceTime,
11
+ Subject } from 'rxjs'
12
+ import type { DefinePluginConfig } from '../../../lib/core-types'
13
+ import type { DataFormatterMultiValue } from '../../../lib/core-types'
14
+ import {
15
+ defineMultiValuePlugin, createValueToAxisScale } from '../../../lib/core'
16
+ import { DEFAULT_X_ZOOM_PARAMS } from '../defaults'
17
+ import { getClassName, getUniID } from '../../utils/orbchartsUtils'
18
+ import { LAYER_INDEX_OF_ROOT } from '../../const'
19
+
20
+ const pluginName = 'XZoom'
21
+ const rectClassName = getClassName(pluginName, 'rect')
22
+
23
+ const pluginConfig: DefinePluginConfig<typeof pluginName, typeof DEFAULT_X_ZOOM_PARAMS> = {
24
+ name: pluginName,
25
+ defaultParams: DEFAULT_X_ZOOM_PARAMS,
26
+ layerIndex: LAYER_INDEX_OF_ROOT,
27
+ validator: (params, { validateColumns }) => {
28
+ return {
29
+ status: 'success',
30
+ columnName: '',
31
+ expectToBe: ''
32
+ }
33
+ }
34
+ }
35
+
36
+ export const XZoom = defineMultiValuePlugin(pluginConfig)(({ selection, rootSelection, name, observer, subject }) => {
37
+
38
+ const destroy$ = new Subject()
39
+
40
+ // const rootRectSelection: d3.Selection<SVGRectElement, any, any, any> = rootSelection
41
+ // .append('rect')
42
+ // .classed(rectClassName, true)
43
+ // .attr('opacity', 0)
44
+
45
+ // 紀錄zoom最後一次的transform
46
+ let lastTransform = {
47
+ k: 1,
48
+ x: 0,
49
+ y: 0
50
+ }
51
+ // let lastDomain: [number, number] = [0, 0]
52
+
53
+ // observer.layout$.pipe(
54
+ // takeUntil(destroy$),
55
+ // ).subscribe(d => {
56
+ // rootRectSelection
57
+ // .attr('width', d.width)
58
+ // .attr('height', d.height)
59
+ // .attr('x', d.left)
60
+ // .attr('y', d.top)
61
+ // })
62
+
63
+ // const groupMax$ = observer.computedData$.pipe(
64
+ // map(d => d[0] ? d[0].length - 1 : 0),
65
+ // distinctUntilChanged()
66
+ // )
67
+
68
+ // const fullDataFormatterEvent$: Subject<DataFormatterMultiValue> = new Subject()
69
+ // fullDataFormatterEvent$
70
+ // .pipe(
71
+ // takeUntil(destroy$),
72
+ // debounceTime(50)
73
+ // )
74
+ // .subscribe(fullDataFormatter => {
75
+ // store.fullDataFormatter$.next(fullDataFormatter)
76
+ // })
77
+
78
+ const initXAxis$ = observer.fullDataFormatter$.pipe(
79
+ map(d => d.xAxis),
80
+ // 只用第一次資料來計算scale才不會造成每次變動都受到影響
81
+ first()
82
+ )
83
+
84
+ const initYAxis$ = observer.fullDataFormatter$.pipe(
85
+ map(d => d.yAxis),
86
+ // 只用第一次資料來計算scale才不會造成每次變動都受到影響
87
+ first()
88
+ )
89
+
90
+
91
+ // const groupScale$ = combineLatest({
92
+ // initXAxis: initXAxis$,
93
+ // fullDataFormatter: observer.fullDataFormatter$,
94
+ // groupMax: groupMax$,
95
+ // layout: observer.layout$,
96
+ // // axisSize: observer.gridAxesSize$
97
+ // }).pipe(
98
+ // takeUntil(destroy$),
99
+ // switchMap(async (d) => d),
100
+ // map(data => {
101
+ // // const groupMin = 0
102
+ // const groupScaleDomainMin = data.initXAxis.scaleDomain[0] - data.initXAxis.scalePadding
103
+ // const groupScaleDomainMax = data.initXAxis.scaleDomain[1] === 'max'
104
+ // ? data.groupMax + data.initXAxis.scalePadding
105
+ // : data.initXAxis.scaleDomain[1] as number + data.initXAxis.scalePadding
106
+
107
+ // const groupScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
108
+ // maxValue: data.groupMax,
109
+ // minValue: 0,
110
+ // axisWidth: data.layout.width,
111
+ // scaleDomain: [groupScaleDomainMin, groupScaleDomainMax],
112
+ // scaleRange: [0, 1]
113
+ // })
114
+
115
+ // return groupScale
116
+ // })
117
+ // )
118
+ const initXScale$: Observable<d3.ScaleLinear<number, number>> = new Observable(subscriber => {
119
+ combineLatest({
120
+ initXAxis: initXAxis$,
121
+ layout: observer.layout$,
122
+ xyMinMax: observer.xyMinMax$
123
+ }).pipe(
124
+ takeUntil(destroy$),
125
+ switchMap(async (d) => d),
126
+ ).subscribe(data => {
127
+
128
+ const xScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
129
+ maxValue: data.xyMinMax.maxX,
130
+ minValue: data.xyMinMax.minX,
131
+ axisWidth: data.layout.width,
132
+ scaleDomain: data.initXAxis.scaleDomain,
133
+ scaleRange: data.initXAxis.scaleRange,
134
+ })
135
+
136
+ subscriber.next(xScale)
137
+ })
138
+ })
139
+
140
+ const initYScale$: Observable<d3.ScaleLinear<number, number>> = new Observable(subscriber => {
141
+ combineLatest({
142
+ initYAxis: initYAxis$,
143
+ layout: observer.layout$,
144
+ xyMinMax: observer.xyMinMax$
145
+ }).pipe(
146
+ takeUntil(destroy$),
147
+ switchMap(async (d) => d),
148
+ ).subscribe(data => {
149
+
150
+ const yScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
151
+ maxValue: data.xyMinMax.maxY,
152
+ minValue: data.xyMinMax.minY,
153
+ axisWidth: data.layout.height,
154
+ scaleDomain: data.initYAxis.scaleDomain,
155
+ scaleRange: data.initYAxis.scaleRange,
156
+ reverse: true
157
+ })
158
+
159
+ subscriber.next(yScale)
160
+ })
161
+ })
162
+
163
+ const minMaxScaleDomain$ = combineLatest({
164
+ initXAxis: initXAxis$,
165
+ initYAxis: initYAxis$,
166
+ xyMinMax: observer.xyMinMax$
167
+ }).pipe(
168
+ takeUntil(destroy$),
169
+ switchMap(async (d) => d),
170
+ map(data => {
171
+ let minX = data.xyMinMax.minX
172
+ let maxX = data.xyMinMax.maxX
173
+ let minY = data.xyMinMax.minY
174
+ let maxY = data.xyMinMax.maxY
175
+
176
+ // 原始設定為auto時要額外判斷
177
+ if (data.initXAxis.scaleDomain[0] === 'auto' && minX > 0) {
178
+ minX = 0
179
+ }
180
+ if (data.initXAxis.scaleDomain[1] === 'auto' && maxX < 0) {
181
+ maxX = 0
182
+ }
183
+ if (data.initYAxis.scaleDomain[0] === 'auto' && minY > 0) {
184
+ minY = 0
185
+ }
186
+ if (data.initYAxis.scaleDomain[1] === 'auto' && maxY < 0) {
187
+ maxY = 0
188
+ }
189
+
190
+ return {
191
+ minX,
192
+ maxX,
193
+ minY,
194
+ maxY
195
+ }
196
+ }),
197
+ )
198
+
199
+ combineLatest({
200
+ initXScale: initXScale$,
201
+ // initXAxis: initXAxis$,
202
+ // fullDataFormatter: fullDataFormatter$.pipe(first()), // 只用第一次資料來計算scale才不會造成每次變動都受到影響
203
+ fullDataFormatter: observer.fullDataFormatter$,
204
+ // groupMax: groupMax$,
205
+ // xyMinMax: observer.xyMinMax$,
206
+ minMaxScaleDomain: minMaxScaleDomain$,
207
+ // layout: observer.layout$,
208
+ // axisSize: observer.gridAxesSize$
209
+ }).pipe(
210
+ takeUntil(destroy$),
211
+ switchMap(async (d) => d),
212
+ ).subscribe(data => {
213
+ // const groupMin = 0
214
+
215
+ const shadowScale = data.initXScale.copy()
216
+
217
+ const zoom = d3.zoom()
218
+ // .scaleExtent([1, data.groupMaxIndex])
219
+ // .translateExtent([[0, 0], [data.layout.rootWidth, data.layout.rootWidth]])
220
+ .on("zoom", function zoomed(event) {
221
+ // debugger
222
+ // console.log('event', event)
223
+ const t = event.transform;
224
+
225
+ // if (event.sourceEvent.type === 'mousemove') {
226
+ // // 當進行平移時,反向計算 x 軸
227
+ // const dx = event.transform.x - currentTransform.x; // 本次平移增量
228
+ // const reversedX = currentTransform.x - dx; // 反向累積平移
229
+ // // 更新變換狀態
230
+ // currentTransform = d3.zoomIdentity
231
+ // .translate(reversedX, event.transform.y)
232
+ // .scale(event.transform.k);
233
+ // } else {
234
+ // // 縮放操作:只更新縮放比例
235
+ // currentTransform = d3.zoomIdentity
236
+ // .translate(currentTransform.x, currentTransform.y)
237
+ // .scale(event.transform.k);
238
+ // }
239
+ // console.log('currentTransform', currentTransform)
240
+
241
+ // console.log('t.x', t.x)
242
+ const mapGroupindex = (d: number) => {
243
+ const n = Math.round(d)
244
+ return Math.min(data.minMaxScaleDomain.maxX, Math.max(data.minMaxScaleDomain.minX, n));
245
+ }
246
+
247
+ const zoomedDomain = t.rescaleX(shadowScale)
248
+ .domain()
249
+ .map(mapGroupindex)
250
+
251
+
252
+ // domain超過極限值
253
+ if (zoomedDomain[0] <= data.minMaxScaleDomain.minX && zoomedDomain[1] >= data.minMaxScaleDomain.maxX) {
254
+ // 繼續縮小
255
+ if (t.k < lastTransform.k) {
256
+ // 維持前一次的transform
257
+ t.k = lastTransform.k
258
+ t.x = lastTransform.x
259
+ t.y = lastTransform.y
260
+ }
261
+ // domain間距小於1
262
+ } else if ((zoomedDomain[1] - zoomedDomain[0]) <= 1) {
263
+ // 繼續放大
264
+ if (t.k > lastTransform.k) {
265
+ // 維持前一次的transform
266
+ t.k = lastTransform.k
267
+ t.x = lastTransform.x
268
+ t.y = lastTransform.y
269
+ }
270
+ }
271
+
272
+ // 紀錄transform
273
+ lastTransform.k = t.k
274
+ lastTransform.x = t.x
275
+ lastTransform.y = t.y
276
+
277
+ // console.log(zoomedDomain)
278
+ const newDataFormatter: DataFormatterMultiValue = {
279
+ ...data.fullDataFormatter,
280
+ xAxis: {
281
+ ...data.fullDataFormatter.xAxis,
282
+ scaleDomain: zoomedDomain
283
+ }
284
+ }
285
+ subject.dataFormatter$.next(newDataFormatter)
286
+ })
287
+
288
+ // 傳入外層selection
289
+ // subject.selection.call(zoom as any)
290
+ rootSelection.call(zoom)
291
+
292
+ })
293
+
294
+ return () => {
295
+ destroy$.next(undefined)
296
+ // rootRectSelection.remove()
297
+
298
+ rootSelection.call(d3.zoom().on('zoom', null))
299
+ }
300
300
  })