@orbcharts/core 3.0.0-beta.3 → 3.0.0-beta.5
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/orbcharts-core.es.js +2665 -2376
- package/dist/orbcharts-core.umd.js +4 -4
- package/dist/src/utils/d3Scale.d.ts +28 -0
- package/dist/src/utils/gridObservables.d.ts +29 -19
- package/dist/src/utils/index.d.ts +1 -1
- package/dist/src/utils/multiGridObservables.d.ts +2 -2
- package/dist/src/utils/multiValueObservables.d.ts +73 -0
- package/dist/src/utils/orbchartsUtils.d.ts +19 -5
- package/dist/src/utils/seriesObservables.d.ts +4 -4
- package/dist/src/utils/treeObservables.d.ts +2 -5
- package/package.json +2 -2
- package/src/defaults.ts +4 -1
- package/src/grid/contextObserverCallback.ts +57 -36
- package/src/multiValue/computedDataFn.ts +81 -147
- package/src/multiValue/contextObserverCallback.ts +150 -2
- package/src/relationship/computedDataFn.ts +1 -1
- package/src/tree/computedDataFn.ts +9 -10
- package/src/tree/contextObserverCallback.ts +6 -9
- package/src/utils/d3Scale.ts +198 -0
- package/src/utils/gridObservables.ts +303 -234
- package/src/utils/index.ts +1 -1
- package/src/utils/multiGridObservables.ts +68 -42
- package/src/utils/multiValueObservables.ts +662 -0
- package/src/utils/orbchartsUtils.ts +70 -45
- package/src/utils/seriesObservables.ts +7 -7
- package/src/utils/treeObservables.ts +44 -33
- package/src/utils/validator.ts +3 -2
- package/dist/src/utils/d3Utils.d.ts +0 -19
- package/src/utils/d3Utils.ts +0 -108
@@ -13,11 +13,12 @@ import type {
|
|
13
13
|
DataMultiValue,
|
14
14
|
DataMultiValueDatum,
|
15
15
|
DataMultiValueValue,
|
16
|
+
ComputedLayoutDatumMultiValue,
|
16
17
|
DataFormatterContainer,
|
17
18
|
SeriesDirection,
|
18
19
|
DataFormatterGridGrid,
|
19
|
-
|
20
|
-
|
20
|
+
ContainerPosition,
|
21
|
+
ContainerPositionScaled,
|
21
22
|
Layout
|
22
23
|
} from '../../lib/core-types'
|
23
24
|
import { isPlainObject } from './commonUtils'
|
@@ -29,8 +30,11 @@ export function formatValueToLabel (value: any, valueFormatter: string | ((text:
|
|
29
30
|
return d3.format(valueFormatter as string)!(value)
|
30
31
|
}
|
31
32
|
|
32
|
-
export function createDefaultDatumId (chartTypeOrPrefix: string, levelOneIndex: number, levelTwoIndex
|
33
|
-
let text = `${chartTypeOrPrefix}_${levelOneIndex}
|
33
|
+
export function createDefaultDatumId (chartTypeOrPrefix: string, levelOneIndex: number, levelTwoIndex?: number, levelThreeIndex?: number) {
|
34
|
+
let text = `${chartTypeOrPrefix}_${levelOneIndex}`
|
35
|
+
if (levelTwoIndex != null) {
|
36
|
+
text += `_${levelTwoIndex}`
|
37
|
+
}
|
34
38
|
if (levelThreeIndex != null) {
|
35
39
|
text += `_${levelThreeIndex}`
|
36
40
|
}
|
@@ -45,6 +49,11 @@ export function createDefaultGroupLabel (chartTypeOrPrefix: string, groupIndex:
|
|
45
49
|
return `${chartTypeOrPrefix}_group${groupIndex}`
|
46
50
|
}
|
47
51
|
|
52
|
+
export function createDefaultCategoryLabel () {
|
53
|
+
// return `${chartTypeOrPrefix}_category`
|
54
|
+
return '' // 空值
|
55
|
+
}
|
56
|
+
|
48
57
|
export function createGridSeriesLabels ({ transposedDataGrid, dataFormatterGrid, chartType = 'grid' }: {
|
49
58
|
transposedDataGrid: DataGridDatum[][],
|
50
59
|
dataFormatterGrid: DataFormatterGridGrid
|
@@ -167,14 +176,63 @@ export function getMinAndMaxMultiGrid (data: DataMultiGrid): [number, number] {
|
|
167
176
|
}
|
168
177
|
|
169
178
|
// 取得最小及最大值 - MultiValue Data
|
170
|
-
export function getMinAndMaxMultiValue (data: DataMultiValue, valueIndex: number
|
171
|
-
const
|
172
|
-
|
173
|
-
|
174
|
-
|
179
|
+
export function getMinAndMaxMultiValue (data: DataMultiValue, valueIndex: number): [number, number] {
|
180
|
+
const arr: number[] = data
|
181
|
+
.map(d => {
|
182
|
+
if (Array.isArray(d)) {
|
183
|
+
return d[valueIndex] ?? null
|
184
|
+
} else if (isPlainObject(d)) {
|
185
|
+
return (d as DataMultiValueDatum).value[valueIndex] ?? null
|
186
|
+
} else {
|
187
|
+
return null
|
188
|
+
}
|
189
|
+
})
|
190
|
+
.filter(d => d != null)
|
175
191
|
return getMinAndMax(arr)
|
176
192
|
}
|
177
193
|
|
194
|
+
export function getMinAndMaxMultiValueXY ({ data, minX, maxX, minY, maxY }: {
|
195
|
+
data: ComputedLayoutDatumMultiValue[][]
|
196
|
+
minX: number
|
197
|
+
maxX: number
|
198
|
+
minY: number
|
199
|
+
maxY: number
|
200
|
+
}) {
|
201
|
+
let filteredData: ComputedLayoutDatumMultiValue[][] = []
|
202
|
+
let minXDatum: ComputedLayoutDatumMultiValue | null = null
|
203
|
+
let maxXDatum: ComputedLayoutDatumMultiValue | null = null
|
204
|
+
let minYDatum: ComputedLayoutDatumMultiValue | null = null
|
205
|
+
let maxYDatum: ComputedLayoutDatumMultiValue | null = null
|
206
|
+
|
207
|
+
for (let categoryData of data) {
|
208
|
+
for (let datum of categoryData) {
|
209
|
+
if (datum.axisX >= minX && datum.axisX <= maxX && datum.axisY >= minY && datum.axisY <= maxY) {
|
210
|
+
filteredData.push(categoryData)
|
211
|
+
if (minXDatum == null || datum.axisX < minXDatum.axisX) {
|
212
|
+
minXDatum = datum
|
213
|
+
}
|
214
|
+
if (maxXDatum == null || datum.axisX > maxXDatum.axisX) {
|
215
|
+
maxXDatum = datum
|
216
|
+
}
|
217
|
+
if (minYDatum == null || datum.axisY < minYDatum.axisY) {
|
218
|
+
minYDatum = datum
|
219
|
+
}
|
220
|
+
if (maxYDatum == null || datum.axisY > maxYDatum.axisY) {
|
221
|
+
maxYDatum = datum
|
222
|
+
}
|
223
|
+
}
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
227
|
+
return {
|
228
|
+
minXDatum,
|
229
|
+
maxXDatum,
|
230
|
+
minYDatum,
|
231
|
+
maxYDatum,
|
232
|
+
filteredData
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
178
236
|
// @Q@ 待處理
|
179
237
|
// // 取得最小及最大值 - Relationship Data
|
180
238
|
// export function getMinAndMaxRelationship (data: DataRelationship, target: 'nodes' | 'edges' = 'nodes'): [number, number] {
|
@@ -220,24 +278,6 @@ export function seriesColorPredicate (seriesIndex: number, chartParams: ChartPar
|
|
220
278
|
]
|
221
279
|
}
|
222
280
|
|
223
|
-
// export function calcSeriesContainerPosition (layout: Layout, container: DataFormatterContainer, rowIndex: number, columnIndex: number) {
|
224
|
-
// const { gap, rowAmount, columnAmount } = container
|
225
|
-
// const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
|
226
|
-
// const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
|
227
|
-
// const x = columnIndex * width + (columnIndex * gap)
|
228
|
-
// const y = rowIndex * height + (rowIndex * gap)
|
229
|
-
// // const translate: [number, number] = [x, y]
|
230
|
-
|
231
|
-
// return {
|
232
|
-
// // translate,
|
233
|
-
// startX: x,
|
234
|
-
// startY: y,
|
235
|
-
// centerX: x + width / 2,
|
236
|
-
// centerY: y + height / 2,
|
237
|
-
// width,
|
238
|
-
// height
|
239
|
-
// }
|
240
|
-
// }
|
241
281
|
|
242
282
|
// 計算預設欄列數量
|
243
283
|
// 規則1.rowAmount*columnAmount要大於或等於amount,並且數字要盡可能小
|
@@ -251,7 +291,7 @@ function calcGridDimensions (amount: number): { rowAmount: number; columnAmount:
|
|
251
291
|
return { rowAmount, columnAmount }
|
252
292
|
}
|
253
293
|
|
254
|
-
export function calcSeriesContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number):
|
294
|
+
export function calcSeriesContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): ContainerPosition[] {
|
255
295
|
const { gap } = container
|
256
296
|
const { rowAmount, columnAmount } = (container.rowAmount * container.columnAmount) >= amount
|
257
297
|
// 如果container設定的rowAmount和columnAmount的乘積大於或等於amount,則使用目前設定
|
@@ -284,22 +324,7 @@ export function calcSeriesContainerLayout (layout: Layout, container: DataFormat
|
|
284
324
|
})
|
285
325
|
}
|
286
326
|
|
287
|
-
|
288
|
-
// const { gap, rowAmount, columnAmount } = container
|
289
|
-
// const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
|
290
|
-
// const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
|
291
|
-
// const x = columnIndex * width + (columnIndex * gap)
|
292
|
-
// const y = rowIndex * height + (rowIndex * gap)
|
293
|
-
// const translate: [number, number] = [x, y]
|
294
|
-
// const scale: [number, number] = [width / layout.width, height / layout.height]
|
295
|
-
|
296
|
-
// return {
|
297
|
-
// translate,
|
298
|
-
// scale
|
299
|
-
// }
|
300
|
-
// }
|
301
|
-
|
302
|
-
export function calcGridContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): GridContainerPosition[] {
|
327
|
+
export function calcGridContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): ContainerPositionScaled[] {
|
303
328
|
const { gap } = container
|
304
329
|
const { rowAmount, columnAmount } = (container.rowAmount * container.columnAmount) >= amount
|
305
330
|
// 如果container設定的rowAmount和columnAmount的乘積大於或等於amount,則使用目前設定
|
@@ -318,7 +343,7 @@ export function calcGridContainerLayout (layout: Layout, container: DataFormatte
|
|
318
343
|
const translate: [number, number] = [x, y]
|
319
344
|
const scale: [number, number] = [width / layout.width, height / layout.height]
|
320
345
|
|
321
|
-
return {
|
346
|
+
return {
|
322
347
|
slotIndex: index,
|
323
348
|
rowIndex,
|
324
349
|
columnIndex,
|
@@ -14,7 +14,7 @@ import type {
|
|
14
14
|
ComputedDatumSeries,
|
15
15
|
ComputedDataTypeMap,
|
16
16
|
DataFormatterTypeMap,
|
17
|
-
|
17
|
+
ContainerPosition,
|
18
18
|
Layout } from '../../lib/core-types'
|
19
19
|
import { calcSeriesContainerLayout } from './orbchartsUtils'
|
20
20
|
|
@@ -97,7 +97,7 @@ export const seriesContainerPositionObservable = ({ computedData$, fullDataForma
|
|
97
97
|
computedData$: Observable<ComputedDataTypeMap<'series'>>
|
98
98
|
fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>>
|
99
99
|
layout$: Observable<Layout>
|
100
|
-
}): Observable<
|
100
|
+
}): Observable<ContainerPosition[]> => {
|
101
101
|
|
102
102
|
const gridContainerPosition$ = combineLatest({
|
103
103
|
computedData: computedData$,
|
@@ -113,7 +113,7 @@ export const seriesContainerPositionObservable = ({ computedData$, fullDataForma
|
|
113
113
|
// return data.computedData.map((seriesData, seriesIndex) => {
|
114
114
|
// const columnIndex = seriesIndex % data.fullDataFormatter.container.columnAmount
|
115
115
|
// const rowIndex = Math.floor(seriesIndex / data.fullDataFormatter.container.columnAmount)
|
116
|
-
// const { startX, startY, centerX, centerY, width, height } =
|
116
|
+
// const { startX, startY, centerX, centerY, width, height } = calcContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
117
117
|
// return {
|
118
118
|
// slotIndex: seriesIndex,
|
119
119
|
// rowIndex,
|
@@ -132,7 +132,7 @@ export const seriesContainerPositionObservable = ({ computedData$, fullDataForma
|
|
132
132
|
// const columnIndex = 0
|
133
133
|
// const rowIndex = 0
|
134
134
|
// return data.computedData.map((seriesData, seriesIndex) => {
|
135
|
-
// const { startX, startY, centerX, centerY, width, height } =
|
135
|
+
// const { startX, startY, centerX, centerY, width, height } = calcContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
136
136
|
// return {
|
137
137
|
// slotIndex: 0,
|
138
138
|
// rowIndex,
|
@@ -153,7 +153,7 @@ export const seriesContainerPositionObservable = ({ computedData$, fullDataForma
|
|
153
153
|
}
|
154
154
|
|
155
155
|
export const seriesContainerPositionMapObservable = ({ seriesContainerPosition$, seriesLabels$, separateSeries$ }: {
|
156
|
-
seriesContainerPosition$: Observable<
|
156
|
+
seriesContainerPosition$: Observable<ContainerPosition[]>
|
157
157
|
seriesLabels$: Observable<string[]>
|
158
158
|
separateSeries$: Observable<boolean>
|
159
159
|
}) => {
|
@@ -165,10 +165,10 @@ export const seriesContainerPositionMapObservable = ({ seriesContainerPosition$,
|
|
165
165
|
switchMap(async (d) => d),
|
166
166
|
map(data => {
|
167
167
|
return data.separateSeries
|
168
|
-
? new Map<string,
|
168
|
+
? new Map<string, ContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
|
169
169
|
return [seriesLabel, data.seriesContainerPosition[seriesIndex] ?? data.seriesContainerPosition[0]]
|
170
170
|
}))
|
171
|
-
: new Map<string,
|
171
|
+
: new Map<string, ContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
|
172
172
|
return [seriesLabel, data.seriesContainerPosition[0]]
|
173
173
|
}))
|
174
174
|
})
|
@@ -34,42 +34,53 @@ export const nodeListObservable = ({ computedData$ }: { computedData$: Observabl
|
|
34
34
|
)
|
35
35
|
}
|
36
36
|
|
37
|
-
export const
|
38
|
-
|
39
|
-
|
40
|
-
}) => {
|
37
|
+
// export const categoryLabelsObservable = ({ nodeList$, fullDataFormatter$ }: {
|
38
|
+
// nodeList$: Observable<ComputedDataTree[]>
|
39
|
+
// fullDataFormatter$: Observable<DataFormatterTree>
|
40
|
+
// }) => {
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
// const categoryLabels$ = fullDataFormatter$.pipe(
|
43
|
+
// map(d => d.categoryLabels),
|
44
|
+
// distinctUntilChanged((a, b) => {
|
45
|
+
// return JSON.stringify(a).length === JSON.stringify(b).length
|
46
|
+
// }),
|
47
|
+
// )
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
49
|
+
// return combineLatest({
|
50
|
+
// nodeList: nodeList$,
|
51
|
+
// categoryLabels: categoryLabels$
|
52
|
+
// }).pipe(
|
53
|
+
// switchMap(async d => d),
|
54
|
+
// map(data => {
|
55
|
+
// const CurrentLabelSet = new Set(data.categoryLabels)
|
56
|
+
// const ExistLabelSet = new Set(
|
57
|
+
// data.nodeList.filter(node => node.visible).map(node => node.categoryLabel)
|
58
|
+
// )
|
59
|
+
// // 加入已存在的label(data.nodeList有,但是dataFormatter.categoryLabels沒有)
|
60
|
+
// Array.from(ExistLabelSet).forEach(label => {
|
61
|
+
// if (!CurrentLabelSet.has(label)) {
|
62
|
+
// CurrentLabelSet.add(label)
|
63
|
+
// }
|
64
|
+
// })
|
65
|
+
// // 移除不存在的label(dataFormatter.categoryLabels有,但是data.nodeList沒有)
|
66
|
+
// Array.from(CurrentLabelSet).forEach(label => {
|
67
|
+
// if (!ExistLabelSet.has(label)) {
|
68
|
+
// ExistLabelSet.delete(label)
|
69
|
+
// }
|
70
|
+
// })
|
71
71
|
|
72
|
-
|
72
|
+
// return Array.from(CurrentLabelSet)
|
73
|
+
// }),
|
74
|
+
// distinctUntilChanged((a, b) => {
|
75
|
+
// return JSON.stringify(a).length === JSON.stringify(b).length
|
76
|
+
// }),
|
77
|
+
// )
|
78
|
+
// }
|
79
|
+
|
80
|
+
export const categoryLabelsObservable = (CategoryDataMap$: Observable<Map<string, ComputedDataTree[]>>) => {
|
81
|
+
return CategoryDataMap$.pipe(
|
82
|
+
map(data => {
|
83
|
+
return Array.from(data.keys())
|
73
84
|
}),
|
74
85
|
distinctUntilChanged((a, b) => {
|
75
86
|
return JSON.stringify(a).length === JSON.stringify(b).length
|
package/src/utils/validator.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import type {
|
2
|
+
ColorType,
|
2
3
|
ValidatorResult,
|
3
4
|
ToBeTypes,
|
4
5
|
ToBeOption,
|
@@ -40,14 +41,14 @@ function getInvalidColumn<T> (data: T, rules: Partial<ValidatorRule<T>>) {
|
|
40
41
|
}
|
41
42
|
// "toBeOption" 的測試
|
42
43
|
const testOption: {[key in ToBeOption]: (value: any) => boolean} = {
|
43
|
-
ColorType: (value:
|
44
|
+
ColorType: (value: ColorType) => {
|
44
45
|
return value === 'none'
|
45
46
|
|| value === 'series'
|
46
47
|
|| value === 'primary'
|
47
48
|
|| value === 'secondary'
|
48
49
|
|| value === 'white'
|
49
50
|
|| value === 'background'
|
50
|
-
}
|
51
|
+
},
|
51
52
|
}
|
52
53
|
|
53
54
|
const failColumn = Object.keys(data).find((columnName: string) => {
|
@@ -1,19 +0,0 @@
|
|
1
|
-
import * as d3 from 'd3';
|
2
|
-
export declare const createAxisLinearScale: ({ maxValue, minValue, axisWidth, scaleDomain, scaleRange, }: {
|
3
|
-
maxValue: number;
|
4
|
-
minValue: number;
|
5
|
-
axisWidth: number;
|
6
|
-
scaleDomain: [number | "min" | "auto", number | "max" | "auto"];
|
7
|
-
scaleRange: [number, number];
|
8
|
-
}) => d3.ScaleLinear<number, number, never>;
|
9
|
-
export declare const createAxisPointScale: ({ axisLabels, axisWidth, padding }: {
|
10
|
-
axisLabels: string[];
|
11
|
-
axisWidth: number;
|
12
|
-
padding?: number;
|
13
|
-
}) => d3.ScalePoint<string>;
|
14
|
-
export declare const createAxisQuantizeScale: ({ axisLabels, axisWidth, padding, reverse }: {
|
15
|
-
axisLabels: string[] | Date[];
|
16
|
-
axisWidth: number;
|
17
|
-
padding?: number;
|
18
|
-
reverse?: boolean;
|
19
|
-
}) => d3.ScaleQuantize<number, never>;
|
package/src/utils/d3Utils.ts
DELETED
@@ -1,108 +0,0 @@
|
|
1
|
-
import * as d3 from 'd3'
|
2
|
-
import { DATA_FORMATTER_VALUE_AXIS_DEFAULT } from '../defaults'
|
3
|
-
|
4
|
-
// scaleLinear - 連續資料對應到比例尺座標上
|
5
|
-
export const createAxisLinearScale = ({
|
6
|
-
maxValue = 1,
|
7
|
-
minValue = 0,
|
8
|
-
axisWidth,
|
9
|
-
scaleDomain = DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleDomain,
|
10
|
-
scaleRange = DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleRange,
|
11
|
-
}: {
|
12
|
-
maxValue: number
|
13
|
-
minValue: number
|
14
|
-
axisWidth: number
|
15
|
-
scaleDomain: [number | 'min' | 'auto', number | 'max' | 'auto']
|
16
|
-
scaleRange: [number, number] // 0-1
|
17
|
-
}) => {
|
18
|
-
// -- 無值補上預設值 --
|
19
|
-
const domainMin: number | 'min' | 'auto' = scaleDomain[0] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleDomain[0]
|
20
|
-
const domainMax: number | 'max' | 'auto' = scaleDomain[1] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleDomain[1]
|
21
|
-
const rangeMin: number = scaleRange[0] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleRange[0]
|
22
|
-
const rangeMax: number = scaleRange[1] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleRange[1]
|
23
|
-
|
24
|
-
// -- 'auto' | 'max' | 'min' 替換成實際值 --
|
25
|
-
let domainMinValue: number = (() => {
|
26
|
-
if (domainMin === 'auto') {
|
27
|
-
return minValue < 0 ? minValue : 0
|
28
|
-
} else if (domainMin === 'min') {
|
29
|
-
return minValue
|
30
|
-
} else {
|
31
|
-
return domainMin
|
32
|
-
}
|
33
|
-
})()
|
34
|
-
|
35
|
-
let domainMaxValue: number = (() => {
|
36
|
-
if (domainMax === 'auto') {
|
37
|
-
return maxValue >= 0 ? maxValue : 0
|
38
|
-
} else if (domainMax === 'max') {
|
39
|
-
return maxValue
|
40
|
-
} else {
|
41
|
-
return domainMax
|
42
|
-
}
|
43
|
-
})()
|
44
|
-
// let rangeMinValue = axisWidth * rangeMin
|
45
|
-
// let rangeMaxValue = axisWidth * rangeMax
|
46
|
-
|
47
|
-
// -- 計算padding --
|
48
|
-
// if (padding > 0) {
|
49
|
-
// const stepAmount = maxValue - minValue + (padding * 2)
|
50
|
-
// const eachStepWidth = axisWidth / stepAmount
|
51
|
-
// const paddingWidth = eachStepWidth * padding
|
52
|
-
// rangeMinValue += paddingWidth
|
53
|
-
// rangeMaxValue -= paddingWidth
|
54
|
-
// }
|
55
|
-
|
56
|
-
// -- 依場景大小換算 --
|
57
|
-
const axisDomainMinValue = maxValue - (maxValue - domainMinValue) / (1 - rangeMin)
|
58
|
-
const axisDomainMaxValue = domainMaxValue / rangeMax
|
59
|
-
|
60
|
-
// return d3.scaleLinear()
|
61
|
-
// .domain([domainMinValue, domainMaxValue])
|
62
|
-
// .range([rangeMinValue, rangeMaxValue])
|
63
|
-
return d3.scaleLinear()
|
64
|
-
.domain([axisDomainMinValue, axisDomainMaxValue])
|
65
|
-
.range([0, axisWidth])
|
66
|
-
}
|
67
|
-
|
68
|
-
// scalePoint - 非連續資料對應到比例尺座標上
|
69
|
-
export const createAxisPointScale = ({ axisLabels, axisWidth, padding = 0.5 }: {
|
70
|
-
axisLabels: string[]
|
71
|
-
axisWidth: number
|
72
|
-
padding?: number
|
73
|
-
// reverse?: boolean
|
74
|
-
}) => {
|
75
|
-
let range: [d3.NumberValue, d3.NumberValue] = [0, axisWidth]
|
76
|
-
|
77
|
-
return d3.scalePoint()
|
78
|
-
.domain(axisLabels)
|
79
|
-
.range(range)
|
80
|
-
.padding(padding)
|
81
|
-
}
|
82
|
-
|
83
|
-
// scaleQuantize - 比例尺座標對應非連續資料索引
|
84
|
-
export const createAxisQuantizeScale = ({ axisLabels, axisWidth, padding = 0, reverse = false }:{
|
85
|
-
axisLabels: string[] | Date[],
|
86
|
-
axisWidth: number
|
87
|
-
padding?: number
|
88
|
-
reverse?: boolean
|
89
|
-
}) => {
|
90
|
-
|
91
|
-
let range: number[] = axisLabels.map((d: string | Date, i: number) => i)
|
92
|
-
if (reverse) {
|
93
|
-
range.reverse()
|
94
|
-
}
|
95
|
-
// if (reverse) {
|
96
|
-
// range = axisLabels.map((d: string | Date, i: number) => axisLabels.length - 1 - i)
|
97
|
-
// } else {
|
98
|
-
// range = axisLabels.map((d: string | Date, i: number) => i)
|
99
|
-
// }
|
100
|
-
const step = range.length - 1 + (padding * 2) // 圖軸刻度分段數量
|
101
|
-
const stepWidth = axisWidth / step
|
102
|
-
const rangePadding = stepWidth * padding - (stepWidth * 0.5) // 實際要計算的範圍是圖軸左右那邊增加0.5
|
103
|
-
|
104
|
-
// console.log('rangePadding', rangePadding)
|
105
|
-
return d3.scaleQuantize<number>()
|
106
|
-
.domain([rangePadding, axisWidth - rangePadding])
|
107
|
-
.range(range)
|
108
|
-
}
|