@orbcharts/plugin-basic 4.0.0-pre-alpha.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/LICENSE +201 -0
- package/dist/orbcharts-plugin-basic.es.js +25335 -0
- package/dist/orbcharts-plugin-basic.umd.js +341 -0
- package/dist/plugin-basic/src/baseLayers/BaseBars.d.ts +38 -0
- package/dist/plugin-basic/src/baseLayers/BaseBarsTriangle.d.ts +37 -0
- package/dist/plugin-basic/src/baseLayers/BaseCategoryAxis.d.ts +42 -0
- package/dist/plugin-basic/src/baseLayers/BaseDots.d.ts +38 -0
- package/dist/plugin-basic/src/baseLayers/BaseLegend.d.ts +31 -0
- package/dist/plugin-basic/src/baseLayers/BaseLineAreas.d.ts +36 -0
- package/dist/plugin-basic/src/baseLayers/BaseLines.d.ts +36 -0
- package/dist/plugin-basic/src/baseLayers/BaseStackedBars.d.ts +41 -0
- package/dist/plugin-basic/src/baseLayers/BaseTooltip.d.ts +47 -0
- package/dist/plugin-basic/src/baseLayers/BaseValueAxis.d.ts +38 -0
- package/dist/plugin-basic/src/baseLayers/BaseXAxis.d.ts +25 -0
- package/dist/plugin-basic/src/baseLayers/BaseXZoom.d.ts +22 -0
- package/dist/plugin-basic/src/baseLayers/BaseYAxis.d.ts +23 -0
- package/dist/plugin-basic/src/baseLayers/types.d.ts +171 -0
- package/dist/plugin-basic/src/const/layerIndex.d.ts +10 -0
- package/dist/plugin-basic/src/const/sharedPluginParams.d.ts +6 -0
- package/dist/plugin-basic/src/index.d.ts +2 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/CompositionPlot.d.ts +22 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/contextObservables.d.ts +40 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/defaults.d.ts +10 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/index.d.ts +3 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/layers/Bubbles.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/layers/Indicator.d.ts +0 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/layers/Pie.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/layers/PieEventTexts.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/layers/PieLabels.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/layers/Rose.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/layers/RoseLabels.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/layers/Waffle.d.ts +0 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/types.d.ts +110 -0
- package/dist/plugin-basic/src/plugins/CompositionPlot/utils.d.ts +19 -0
- package/dist/plugin-basic/src/plugins/HierarchyPlot/HierarchyPlot.d.ts +22 -0
- package/dist/plugin-basic/src/plugins/HierarchyPlot/contextObservables.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/HierarchyPlot/defaults.d.ts +4 -0
- package/dist/plugin-basic/src/plugins/HierarchyPlot/index.d.ts +3 -0
- package/dist/plugin-basic/src/plugins/HierarchyPlot/layers/TreeMap.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/HierarchyPlot/types.d.ts +29 -0
- package/dist/plugin-basic/src/plugins/Legend/Legend.d.ts +22 -0
- package/dist/plugin-basic/src/plugins/Legend/contextObservables.d.ts +9 -0
- package/dist/plugin-basic/src/plugins/Legend/defaults.d.ts +4 -0
- package/dist/plugin-basic/src/plugins/Legend/index.d.ts +3 -0
- package/dist/plugin-basic/src/plugins/Legend/layers/Legend.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/Legend/types.d.ts +31 -0
- package/dist/plugin-basic/src/plugins/Legend/utils.d.ts +19 -0
- package/dist/plugin-basic/src/plugins/NetworkPlot/NetworkPlot.d.ts +22 -0
- package/dist/plugin-basic/src/plugins/NetworkPlot/contextObservables.d.ts +19 -0
- package/dist/plugin-basic/src/plugins/NetworkPlot/defaults.d.ts +5 -0
- package/dist/plugin-basic/src/plugins/NetworkPlot/index.d.ts +3 -0
- package/dist/plugin-basic/src/plugins/NetworkPlot/layers/ForceDirected.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/NetworkPlot/layers/ForceDirectedBubbles.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/NetworkPlot/types.d.ts +117 -0
- package/dist/plugin-basic/src/plugins/ScatterPlot/ScatterPlot.d.ts +22 -0
- package/dist/plugin-basic/src/plugins/ScatterPlot/contextObservables.d.ts +140 -0
- package/dist/plugin-basic/src/plugins/ScatterPlot/defaults.d.ts +8 -0
- package/dist/plugin-basic/src/plugins/ScatterPlot/index.d.ts +3 -0
- package/dist/plugin-basic/src/plugins/ScatterPlot/layers/Scatter.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/ScatterPlot/layers/ScatterBubbles.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/ScatterPlot/layers/XYAux.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/ScatterPlot/layers/XYAxes.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/ScatterPlot/layers/XZoom.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/ScatterPlot/types.d.ts +146 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/SeriesPlot.d.ts +22 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/contextObservables.d.ts +77 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/defaults.d.ts +15 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/index.d.ts +3 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/Bars.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/BarsPN.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/BarsTriangle.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/CategoryAux.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/CategoryAxis.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/CategoryZoom.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/Dots.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/LineAreas.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/Lines.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/StackedBars.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/StackedValueAxis.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/layers/ValueAxis.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/SeriesPlot/types.d.ts +140 -0
- package/dist/plugin-basic/src/plugins/Tooltip/Tooltip.d.ts +22 -0
- package/dist/plugin-basic/src/plugins/Tooltip/contextObservables.d.ts +9 -0
- package/dist/plugin-basic/src/plugins/Tooltip/defaults.d.ts +4 -0
- package/dist/plugin-basic/src/plugins/Tooltip/index.d.ts +3 -0
- package/dist/plugin-basic/src/plugins/Tooltip/layers/Tooltip.d.ts +16 -0
- package/dist/plugin-basic/src/plugins/Tooltip/types.d.ts +35 -0
- package/dist/plugin-basic/src/plugins/Tooltip/utils.d.ts +19 -0
- package/dist/plugin-basic/src/plugins/index.d.ts +7 -0
- package/dist/plugin-basic/src/types/BaseLayer.d.ts +3 -0
- package/dist/plugin-basic/src/types/Common.d.ts +14 -0
- package/dist/plugin-basic/src/types/ComputedData.d.ts +27 -0
- package/dist/plugin-basic/src/types/PluginParams.d.ts +66 -0
- package/dist/plugin-basic/src/types/index.d.ts +3 -0
- package/dist/plugin-basic/src/utils/commonUtils.d.ts +3 -0
- package/dist/plugin-basic/src/utils/d3Graphics.d.ts +24 -0
- package/dist/plugin-basic/src/utils/d3Scale.d.ts +28 -0
- package/dist/plugin-basic/src/utils/d3Utils.d.ts +14 -0
- package/dist/plugin-basic/src/utils/graphObservables.d.ts +0 -0
- package/dist/plugin-basic/src/utils/gridObservables.d.ts +51 -0
- package/dist/plugin-basic/src/utils/multivariateObservables.d.ts +74 -0
- package/dist/plugin-basic/src/utils/observables.d.ts +34 -0
- package/dist/plugin-basic/src/utils/orbchartsUtils.d.ts +26 -0
- package/dist/plugin-basic/src/utils/seriesObservables.d.ts +22 -0
- package/dist/plugin-basic/vite.config.d.ts +2 -0
- package/dist/src/index.d.ts +1 -0
- package/package.json +62 -0
- package/src/baseLayers/BaseBars.ts +783 -0
- package/src/baseLayers/BaseBarsTriangle.ts +692 -0
- package/src/baseLayers/BaseCategoryAxis.ts +708 -0
- package/src/baseLayers/BaseDots.ts +495 -0
- package/src/baseLayers/BaseLegend.ts +684 -0
- package/src/baseLayers/BaseLineAreas.ts +644 -0
- package/src/baseLayers/BaseLines.ts +721 -0
- package/src/baseLayers/BaseStackedBars.ts +818 -0
- package/src/baseLayers/BaseTooltip.ts +435 -0
- package/src/baseLayers/BaseValueAxis.ts +612 -0
- package/src/baseLayers/BaseXAxis.ts +412 -0
- package/src/baseLayers/BaseXZoom.ts +250 -0
- package/src/baseLayers/BaseYAxis.ts +371 -0
- package/src/baseLayers/types.ts +174 -0
- package/src/const/layerIndex.ts +36 -0
- package/src/const/sharedPluginParams.ts +29 -0
- package/src/index.ts +3 -0
- package/src/plugins/CompositionPlot/CompositionPlot.ts +308 -0
- package/src/plugins/CompositionPlot/contextObservables.ts +251 -0
- package/src/plugins/CompositionPlot/defaults.ts +162 -0
- package/src/plugins/CompositionPlot/index.ts +3 -0
- package/src/plugins/CompositionPlot/layers/Bubbles.ts +808 -0
- package/src/plugins/CompositionPlot/layers/Indicator.ts +0 -0
- package/src/plugins/CompositionPlot/layers/Pie.ts +776 -0
- package/src/plugins/CompositionPlot/layers/PieEventTexts.ts +326 -0
- package/src/plugins/CompositionPlot/layers/PieLabels.ts +651 -0
- package/src/plugins/CompositionPlot/layers/Rose.ts +546 -0
- package/src/plugins/CompositionPlot/layers/RoseLabels.ts +616 -0
- package/src/plugins/CompositionPlot/layers/Waffle.ts +0 -0
- package/src/plugins/CompositionPlot/types.ts +129 -0
- package/src/plugins/CompositionPlot/utils.ts +53 -0
- package/src/plugins/HierarchyPlot/HierarchyPlot.ts +190 -0
- package/src/plugins/HierarchyPlot/contextObservables.ts +136 -0
- package/src/plugins/HierarchyPlot/defaults.ts +31 -0
- package/src/plugins/HierarchyPlot/index.ts +3 -0
- package/src/plugins/HierarchyPlot/layers/TreeMap.ts +371 -0
- package/src/plugins/HierarchyPlot/types.ts +36 -0
- package/src/plugins/Legend/Legend.ts +151 -0
- package/src/plugins/Legend/contextObservables.ts +55 -0
- package/src/plugins/Legend/defaults.ts +37 -0
- package/src/plugins/Legend/index.ts +3 -0
- package/src/plugins/Legend/layers/Legend.ts +114 -0
- package/src/plugins/Legend/types.ts +45 -0
- package/src/plugins/Legend/utils.ts +53 -0
- package/src/plugins/NetworkPlot/NetworkPlot.ts +228 -0
- package/src/plugins/NetworkPlot/contextObservables.ts +123 -0
- package/src/plugins/NetworkPlot/defaults.ts +147 -0
- package/src/plugins/NetworkPlot/index.ts +3 -0
- package/src/plugins/NetworkPlot/layers/ForceDirected.ts +1048 -0
- package/src/plugins/NetworkPlot/layers/ForceDirectedBubbles.ts +1318 -0
- package/src/plugins/NetworkPlot/types.ts +146 -0
- package/src/plugins/ScatterPlot/ScatterPlot.ts +569 -0
- package/src/plugins/ScatterPlot/contextObservables.ts +901 -0
- package/src/plugins/ScatterPlot/defaults.ts +212 -0
- package/src/plugins/ScatterPlot/index.ts +3 -0
- package/src/plugins/ScatterPlot/layers/Scatter.ts +518 -0
- package/src/plugins/ScatterPlot/layers/ScatterBubbles.ts +670 -0
- package/src/plugins/ScatterPlot/layers/XYAux.ts +686 -0
- package/src/plugins/ScatterPlot/layers/XYAxes.ts +205 -0
- package/src/plugins/ScatterPlot/layers/XZoom.ts +48 -0
- package/src/plugins/ScatterPlot/types.ts +179 -0
- package/src/plugins/SeriesPlot/SeriesPlot.ts +494 -0
- package/src/plugins/SeriesPlot/contextObservables.ts +726 -0
- package/src/plugins/SeriesPlot/defaults.ts +142 -0
- package/src/plugins/SeriesPlot/index.ts +3 -0
- package/src/plugins/SeriesPlot/layers/Bars.ts +84 -0
- package/src/plugins/SeriesPlot/layers/BarsPN.ts +85 -0
- package/src/plugins/SeriesPlot/layers/BarsTriangle.ts +89 -0
- package/src/plugins/SeriesPlot/layers/CategoryAux.ts +1131 -0
- package/src/plugins/SeriesPlot/layers/CategoryAxis.ts +92 -0
- package/src/plugins/SeriesPlot/layers/CategoryZoom.ts +233 -0
- package/src/plugins/SeriesPlot/layers/Dots.ts +91 -0
- package/src/plugins/SeriesPlot/layers/LineAreas.ts +82 -0
- package/src/plugins/SeriesPlot/layers/Lines.ts +75 -0
- package/src/plugins/SeriesPlot/layers/StackedBars.ts +85 -0
- package/src/plugins/SeriesPlot/layers/StackedValueAxis.ts +111 -0
- package/src/plugins/SeriesPlot/layers/ValueAxis.ts +111 -0
- package/src/plugins/SeriesPlot/types.ts +201 -0
- package/src/plugins/Tooltip/Tooltip.ts +159 -0
- package/src/plugins/Tooltip/contextObservables.ts +55 -0
- package/src/plugins/Tooltip/defaults.ts +458 -0
- package/src/plugins/Tooltip/index.ts +3 -0
- package/src/plugins/Tooltip/layers/Tooltip.ts +90 -0
- package/src/plugins/Tooltip/types.ts +55 -0
- package/src/plugins/Tooltip/utils.ts +53 -0
- package/src/plugins/index.ts +8 -0
- package/src/types/BaseLayer.ts +3 -0
- package/src/types/Common.ts +20 -0
- package/src/types/ComputedData.ts +55 -0
- package/src/types/PluginParams.ts +81 -0
- package/src/types/index.ts +3 -0
- package/src/utils/commonUtils.ts +31 -0
- package/src/utils/d3Graphics.ts +177 -0
- package/src/utils/d3Scale.ts +198 -0
- package/src/utils/d3Utils.ts +92 -0
- package/src/utils/graphObservables.ts +0 -0
- package/src/utils/gridObservables.ts +637 -0
- package/src/utils/multivariateObservables.ts +790 -0
- package/src/utils/observables.ts +357 -0
- package/src/utils/orbchartsUtils.ts +335 -0
- package/src/utils/seriesObservables.ts +172 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import * as d3 from 'd3'
|
|
2
|
+
// import { Observable, merge, distinctUntilChanged, fromEvent } from 'rxjs'
|
|
3
|
+
import {
|
|
4
|
+
combineLatest,
|
|
5
|
+
distinctUntilChanged,
|
|
6
|
+
filter,
|
|
7
|
+
fromEvent,
|
|
8
|
+
map,
|
|
9
|
+
merge,
|
|
10
|
+
takeUntil,
|
|
11
|
+
shareReplay,
|
|
12
|
+
switchMap,
|
|
13
|
+
Subject,
|
|
14
|
+
Observable,
|
|
15
|
+
debounceTime
|
|
16
|
+
} from 'rxjs'
|
|
17
|
+
import type {
|
|
18
|
+
ModelType,
|
|
19
|
+
Theme,
|
|
20
|
+
ModelDatum
|
|
21
|
+
} from '@orbcharts/core'
|
|
22
|
+
import type {
|
|
23
|
+
ComputedDatum
|
|
24
|
+
} from '../types/ComputedData'
|
|
25
|
+
import type {
|
|
26
|
+
EventData
|
|
27
|
+
} from '@orbcharts/core'
|
|
28
|
+
import type {
|
|
29
|
+
Layout,
|
|
30
|
+
Padding,
|
|
31
|
+
GraphicStyles,
|
|
32
|
+
ContainerPositionScaled,
|
|
33
|
+
HighlightTarget,
|
|
34
|
+
Container
|
|
35
|
+
} from '../types/PluginParams'
|
|
36
|
+
|
|
37
|
+
// interface DatumUnknown {
|
|
38
|
+
// value: number | null
|
|
39
|
+
// id: string
|
|
40
|
+
// // label: string
|
|
41
|
+
// seriesLabel?: string // 要符合每一種computedData所以不一定會有seriesLabel
|
|
42
|
+
// groupLabel?: string // 要符合每一種computedData所以不一定會有groupLabel
|
|
43
|
+
// }
|
|
44
|
+
|
|
45
|
+
export function d3EventObservable(selection: d3.Selection<any, any, any, any>, event: any) {
|
|
46
|
+
// Start with an observable that will never emit
|
|
47
|
+
let obs: Observable<MouseEvent> = new Observable(() => {});
|
|
48
|
+
selection.each(function () {
|
|
49
|
+
// Create observables from each of the elements
|
|
50
|
+
const events: Observable<MouseEvent> = fromEvent(this, event);
|
|
51
|
+
// Merge the observables into one
|
|
52
|
+
obs = merge(obs, events);
|
|
53
|
+
});
|
|
54
|
+
return obs;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function resizeObservable(elem: HTMLElement | Element): Observable<DOMRectReadOnly> {
|
|
58
|
+
return new Observable(subscriber => {
|
|
59
|
+
const ro = new ResizeObserver(entries => {
|
|
60
|
+
const entry = entries[0]
|
|
61
|
+
if (entry && entry.contentRect) {
|
|
62
|
+
subscriber.next(entry.contentRect)
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
ro.observe(elem)
|
|
67
|
+
return function unsubscribe() {
|
|
68
|
+
ro.unobserve(elem)
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function layoutObservable({size$, padding$}: {size$: Observable<{ width: number, height: number }>, padding$: Observable<Padding>}): Observable<Layout> {
|
|
74
|
+
return combineLatest({
|
|
75
|
+
size: size$,
|
|
76
|
+
padding: padding$
|
|
77
|
+
}).pipe(
|
|
78
|
+
debounceTime(0),
|
|
79
|
+
map(data => {
|
|
80
|
+
const width = data.size.width - data.padding.left - data.padding.right
|
|
81
|
+
const height = data.size.height - data.padding.top - data.padding.bottom
|
|
82
|
+
const layout: Layout = {
|
|
83
|
+
rootWidth: data.size.width,
|
|
84
|
+
rootHeight: data.size.height,
|
|
85
|
+
width: width > 0 ? width : 0,
|
|
86
|
+
height: height > 0 ? height : 0,
|
|
87
|
+
left: data.padding.left,
|
|
88
|
+
right: data.padding.right,
|
|
89
|
+
top: data.padding.top,
|
|
90
|
+
bottom: data.padding.bottom
|
|
91
|
+
}
|
|
92
|
+
return layout
|
|
93
|
+
}),
|
|
94
|
+
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
|
|
95
|
+
shareReplay(1)
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
interface HighlightTargetValue {
|
|
100
|
+
id: string | null
|
|
101
|
+
label: string | null
|
|
102
|
+
series: string | null
|
|
103
|
+
// group: string | null
|
|
104
|
+
category: string | null
|
|
105
|
+
// highlightDefault: string | null
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 通用 highlight Observable
|
|
109
|
+
export const highlightObservable = <T extends ModelType, D>({ datumList$, styles$, event$ }: {
|
|
110
|
+
datumList$: Observable<D[]>
|
|
111
|
+
styles$: Observable<GraphicStyles>
|
|
112
|
+
event$: Observable<EventData<T>>
|
|
113
|
+
}): Observable<D[]> => {
|
|
114
|
+
const destroy$ = new Subject()
|
|
115
|
+
|
|
116
|
+
// 預設的highlight
|
|
117
|
+
const highlightDefault$: Observable<HighlightTargetValue> = styles$.pipe(
|
|
118
|
+
takeUntil(destroy$),
|
|
119
|
+
map(d => d.highlightDefault || null),
|
|
120
|
+
distinctUntilChanged(),
|
|
121
|
+
map(highlightDefault => {
|
|
122
|
+
return {
|
|
123
|
+
id: highlightDefault,
|
|
124
|
+
label: highlightDefault,
|
|
125
|
+
series: highlightDefault,
|
|
126
|
+
category: highlightDefault,
|
|
127
|
+
// highlightDefault
|
|
128
|
+
} as HighlightTargetValue
|
|
129
|
+
}),
|
|
130
|
+
shareReplay(1)
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
const highlightTarget$: Observable<HighlightTarget> = styles$.pipe(
|
|
134
|
+
takeUntil(destroy$),
|
|
135
|
+
map(d => d.highlightTarget),
|
|
136
|
+
distinctUntilChanged(),
|
|
137
|
+
shareReplay(1)
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
// 事件觸發的highlight
|
|
141
|
+
const highlightMouseover$: Observable<HighlightTargetValue> = highlightTarget$.pipe(
|
|
142
|
+
switchMap(highlightTarget => {
|
|
143
|
+
return event$.pipe(
|
|
144
|
+
takeUntil(destroy$),
|
|
145
|
+
// filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove'),
|
|
146
|
+
filter(d => d.eventName === 'mouseover'),
|
|
147
|
+
// distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
|
|
148
|
+
map(d => {
|
|
149
|
+
|
|
150
|
+
// const d = _d as any
|
|
151
|
+
// console.log('mouseover event', d)
|
|
152
|
+
return d.target
|
|
153
|
+
? {
|
|
154
|
+
id: d.target.id,
|
|
155
|
+
label: null, // label有可能重覆所以不做判斷
|
|
156
|
+
series: highlightTarget === 'series' ? d.target.series : null,
|
|
157
|
+
category: highlightTarget === 'category' ? (d.target as ModelDatum<'grid' | 'multivariate' | 'graph' | 'tree'>).category : null,
|
|
158
|
+
// highlightDefault: null
|
|
159
|
+
} as HighlightTargetValue
|
|
160
|
+
: {
|
|
161
|
+
id: null,
|
|
162
|
+
label: null,
|
|
163
|
+
series: null,
|
|
164
|
+
// group: null,
|
|
165
|
+
category: null,
|
|
166
|
+
// highlightDefault: null
|
|
167
|
+
} as HighlightTargetValue
|
|
168
|
+
})
|
|
169
|
+
)
|
|
170
|
+
})
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
const highlightMouseout$ = event$.pipe(
|
|
174
|
+
takeUntil(destroy$),
|
|
175
|
+
filter(d => d.eventName === 'mouseout'),
|
|
176
|
+
// distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
|
|
177
|
+
// map(d => {
|
|
178
|
+
// return { id: '', label: '' }
|
|
179
|
+
// })
|
|
180
|
+
switchMap(d => highlightDefault$)
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
// function getDatumIds (datumList: ComputedDatum<T>[], id: string | null) {
|
|
184
|
+
// const datum = datumList.find(d => (d as ComputedDatumBase).id === id)
|
|
185
|
+
// return datum ? [datum] : []
|
|
186
|
+
// }
|
|
187
|
+
function getDatumIds (datumList: ComputedDatum<T>[], id: string | null, label: string | null) {
|
|
188
|
+
return id == null && label == null
|
|
189
|
+
? []
|
|
190
|
+
: datumList.filter(d => d.id === id || d.name === label)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function getSeriesIds (datumList: ComputedDatum<T>[], seriesLabel: string | null) {
|
|
194
|
+
return seriesLabel == null
|
|
195
|
+
? []
|
|
196
|
+
: datumList.filter(d => (d as ComputedDatum<"series">).series === seriesLabel)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// function getGroupIds (datumList: ComputedDatum<T>[], groupLabel: string | null) {
|
|
200
|
+
// return groupLabel == null
|
|
201
|
+
// ? []
|
|
202
|
+
// : datumList.filter(d => (d as ComputedDatum<"grid">).category === groupLabel)
|
|
203
|
+
// }
|
|
204
|
+
|
|
205
|
+
function getCategoryIds (datumList: ComputedDatum<T>[], category: string | null) {
|
|
206
|
+
return category == null
|
|
207
|
+
? []
|
|
208
|
+
: datumList.filter(d => (d as ComputedDatum<"multivariate" | "graph" | "tree">).category === category)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return new Observable<D[]>(subscriber => {
|
|
212
|
+
combineLatest({
|
|
213
|
+
target: merge(highlightMouseover$, highlightMouseout$, highlightDefault$),
|
|
214
|
+
datumList: datumList$,
|
|
215
|
+
styles: styles$,
|
|
216
|
+
}).pipe(
|
|
217
|
+
takeUntil(destroy$),
|
|
218
|
+
debounceTime(0),
|
|
219
|
+
).subscribe(data => {
|
|
220
|
+
let datumList: ComputedDatum<T>[] = []
|
|
221
|
+
if (data.styles.highlightTarget === 'datum') {
|
|
222
|
+
datumList = getDatumIds(data.datumList as ComputedDatum<T>[], data.target.id, data.target.label)
|
|
223
|
+
} else if (data.styles.highlightTarget === 'series') {
|
|
224
|
+
datumList = getSeriesIds(data.datumList as ComputedDatum<T>[], data.target.series)
|
|
225
|
+
// } else if (data.styles.highlightTarget === 'group') {
|
|
226
|
+
// datumList = getGroupIds(data.datumList as ComputedDatum<T>[], data.target.group)
|
|
227
|
+
} else if (data.styles.highlightTarget === 'category') {
|
|
228
|
+
datumList = getCategoryIds(data.datumList as ComputedDatum<T>[], data.target.category)
|
|
229
|
+
}
|
|
230
|
+
subscriber.next(datumList as D[])
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
return function unsubscribe () {
|
|
234
|
+
destroy$.next(undefined)
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export const seriesDataMapObservable = <DatumType extends ComputedDatum<'series' | 'grid'>>({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
|
|
240
|
+
return datumList$.pipe(
|
|
241
|
+
map(data => {
|
|
242
|
+
const SeriesDataMap: Map<string, DatumType[]> = new Map()
|
|
243
|
+
data.forEach(d => {
|
|
244
|
+
const seriesData = SeriesDataMap.get(d.series) ?? []
|
|
245
|
+
seriesData.push(d)
|
|
246
|
+
SeriesDataMap.set(d.series, seriesData)
|
|
247
|
+
})
|
|
248
|
+
return SeriesDataMap
|
|
249
|
+
})
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// export const groupDataMapObservable = <DatumType extends ComputedDatum<'grid'>> ({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
|
|
254
|
+
// return datumList$.pipe(
|
|
255
|
+
// map(data => {
|
|
256
|
+
// const GroupDataMap: Map<string, DatumType[]> = new Map()
|
|
257
|
+
// data.forEach(d => {
|
|
258
|
+
// const groupData = GroupDataMap.get(d.category) ?? []
|
|
259
|
+
// groupData.push(d)
|
|
260
|
+
// GroupDataMap.set(d.category, groupData)
|
|
261
|
+
// })
|
|
262
|
+
// return GroupDataMap
|
|
263
|
+
// })
|
|
264
|
+
// )
|
|
265
|
+
// }
|
|
266
|
+
|
|
267
|
+
export const categoryDataMapObservable = <DatumType extends ComputedDatum<'multivariate' | 'graph' | 'tree'>> ({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
|
|
268
|
+
return datumList$.pipe(
|
|
269
|
+
map(data => {
|
|
270
|
+
const GroupDataMap: Map<string, DatumType[]> = new Map()
|
|
271
|
+
data
|
|
272
|
+
.filter(d => d.category != null)
|
|
273
|
+
.forEach(d => {
|
|
274
|
+
const groupData = GroupDataMap.get(d.category) ?? []
|
|
275
|
+
groupData.push(d)
|
|
276
|
+
GroupDataMap.set(d.category, groupData)
|
|
277
|
+
})
|
|
278
|
+
return GroupDataMap
|
|
279
|
+
})
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export const fontSizePxObservable = (chartParams$: Observable<Theme>) => {
|
|
284
|
+
return chartParams$.pipe(
|
|
285
|
+
map(d => d.fontSize),
|
|
286
|
+
distinctUntilChanged(),
|
|
287
|
+
map(data => {
|
|
288
|
+
let value = NaN
|
|
289
|
+
if (typeof data === 'string') {
|
|
290
|
+
if (data.includes('rem')) {
|
|
291
|
+
const rootFontSizePx = parseFloat(getComputedStyle(document.documentElement).fontSize)
|
|
292
|
+
const num = parseFloat(data)
|
|
293
|
+
value = num * rootFontSizePx
|
|
294
|
+
} else if (data.includes('px')) {
|
|
295
|
+
value = parseFloat(data)
|
|
296
|
+
}
|
|
297
|
+
} else if (typeof data === 'number') {
|
|
298
|
+
return data
|
|
299
|
+
}
|
|
300
|
+
return value ? value : 14 // default
|
|
301
|
+
})
|
|
302
|
+
)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export const containerSizeObservable = ({ layout$, containerPosition$, container$ }: {
|
|
306
|
+
layout$: Observable<Layout>
|
|
307
|
+
containerPosition$: Observable<ContainerPositionScaled[]>
|
|
308
|
+
container$: Observable<Container>
|
|
309
|
+
}) => {
|
|
310
|
+
const rowAmount$ = containerPosition$.pipe(
|
|
311
|
+
map(containerPosition => {
|
|
312
|
+
const maxRowIndex = containerPosition.reduce((acc, current) => {
|
|
313
|
+
return current.rowIndex > acc ? current.rowIndex : acc
|
|
314
|
+
}, 0)
|
|
315
|
+
return maxRowIndex + 1
|
|
316
|
+
}),
|
|
317
|
+
distinctUntilChanged(),
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
const columnAmount$ = containerPosition$.pipe(
|
|
321
|
+
map(containerPosition => {
|
|
322
|
+
const maxColumnIndex = containerPosition.reduce((acc, current) => {
|
|
323
|
+
return current.columnIndex > acc ? current.columnIndex : acc
|
|
324
|
+
}, 0)
|
|
325
|
+
return maxColumnIndex + 1
|
|
326
|
+
}),
|
|
327
|
+
distinctUntilChanged()
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
return combineLatest({
|
|
331
|
+
layout: layout$,
|
|
332
|
+
rowAmount: rowAmount$,
|
|
333
|
+
columnAmount: columnAmount$,
|
|
334
|
+
container: container$
|
|
335
|
+
}).pipe(
|
|
336
|
+
debounceTime(0),
|
|
337
|
+
map(data => {
|
|
338
|
+
// const width = (data.layout.rootWidth / data.columnAmount) - (data.layout.left + data.layout.right)
|
|
339
|
+
// const height = (data.layout.rootHeight / data.rowAmount) - (data.layout.top + data.layout.bottom)
|
|
340
|
+
const columnGap = data.container.columnGap === 'auto'
|
|
341
|
+
? data.layout.left + data.layout.right
|
|
342
|
+
: data.container.columnGap
|
|
343
|
+
const rowGap = data.container.rowGap === 'auto'
|
|
344
|
+
? data.layout.top + data.layout.bottom
|
|
345
|
+
: data.container.rowGap
|
|
346
|
+
const width = (data.layout.rootWidth - data.layout.left - data.layout.right - (columnGap * (data.columnAmount - 1))) / data.columnAmount
|
|
347
|
+
const height = (data.layout.rootHeight - data.layout.top - data.layout.bottom - (rowGap * (data.rowAmount - 1))) / data.rowAmount
|
|
348
|
+
|
|
349
|
+
return {
|
|
350
|
+
width,
|
|
351
|
+
height
|
|
352
|
+
}
|
|
353
|
+
}),
|
|
354
|
+
distinctUntilChanged((a, b) => a.width === b.width && a.height === b.height),
|
|
355
|
+
// shareReplay(1)
|
|
356
|
+
)
|
|
357
|
+
}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
// AxisPosition,
|
|
3
|
+
ColorType,
|
|
4
|
+
Theme,
|
|
5
|
+
ModelDatum,
|
|
6
|
+
ModelDatumBase,
|
|
7
|
+
ModelDatumSeries,
|
|
8
|
+
ModelType,
|
|
9
|
+
|
|
10
|
+
// ChartParams,
|
|
11
|
+
// ComputedDatumBase,
|
|
12
|
+
// ComputedDatumBaseValue,
|
|
13
|
+
// ComputedDatumBaseSeries,
|
|
14
|
+
// ComputedDatumBaseCategory
|
|
15
|
+
} from '@orbcharts/core'
|
|
16
|
+
import { Layout, Container, ContainerPosition, ContainerPositionScaled } from '../types/PluginParams'
|
|
17
|
+
import { getMinMax } from './commonUtils'
|
|
18
|
+
import { isLightColor } from './d3Utils'
|
|
19
|
+
import { createLayerClassName } from '@orbcharts/core'
|
|
20
|
+
import type { AxisPosition } from '../types/PluginParams'
|
|
21
|
+
import type { ComputedDatum } from '../types/ComputedData'
|
|
22
|
+
|
|
23
|
+
// 取得最小及最大值 - datum格式陣列資料
|
|
24
|
+
export function getMinMaxValue<T extends ModelType> (data: ComputedDatum<T>[]): [number, number] {
|
|
25
|
+
const arr = data
|
|
26
|
+
.filter(d => d.value != null && d.visible != false)
|
|
27
|
+
.map(d => d.value as number)
|
|
28
|
+
return getMinMax(arr)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// // 取得最小及最大值 - Series Data
|
|
32
|
+
// export function getMinMaxSeries (data: ModelDatum<'series'>[][]): [number, number] {
|
|
33
|
+
// const flatData: ModelDatum<'series'>[] = data[0] && Array.isArray((data as (DataSeriesValue | DataSeriesDatum)[][])[0])
|
|
34
|
+
// ? data.flat()
|
|
35
|
+
// : data as (DataSeriesValue | DataSeriesDatum)[]
|
|
36
|
+
// const arr = flatData
|
|
37
|
+
// .filter(d => (d == null || (isPlainObject(d) && (d as DataSeriesDatum).value == null)) === false) // 過濾掉null &
|
|
38
|
+
// .map(d => typeof d === 'number' ? d : d.value )
|
|
39
|
+
// return getMinMax(arr)
|
|
40
|
+
// }
|
|
41
|
+
|
|
42
|
+
// // 取得最小及最大值 - Grid Data
|
|
43
|
+
// export function getMinMaxGrid (data: DataGrid): [number, number] {
|
|
44
|
+
// const flatData: (DataGridValue | DataGridDatum)[] = data.flat()
|
|
45
|
+
// const arr = flatData
|
|
46
|
+
// .filter(d => (d == null || (isPlainObject(d) && (d as DataGridDatum).value == null)) === false) // 過濾掉null
|
|
47
|
+
// .map(d => typeof d === 'number' ? d : d.value )
|
|
48
|
+
// return getMinMax(arr)
|
|
49
|
+
// }
|
|
50
|
+
|
|
51
|
+
// // 取得最小及最大值 - MultiGrid Data
|
|
52
|
+
// export function getMinMaxMultiGrid (data: DataMultiGrid): [number, number] {
|
|
53
|
+
// const flatData: (DataGridValue | DataGridDatum)[] = data.flat().flat()
|
|
54
|
+
// const arr = flatData
|
|
55
|
+
// .filter(d => (d == null || (isPlainObject(d) && (d as DataGridDatum).value == null)) === false) // 過濾掉null
|
|
56
|
+
// .map(d => typeof d === 'number' ? d : d.value )
|
|
57
|
+
// return getMinMax(arr)
|
|
58
|
+
// }
|
|
59
|
+
|
|
60
|
+
// // 取得最小及最大值 - MultiValue Data
|
|
61
|
+
// export function getMinMaxMultiValue (data: DataMultiValue, valueIndex: number): [number, number] {
|
|
62
|
+
// const arr: number[] = data
|
|
63
|
+
// .map(d => {
|
|
64
|
+
// if (Array.isArray(d)) {
|
|
65
|
+
// return d[valueIndex] ?? null
|
|
66
|
+
// } else if (isPlainObject(d)) {
|
|
67
|
+
// return (d as DataMultiValueDatum).value[valueIndex] ?? null
|
|
68
|
+
// } else {
|
|
69
|
+
// return null
|
|
70
|
+
// }
|
|
71
|
+
// })
|
|
72
|
+
// .filter(d => d != null)
|
|
73
|
+
// return getMinMax(arr)
|
|
74
|
+
// }
|
|
75
|
+
|
|
76
|
+
// export function getMinMaxMultiValueXY ({ data, minX, maxX, minY, maxY }: {
|
|
77
|
+
// data: ComputedXYDatumMultiValue[][]
|
|
78
|
+
// minX: number
|
|
79
|
+
// maxX: number
|
|
80
|
+
// minY: number
|
|
81
|
+
// maxY: number
|
|
82
|
+
// }) {
|
|
83
|
+
// let filteredData: ComputedXYDatumMultiValue[][] = []
|
|
84
|
+
// let minXDatum: ComputedXYDatumMultiValue | null = null
|
|
85
|
+
// let maxXDatum: ComputedXYDatumMultiValue | null = null
|
|
86
|
+
// let minYDatum: ComputedXYDatumMultiValue | null = null
|
|
87
|
+
// let maxYDatum: ComputedXYDatumMultiValue | null = null
|
|
88
|
+
|
|
89
|
+
// for (let categoryData of data) {
|
|
90
|
+
// for (let datum of categoryData) {
|
|
91
|
+
// if (datum.axisX >= minX && datum.axisX <= maxX && datum.axisY >= minY && datum.axisY <= maxY) {
|
|
92
|
+
// filteredData.push(categoryData)
|
|
93
|
+
// if (minXDatum == null || datum.axisX < minXDatum.axisX) {
|
|
94
|
+
// minXDatum = datum
|
|
95
|
+
// }
|
|
96
|
+
// if (maxXDatum == null || datum.axisX > maxXDatum.axisX) {
|
|
97
|
+
// maxXDatum = datum
|
|
98
|
+
// }
|
|
99
|
+
// if (minYDatum == null || datum.axisY < minYDatum.axisY) {
|
|
100
|
+
// minYDatum = datum
|
|
101
|
+
// }
|
|
102
|
+
// if (maxYDatum == null || datum.axisY > maxYDatum.axisY) {
|
|
103
|
+
// maxYDatum = datum
|
|
104
|
+
// }
|
|
105
|
+
// }
|
|
106
|
+
// }
|
|
107
|
+
// }
|
|
108
|
+
|
|
109
|
+
// return {
|
|
110
|
+
// minXDatum,
|
|
111
|
+
// maxXDatum,
|
|
112
|
+
// minYDatum,
|
|
113
|
+
// maxYDatum,
|
|
114
|
+
// filteredData
|
|
115
|
+
// }
|
|
116
|
+
// }
|
|
117
|
+
|
|
118
|
+
export function getColorScheme (themeColorScheme: 'light' | 'dark' | 'auto') {
|
|
119
|
+
if (themeColorScheme === 'auto') {
|
|
120
|
+
const MediaQueryList = window.matchMedia('(prefers-color-scheme: dark)')
|
|
121
|
+
return MediaQueryList.matches ? 'dark' : 'light'
|
|
122
|
+
} else {
|
|
123
|
+
return themeColorScheme
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 取得colorType顏色
|
|
128
|
+
export function getColor (colorType: ColorType, theme: Theme) {
|
|
129
|
+
const colorScheme = getColorScheme(theme.colorScheme)
|
|
130
|
+
const colors = theme.colors[colorScheme]
|
|
131
|
+
if (colorType === 'data') {
|
|
132
|
+
return colors.data[0] // default label color
|
|
133
|
+
} else if (colorType === 'dataContrast') {
|
|
134
|
+
return isLightColor(colors.data[0]) // default label color
|
|
135
|
+
? colors.dataContrast[1]
|
|
136
|
+
: colors.dataContrast[0]
|
|
137
|
+
}
|
|
138
|
+
return colorType == 'none'
|
|
139
|
+
? 'none'
|
|
140
|
+
: colors[colorType] != undefined
|
|
141
|
+
? colors[colorType]
|
|
142
|
+
: colors.primary // 如果比對不到
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// export function getSeriesValueColor () {
|
|
146
|
+
|
|
147
|
+
// }
|
|
148
|
+
|
|
149
|
+
// export function getCategoryValueColor ({ datum, colorType, fullChartParams }: { datum: ComputedDatumBaseCategory, colorType: ColorType, fullChartParams: ChartParams }) {
|
|
150
|
+
|
|
151
|
+
// }
|
|
152
|
+
|
|
153
|
+
// // 取得Series顏色
|
|
154
|
+
// export function getSeriesColor (seriesIndex: number, fullChartParams: ChartParams) {
|
|
155
|
+
// const colorIndex = seriesIndex < fullChartParams.colors[fullChartParams.colorScheme].series.length
|
|
156
|
+
// ? seriesIndex
|
|
157
|
+
// : seriesIndex % fullChartParams.colors[fullChartParams.colorScheme].series.length
|
|
158
|
+
// return fullChartParams.colors[fullChartParams.colorScheme].series[colorIndex]
|
|
159
|
+
// }
|
|
160
|
+
|
|
161
|
+
// 取得Datum顏色
|
|
162
|
+
export function getDatumColor ({ datum, colorType, theme }: { datum: ModelDatumBase, colorType: ColorType, theme: Theme }) {
|
|
163
|
+
const colors = theme.colors[getColorScheme(theme.colorScheme)]
|
|
164
|
+
|
|
165
|
+
if (colorType === 'data') {
|
|
166
|
+
const datumColor: string | undefined = (datum as unknown as ModelDatumSeries).color
|
|
167
|
+
if (datumColor) {
|
|
168
|
+
return datumColor
|
|
169
|
+
} else {
|
|
170
|
+
// default label color
|
|
171
|
+
return colors.data[0]
|
|
172
|
+
}
|
|
173
|
+
} else if (colorType === 'dataContrast') {
|
|
174
|
+
const datumColor: string | undefined = (datum as unknown as ModelDatumSeries).color
|
|
175
|
+
if (datumColor) {
|
|
176
|
+
return isLightColor(datumColor)
|
|
177
|
+
? colors.dataContrast[1]
|
|
178
|
+
: colors.dataContrast[0]
|
|
179
|
+
} else {
|
|
180
|
+
// default label color
|
|
181
|
+
return isLightColor(colors.data[0])
|
|
182
|
+
? colors.dataContrast[1]
|
|
183
|
+
: colors.dataContrast[0]
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// 對應colorType設定的顏色
|
|
187
|
+
return colorType == 'none'
|
|
188
|
+
? 'none'
|
|
189
|
+
: colors[colorType] != undefined
|
|
190
|
+
? colors[colorType]
|
|
191
|
+
: colors.primary
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function seriesColorPredicate (seriesIndex: number, theme: Theme) {
|
|
195
|
+
const colorScheme = getColorScheme(theme.colorScheme)
|
|
196
|
+
return seriesIndex < theme.colors[colorScheme].data.length
|
|
197
|
+
? theme.colors[colorScheme].data[seriesIndex]
|
|
198
|
+
: theme.colors[colorScheme].data[
|
|
199
|
+
seriesIndex % theme.colors[colorScheme].data.length
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function createClassName (pluginName: string, layerName: string, elementName: string, modifier?: string) {
|
|
204
|
+
const modifierText = modifier ? `--${modifier}` : ''
|
|
205
|
+
return `${createLayerClassName(pluginName, layerName)}__${elementName}${modifierText}`
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function createUniID (pluginName: string, layerName: string, elementName: string) {
|
|
209
|
+
const textLength = 5
|
|
210
|
+
// 英文+數字
|
|
211
|
+
const randomText: string = Math.random().toString(36).substr(2, textLength)
|
|
212
|
+
|
|
213
|
+
return createClassName(pluginName, layerName, elementName, randomText)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
export function calcAxesSize ({ xAxisPosition, yAxisPosition, width, height }: {
|
|
218
|
+
xAxisPosition: AxisPosition
|
|
219
|
+
yAxisPosition: AxisPosition
|
|
220
|
+
width: number
|
|
221
|
+
height: number
|
|
222
|
+
}) {
|
|
223
|
+
if ((xAxisPosition === 'bottom' || xAxisPosition === 'top') && (yAxisPosition === 'left' || yAxisPosition === 'right')) {
|
|
224
|
+
return { width, height }
|
|
225
|
+
} else if ((xAxisPosition === 'left' || xAxisPosition === 'right') && (yAxisPosition === 'bottom' || yAxisPosition === 'top')) {
|
|
226
|
+
return {
|
|
227
|
+
width: height,
|
|
228
|
+
height: width
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// export function getTicks (minValue: number, maxValue: number, defaultTicks: number | null) {
|
|
234
|
+
// let valueLength = maxValue - minValue
|
|
235
|
+
// if (defaultTicks === null) {
|
|
236
|
+
// if (valueLength <= 1) {
|
|
237
|
+
// return 1
|
|
238
|
+
// } else {
|
|
239
|
+
// // d3.js自動判斷
|
|
240
|
+
// return null
|
|
241
|
+
// }
|
|
242
|
+
// } else if (valueLength < defaultTicks) {
|
|
243
|
+
// return Math.ceil(valueLength)
|
|
244
|
+
// } else {
|
|
245
|
+
// return defaultTicks
|
|
246
|
+
// }
|
|
247
|
+
// }
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
// 計算預設欄列數量
|
|
252
|
+
// 規則1.rowAmount*columnAmount要大於或等於amount,並且數字要盡可能小
|
|
253
|
+
// 規則2.columnAmount要大於或等於rowAmount,並且數字要盡可能小
|
|
254
|
+
function calcGridDimensions (amount: number): { rowAmount: number; columnAmount: number } {
|
|
255
|
+
let rowAmount = Math.floor(Math.sqrt(amount))
|
|
256
|
+
let columnAmount = Math.ceil(amount / rowAmount)
|
|
257
|
+
while (rowAmount * columnAmount < amount) {
|
|
258
|
+
columnAmount++
|
|
259
|
+
}
|
|
260
|
+
return { rowAmount, columnAmount }
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function calcContainerPosition (layout: Layout, container: Container, amount: number): ContainerPosition[] {
|
|
264
|
+
// const { gap } = container
|
|
265
|
+
const columnGap = container.columnGap === 'auto'
|
|
266
|
+
? layout.left + layout.right
|
|
267
|
+
: container.columnGap
|
|
268
|
+
const rowGap = container.rowGap === 'auto'
|
|
269
|
+
? layout.top + layout.bottom
|
|
270
|
+
: container.rowGap
|
|
271
|
+
const { rowAmount, columnAmount } = (container.rowAmount * container.columnAmount) >= amount
|
|
272
|
+
// 如果container設定的rowAmount和columnAmount的乘積大於或等於amount,則使用目前設定
|
|
273
|
+
? container
|
|
274
|
+
// 否則計算一個合適的預設值
|
|
275
|
+
: calcGridDimensions(amount)
|
|
276
|
+
|
|
277
|
+
return new Array(amount).fill(null).map((_, index) => {
|
|
278
|
+
const columnIndex = index % columnAmount
|
|
279
|
+
const rowIndex = Math.floor(index / columnAmount)
|
|
280
|
+
|
|
281
|
+
const width = (layout.width - (columnGap * (columnAmount - 1))) / columnAmount
|
|
282
|
+
const height = (layout.height - (rowGap * (rowAmount - 1))) / rowAmount
|
|
283
|
+
const x = columnIndex * width + (columnIndex * columnGap)
|
|
284
|
+
const y = rowIndex * height + (rowIndex * rowGap)
|
|
285
|
+
// const translate: [number, number] = [x, y]
|
|
286
|
+
|
|
287
|
+
return {
|
|
288
|
+
slotIndex: index,
|
|
289
|
+
rowIndex,
|
|
290
|
+
columnIndex,
|
|
291
|
+
// translate,
|
|
292
|
+
startX: x,
|
|
293
|
+
startY: y,
|
|
294
|
+
centerX: x + width / 2,
|
|
295
|
+
centerY: y + height / 2,
|
|
296
|
+
width,
|
|
297
|
+
height
|
|
298
|
+
}
|
|
299
|
+
})
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export function calcContainerPositionScaled (layout: Layout, container: Container, amount: number): ContainerPositionScaled[] {
|
|
303
|
+
// const { gap } = container
|
|
304
|
+
const columnGap = container.columnGap === 'auto'
|
|
305
|
+
? layout.left + layout.right
|
|
306
|
+
: container.columnGap
|
|
307
|
+
const rowGap = container.rowGap === 'auto'
|
|
308
|
+
? layout.top + layout.bottom
|
|
309
|
+
: container.rowGap
|
|
310
|
+
const { rowAmount, columnAmount } = (container.rowAmount * container.columnAmount) >= amount
|
|
311
|
+
// 如果container設定的rowAmount和columnAmount的乘積大於或等於amount,則使用目前設定
|
|
312
|
+
? container
|
|
313
|
+
// 否則計算一個合適的預設值
|
|
314
|
+
: calcGridDimensions(amount)
|
|
315
|
+
|
|
316
|
+
return new Array(amount).fill(null).map((_, index) => {
|
|
317
|
+
const columnIndex = index % columnAmount
|
|
318
|
+
const rowIndex = Math.floor(index / columnAmount)
|
|
319
|
+
|
|
320
|
+
const width = (layout.width - (columnGap * (columnAmount - 1))) / columnAmount
|
|
321
|
+
const height = (layout.height - (rowGap * (rowAmount - 1))) / rowAmount
|
|
322
|
+
const x = columnIndex * width + (columnIndex * columnGap)
|
|
323
|
+
const y = rowIndex * height + (rowIndex * rowGap)
|
|
324
|
+
const translate: [number, number] = [x, y]
|
|
325
|
+
const scale: [number, number] = [width / layout.width, height / layout.height]
|
|
326
|
+
|
|
327
|
+
return {
|
|
328
|
+
slotIndex: index,
|
|
329
|
+
rowIndex,
|
|
330
|
+
columnIndex,
|
|
331
|
+
translate,
|
|
332
|
+
scale
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
}
|