@orbcharts/plugins-basic 3.0.0-alpha.62 → 3.0.0-alpha.64
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-plugins-basic.es.js +6117 -6067
- package/dist/orbcharts-plugins-basic.umd.js +10 -10
- package/package.json +2 -2
- package/src/base/BaseGroupAxis.ts +141 -62
- package/src/base/BaseLegend.ts +1 -0
- package/src/base/BaseValueAxis.ts +142 -45
- package/src/grid/defaults.ts +1 -1
- package/src/grid/plugins/GroupAux.ts +31 -28
- package/src/multiGrid/plugins/OverlappingValueAxes.ts +3 -0
- package/src/multiGrid/plugins/OverlappingValueStackAxes.ts +1 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@orbcharts/plugins-basic",
|
3
|
-
"version": "3.0.0-alpha.
|
3
|
+
"version": "3.0.0-alpha.64",
|
4
4
|
"description": "plugins for OrbCharts",
|
5
5
|
"author": "Blue Planet Inc.",
|
6
6
|
"license": "Apache-2.0",
|
@@ -35,7 +35,7 @@
|
|
35
35
|
"vite-plugin-dts": "^3.7.3"
|
36
36
|
},
|
37
37
|
"dependencies": {
|
38
|
-
"@orbcharts/core": "^3.0.0-alpha.
|
38
|
+
"@orbcharts/core": "^3.0.0-alpha.58",
|
39
39
|
"d3": "^7.8.5",
|
40
40
|
"rxjs": "^7.8.1"
|
41
41
|
}
|
@@ -69,33 +69,54 @@ interface TextAlign {
|
|
69
69
|
// const groupingLabelClassName = getClassName(pluginName, 'groupingLabel')
|
70
70
|
const defaultTickSize = 6
|
71
71
|
|
72
|
-
function
|
72
|
+
function renderAxisLabel ({ selection, groupingLabelClassName, fullParams, axisLabelAlign, gridAxesSize, fullDataFormatter, chartParams, textReverseTransform }: {
|
73
73
|
selection: d3.Selection<SVGGElement, any, any, any>,
|
74
|
-
xAxisClassName: string
|
75
74
|
groupingLabelClassName: string
|
76
|
-
|
77
|
-
tickTextAlign: TextAlign
|
75
|
+
fullParams: BaseGroupAxisParams
|
78
76
|
axisLabelAlign: TextAlign
|
79
77
|
gridAxesSize: { width: number, height: number }
|
80
78
|
fullDataFormatter: DataFormatterGrid,
|
81
79
|
chartParams: ChartParams
|
82
|
-
|
83
|
-
groupScale: d3.ScaleLinear<number, number>
|
84
|
-
groupScaleDomain: number[]
|
85
|
-
groupLabels: string[]
|
86
|
-
textTransform: string
|
87
|
-
// tickTextFormatter: string | ((label: any) => string)
|
80
|
+
textReverseTransform: string
|
88
81
|
}) {
|
89
|
-
|
90
|
-
const
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
82
|
+
|
83
|
+
const offsetX = fullParams.tickPadding + fullParams.labelOffset[0]
|
84
|
+
const offsetY = fullParams.tickPadding + fullParams.labelOffset[1]
|
85
|
+
let labelX = 0
|
86
|
+
let labelY = 0
|
87
|
+
if (fullDataFormatter.grid.groupAxis.position === 'bottom') {
|
88
|
+
labelY = offsetY
|
89
|
+
if (fullDataFormatter.grid.valueAxis.position === 'left') {
|
90
|
+
labelX = offsetX
|
91
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'right') {
|
92
|
+
labelX = - offsetX
|
93
|
+
}
|
94
|
+
} else if (fullDataFormatter.grid.groupAxis.position === 'top') {
|
95
|
+
labelY = - offsetY
|
96
|
+
if (fullDataFormatter.grid.valueAxis.position === 'left') {
|
97
|
+
labelX = offsetX
|
98
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'right') {
|
99
|
+
labelX = - offsetX
|
100
|
+
}
|
101
|
+
} else if (fullDataFormatter.grid.groupAxis.position === 'left') {
|
102
|
+
labelX = - offsetX
|
103
|
+
if (fullDataFormatter.grid.valueAxis.position === 'bottom') {
|
104
|
+
labelY = - offsetY
|
105
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'top') {
|
106
|
+
labelY = offsetY
|
107
|
+
}
|
108
|
+
} else if (fullDataFormatter.grid.groupAxis.position === 'right') {
|
109
|
+
labelX = offsetX
|
110
|
+
if (fullDataFormatter.grid.valueAxis.position === 'bottom') {
|
111
|
+
labelY = - offsetY
|
112
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'top') {
|
113
|
+
labelY = offsetY
|
114
|
+
}
|
115
|
+
}
|
95
116
|
|
96
117
|
const axisLabelSelection = selection
|
97
118
|
.selectAll<SVGGElement, BaseGroupAxisParams>(`g.${groupingLabelClassName}`)
|
98
|
-
.data([
|
119
|
+
.data([fullParams])
|
99
120
|
.join('g')
|
100
121
|
.classed(groupingLabelClassName, true)
|
101
122
|
.each((d, i, g) => {
|
@@ -114,34 +135,76 @@ function renderAxis ({ selection, xAxisClassName, groupingLabelClassName, params
|
|
114
135
|
.attr('text-anchor', axisLabelAlign.textAnchor)
|
115
136
|
.attr('dominant-baseline', axisLabelAlign.dominantBaseline)
|
116
137
|
.attr('font-size', chartParams.styles.textSize)
|
117
|
-
.style('fill', getColor(
|
118
|
-
|
138
|
+
.style('fill', getColor(fullParams.labelColorType, chartParams))
|
139
|
+
.style('transform', textReverseTransform)
|
140
|
+
// 偏移使用 x, y 而非 transform 才不會受到外層 scale 變形影響
|
141
|
+
.attr('x', labelX)
|
142
|
+
.attr('y', labelY)
|
119
143
|
.text(d => fullDataFormatter.grid.groupAxis.label)
|
120
144
|
})
|
121
|
-
.attr('transform', d => `translate(${gridAxesSize.width
|
145
|
+
.attr('transform', d => `translate(${gridAxesSize.width}, 0)`)
|
146
|
+
// .attr('transform', d => `translate(${gridAxesSize.width + d.tickPadding + fullParams.labelOffset[0]}, ${- d.tickPadding - fullParams.labelOffset[1]})`)
|
147
|
+
|
148
|
+
}
|
149
|
+
|
150
|
+
function renderAxis ({ selection, xAxisClassName, fullParams, tickTextAlign, gridAxesSize, fullDataFormatter, chartParams, groupScale, groupScaleDomain, groupLabels, textReverseTransformWithRotate }: {
|
151
|
+
selection: d3.Selection<SVGGElement, any, any, any>,
|
152
|
+
xAxisClassName: string
|
153
|
+
fullParams: BaseGroupAxisParams
|
154
|
+
tickTextAlign: TextAlign
|
155
|
+
gridAxesSize: { width: number, height: number }
|
156
|
+
fullDataFormatter: DataFormatterGrid,
|
157
|
+
chartParams: ChartParams
|
158
|
+
groupScale: d3.ScaleLinear<number, number>
|
159
|
+
groupScaleDomain: number[]
|
160
|
+
groupLabels: string[]
|
161
|
+
textReverseTransformWithRotate: string
|
162
|
+
}) {
|
163
|
+
|
164
|
+
const xAxisSelection = selection
|
165
|
+
.selectAll<SVGGElement, BaseGroupAxisParams>(`g.${xAxisClassName}`)
|
166
|
+
.data([fullParams])
|
167
|
+
.join('g')
|
168
|
+
.classed(xAxisClassName, true)
|
122
169
|
|
123
170
|
// 計算所有範圍內groupLabels數量(顯示所有刻度)
|
124
171
|
const allTicksAmount = Math.floor(groupScaleDomain[1]) - Math.ceil(groupScaleDomain[0]) + 1
|
125
172
|
|
173
|
+
// 刻度文字偏移
|
174
|
+
let tickPadding = 0
|
175
|
+
let textX = 0
|
176
|
+
if (fullDataFormatter.grid.groupAxis.position === 'left') {
|
177
|
+
tickPadding = 0
|
178
|
+
textX = - fullParams.tickPadding
|
179
|
+
} else if (fullDataFormatter.grid.groupAxis.position === 'right') {
|
180
|
+
tickPadding = 0
|
181
|
+
textX = fullParams.tickPadding
|
182
|
+
} else if (fullDataFormatter.grid.groupAxis.position === 'bottom') {
|
183
|
+
tickPadding = fullParams.tickPadding
|
184
|
+
textX = 0
|
185
|
+
} else if (fullDataFormatter.grid.groupAxis.position === 'top') {
|
186
|
+
tickPadding = - fullParams.tickPadding
|
187
|
+
textX = - 0
|
188
|
+
}
|
189
|
+
|
126
190
|
// 設定X軸刻度
|
127
|
-
|
128
|
-
const xAxis = d3.axisTop(groupScale)
|
191
|
+
const xAxis = d3.axisBottom(groupScale)
|
129
192
|
.scale(groupScale)
|
130
|
-
.ticks(
|
193
|
+
.ticks(fullParams.ticks === 'all'
|
131
194
|
? allTicksAmount
|
132
|
-
:
|
195
|
+
: fullParams.ticks > allTicksAmount
|
133
196
|
? allTicksAmount // 不顯示超過groupLabels數量的刻度
|
134
|
-
:
|
135
|
-
.tickSize(
|
136
|
-
?
|
137
|
-
: defaultTickSize)
|
197
|
+
: fullParams.ticks)
|
198
|
+
.tickSize(fullParams.tickFullLine == true
|
199
|
+
? gridAxesSize.height
|
200
|
+
: - defaultTickSize)
|
138
201
|
.tickSizeOuter(0)
|
139
202
|
.tickFormat((groupIndex: number) => {
|
140
203
|
// 用index對應到groupLabel
|
141
204
|
const groupLabel = groupLabels[groupIndex] ?? '' // 非整數index不顯示
|
142
|
-
return parseTickFormatValue(groupLabel,
|
205
|
+
return parseTickFormatValue(groupLabel, fullParams.tickFormat)
|
143
206
|
})
|
144
|
-
.tickPadding(
|
207
|
+
.tickPadding(tickPadding)
|
145
208
|
|
146
209
|
const xAxisEl = xAxisSelection
|
147
210
|
.transition()
|
@@ -152,13 +215,13 @@ function renderAxis ({ selection, xAxisClassName, groupingLabelClassName, params
|
|
152
215
|
|
153
216
|
xAxisEl.selectAll('line')
|
154
217
|
.style('fill', 'none')
|
155
|
-
.style('stroke',
|
156
|
-
.style('stroke-dasharray',
|
218
|
+
.style('stroke', fullParams.tickLineVisible == true ? getColor(fullParams.tickColorType, chartParams) : 'none')
|
219
|
+
.style('stroke-dasharray', fullParams.tickFullLineDasharray)
|
157
220
|
.attr('pointer-events', 'none')
|
158
221
|
|
159
222
|
xAxisEl.selectAll('path')
|
160
223
|
.style('fill', 'none')
|
161
|
-
.style('stroke',
|
224
|
+
.style('stroke', fullParams.axisLineVisible == true ? getColor(fullParams.axisLineColorType, chartParams) : 'none')
|
162
225
|
.style('shape-rendering', 'crispEdges')
|
163
226
|
|
164
227
|
// const xText = xAxisEl.selectAll('text')
|
@@ -174,18 +237,22 @@ function renderAxis ({ selection, xAxisClassName, groupingLabelClassName, params
|
|
174
237
|
// .attr('text-anchor', tickTextAlign.textAnchor)
|
175
238
|
// .attr('dominant-baseline', tickTextAlign.dominantBaseline)
|
176
239
|
// .attr('transform-origin', `0 -${params.tickPadding + defaultTickSize}`)
|
177
|
-
// .style('transform',
|
240
|
+
// .style('transform', textReverseTransform)
|
178
241
|
// })
|
179
242
|
const xText = xAxisSelection.selectAll('text')
|
180
243
|
// .style('font-family', 'sans-serif')
|
181
244
|
.attr('font-size', chartParams.styles.textSize)
|
182
245
|
// .style('font-weight', 'bold')
|
183
|
-
.style('color', getColor(
|
246
|
+
.style('color', getColor(fullParams.tickTextColorType, chartParams))
|
184
247
|
.attr('text-anchor', tickTextAlign.textAnchor)
|
185
248
|
.attr('dominant-baseline', tickTextAlign.dominantBaseline)
|
186
|
-
.attr('
|
187
|
-
.style('transform',
|
188
|
-
|
249
|
+
.attr('x', textX)
|
250
|
+
.style('transform', textReverseTransformWithRotate)
|
251
|
+
|
252
|
+
// 抵消掉預設的偏移
|
253
|
+
// if (fullDataFormatter.grid.groupAxis.position === 'left' || fullDataFormatter.grid.groupAxis.position === 'right') {
|
254
|
+
xText.attr('dy', 0)
|
255
|
+
// }
|
189
256
|
|
190
257
|
return xAxisSelection
|
191
258
|
}
|
@@ -297,7 +364,7 @@ export const createBaseGroupAxis: BasePluginFn<BaseGroupAxisContext> = ((pluginN
|
|
297
364
|
// })
|
298
365
|
// )
|
299
366
|
|
300
|
-
// const
|
367
|
+
// const textReverseTransform$: Observable<string> = new Observable(subscriber => {
|
301
368
|
// combineLatest({
|
302
369
|
// params: fullParams$,
|
303
370
|
// gridAxesTransform: gridAxesTransform$
|
@@ -338,31 +405,34 @@ export const createBaseGroupAxis: BasePluginFn<BaseGroupAxisContext> = ((pluginN
|
|
338
405
|
// }
|
339
406
|
// }),
|
340
407
|
// )
|
341
|
-
const
|
342
|
-
fullParams: fullParams$,
|
343
|
-
fullDataFormatter: fullDataFormatter$,
|
408
|
+
const textReverseTransform$ = combineLatest({
|
344
409
|
gridAxesReverseTransform: gridAxesReverseTransform$,
|
345
410
|
gridContainerPosition: gridContainerPosition$
|
346
411
|
}).pipe(
|
347
412
|
takeUntil(destroy$),
|
348
413
|
switchMap(async (d) => d),
|
349
414
|
map(data => {
|
350
|
-
const axisReverseTranslateValue = `translate(${data.gridAxesReverseTransform.translate[0]}px, ${data.gridAxesReverseTransform.translate[1]}px)`
|
351
|
-
const
|
352
|
-
const
|
353
|
-
const
|
354
|
-
|
355
|
-
|
356
|
-
: data.fullParams.tickTextRotate
|
357
|
-
|
358
|
-
const textRotateValue = `rotate(${tickTextRotateDeg}deg)`
|
359
|
-
|
360
|
-
// 必須按照順序(先抵消外層rotate,再抵消最外層scale,最後再做本身的rotate)
|
361
|
-
return `${axisReverseTranslateValue} ${axisReverseRotateValue} ${containerScaleReverseScaleValue} ${textRotateValue}`
|
415
|
+
// const axisReverseTranslateValue = `translate(${data.gridAxesReverseTransform.translate[0]}px, ${data.gridAxesReverseTransform.translate[1]}px)`
|
416
|
+
const axesRotateXYReverseValue = `rotateX(${data.gridAxesReverseTransform.rotateX}deg) rotateY(${data.gridAxesReverseTransform.rotateY}deg)`
|
417
|
+
const axesRotateReverseValue = `rotate(${data.gridAxesReverseTransform.rotate}deg)`
|
418
|
+
const containerScaleReverseValue = `scale(${1 / data.gridContainerPosition[0].scale[0]}, ${1 / data.gridContainerPosition[0].scale[1]})`
|
419
|
+
// 必須按照順序(先抵消外層rotate,再抵消最外層scale)
|
420
|
+
return `${axesRotateXYReverseValue} ${axesRotateReverseValue} ${containerScaleReverseValue}`
|
362
421
|
}),
|
363
422
|
distinctUntilChanged()
|
364
423
|
)
|
365
424
|
|
425
|
+
const textReverseTransformWithRotate$ = combineLatest({
|
426
|
+
textReverseTransform: textReverseTransform$,
|
427
|
+
fullParams: fullParams$,
|
428
|
+
}).pipe(
|
429
|
+
takeUntil(destroy$),
|
430
|
+
switchMap(async (d) => d),
|
431
|
+
map(data => {
|
432
|
+
// 必須按照順序(先抵消外層rotate,再抵消最外層scale,最後再做本身的rotate)
|
433
|
+
return `${data.textReverseTransform} rotate(${data.fullParams.tickTextRotate}deg)`
|
434
|
+
})
|
435
|
+
)
|
366
436
|
|
367
437
|
// 使用pointScale計算非連續性比例尺
|
368
438
|
// const groupScale$: Observable<d3.ScalePoint<string>> = new Observable(subscriber => {
|
@@ -469,7 +539,7 @@ export const createBaseGroupAxis: BasePluginFn<BaseGroupAxisContext> = ((pluginN
|
|
469
539
|
dominantBaseline = 'hanging'
|
470
540
|
} else if (data.fullDataFormatter.grid.groupAxis.position === 'top') {
|
471
541
|
textAnchor = data.fullParams.tickTextRotate
|
472
|
-
? '
|
542
|
+
? 'start'
|
473
543
|
: 'middle'
|
474
544
|
dominantBaseline = 'auto'
|
475
545
|
} else if (data.fullDataFormatter.grid.groupAxis.position === 'left') {
|
@@ -519,7 +589,7 @@ export const createBaseGroupAxis: BasePluginFn<BaseGroupAxisContext> = ((pluginN
|
|
519
589
|
|
520
590
|
combineLatest({
|
521
591
|
axisSelection: axisSelection$,
|
522
|
-
|
592
|
+
fullParams: fullParams$,
|
523
593
|
tickTextAlign: tickTextAlign$,
|
524
594
|
axisLabelAlign: axisLabelAlign$,
|
525
595
|
gridAxesSize: gridAxesSize$,
|
@@ -528,7 +598,8 @@ export const createBaseGroupAxis: BasePluginFn<BaseGroupAxisContext> = ((pluginN
|
|
528
598
|
groupScale: groupScale$,
|
529
599
|
groupScaleDomain: groupScaleDomain$,
|
530
600
|
groupLabels: groupLabels$,
|
531
|
-
|
601
|
+
textReverseTransform: textReverseTransform$,
|
602
|
+
textReverseTransformWithRotate: textReverseTransformWithRotate$,
|
532
603
|
// tickTextFormatter: tickTextFormatter$
|
533
604
|
}).pipe(
|
534
605
|
takeUntil(destroy$),
|
@@ -538,18 +609,26 @@ export const createBaseGroupAxis: BasePluginFn<BaseGroupAxisContext> = ((pluginN
|
|
538
609
|
renderAxis({
|
539
610
|
selection: data.axisSelection,
|
540
611
|
xAxisClassName,
|
541
|
-
|
542
|
-
params: data.params,
|
612
|
+
fullParams: data.fullParams,
|
543
613
|
tickTextAlign: data.tickTextAlign,
|
544
|
-
axisLabelAlign: data.axisLabelAlign,
|
545
614
|
gridAxesSize: data.gridAxesSize,
|
546
615
|
fullDataFormatter: data.fullDataFormatter,
|
547
616
|
chartParams: data.chartParams,
|
548
617
|
groupScale: data.groupScale,
|
549
618
|
groupScaleDomain: data.groupScaleDomain,
|
550
619
|
groupLabels: data.groupLabels,
|
551
|
-
|
552
|
-
|
620
|
+
textReverseTransformWithRotate: data.textReverseTransformWithRotate,
|
621
|
+
})
|
622
|
+
|
623
|
+
renderAxisLabel({
|
624
|
+
selection: data.axisSelection,
|
625
|
+
groupingLabelClassName,
|
626
|
+
fullParams: data.fullParams,
|
627
|
+
axisLabelAlign: data.axisLabelAlign,
|
628
|
+
gridAxesSize: data.gridAxesSize,
|
629
|
+
fullDataFormatter: data.fullDataFormatter,
|
630
|
+
chartParams: data.chartParams,
|
631
|
+
textReverseTransform: data.textReverseTransform,
|
553
632
|
})
|
554
633
|
})
|
555
634
|
|
package/src/base/BaseLegend.ts
CHANGED
@@ -66,26 +66,52 @@ interface TextAlign {
|
|
66
66
|
// const textClassName = getClassName(pluginName, 'text')
|
67
67
|
const defaultTickSize = 6
|
68
68
|
|
69
|
-
function
|
69
|
+
function renderAxisLabel ({ selection, textClassName, fullParams, axisLabelAlign, gridAxesSize, fullDataFormatter, fullChartParams, textReverseTransform }: {
|
70
70
|
selection: d3.Selection<SVGGElement, any, any, any>,
|
71
|
-
yAxisClassName: string
|
72
71
|
textClassName: string
|
73
72
|
fullParams: BaseValueAxisParams
|
74
|
-
tickTextAlign: TextAlign
|
75
73
|
axisLabelAlign: TextAlign
|
76
74
|
gridAxesSize: { width: number, height: number }
|
77
75
|
fullDataFormatter: DataFormatterGrid,
|
78
76
|
fullChartParams: ChartParams
|
79
|
-
|
80
|
-
textTransform: string,
|
81
|
-
minAndMax: [number, number]
|
77
|
+
textReverseTransform: string,
|
82
78
|
}) {
|
83
|
-
|
84
|
-
const
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
.
|
79
|
+
const offsetX = fullParams.tickPadding - fullParams.labelOffset[0]
|
80
|
+
const offsetY = fullParams.tickPadding + fullParams.labelOffset[1]
|
81
|
+
let labelX = 0
|
82
|
+
let labelY = 0
|
83
|
+
if (fullDataFormatter.grid.groupAxis.position === 'bottom') {
|
84
|
+
// labelY = - gridAxesSize.height - offsetY
|
85
|
+
labelY = - offsetY
|
86
|
+
if (fullDataFormatter.grid.valueAxis.position === 'left') {
|
87
|
+
labelX = - offsetX
|
88
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'right') {
|
89
|
+
labelX = offsetX
|
90
|
+
}
|
91
|
+
} else if (fullDataFormatter.grid.groupAxis.position === 'top') {
|
92
|
+
// labelY = gridAxesSize.height + offsetY
|
93
|
+
labelY = offsetY
|
94
|
+
if (fullDataFormatter.grid.valueAxis.position === 'left') {
|
95
|
+
labelX = - offsetX
|
96
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'right') {
|
97
|
+
labelX = offsetX
|
98
|
+
}
|
99
|
+
} else if (fullDataFormatter.grid.groupAxis.position === 'left') {
|
100
|
+
// labelX = gridAxesSize.width + offsetX
|
101
|
+
labelX = offsetX
|
102
|
+
if (fullDataFormatter.grid.valueAxis.position === 'bottom') {
|
103
|
+
labelY = offsetY
|
104
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'top') {
|
105
|
+
labelY = - offsetY
|
106
|
+
}
|
107
|
+
} else if (fullDataFormatter.grid.groupAxis.position === 'right') {
|
108
|
+
labelX = - offsetX
|
109
|
+
if (fullDataFormatter.grid.valueAxis.position === 'bottom') {
|
110
|
+
labelY = offsetY
|
111
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'top') {
|
112
|
+
labelY = - offsetY
|
113
|
+
}
|
114
|
+
}
|
89
115
|
|
90
116
|
const axisLabelSelection = selection
|
91
117
|
.selectAll<SVGGElement, BaseValueAxisParams>(`g.${textClassName}`)
|
@@ -109,10 +135,36 @@ function renderAxis ({ selection, yAxisClassName, textClassName, fullParams, tic
|
|
109
135
|
.attr('dominant-baseline', axisLabelAlign.dominantBaseline)
|
110
136
|
.attr('font-size', fullChartParams.styles.textSize)
|
111
137
|
.style('fill', getColor(fullParams.labelColorType, fullChartParams))
|
112
|
-
|
138
|
+
.style('transform', textReverseTransform)
|
139
|
+
// 偏移使用 x, y 而非 transform 才不會受到外層 scale 變形影響
|
140
|
+
.attr('x', labelX)
|
141
|
+
.attr('y', labelY)
|
113
142
|
.text(d => fullDataFormatter.grid.valueAxis.label)
|
114
143
|
})
|
115
|
-
.attr('transform', d => `translate(
|
144
|
+
.attr('transform', d => `translate(0, ${gridAxesSize.height})`)
|
145
|
+
// .attr('transform', d => `translate(${- fullParams.tickPadding + fullParams.labelOffset[0]}, ${gridAxesSize.height + fullParams.tickPadding + fullParams.labelOffset[1]})`)
|
146
|
+
|
147
|
+
|
148
|
+
}
|
149
|
+
|
150
|
+
function renderAxis ({ selection, yAxisClassName, fullParams, tickTextAlign, gridAxesSize, fullDataFormatter, fullChartParams, valueScale, textReverseTransformWithRotate, minAndMax }: {
|
151
|
+
selection: d3.Selection<SVGGElement, any, any, any>,
|
152
|
+
yAxisClassName: string
|
153
|
+
fullParams: BaseValueAxisParams
|
154
|
+
tickTextAlign: TextAlign
|
155
|
+
gridAxesSize: { width: number, height: number }
|
156
|
+
fullDataFormatter: DataFormatterGrid,
|
157
|
+
fullChartParams: ChartParams
|
158
|
+
valueScale: d3.ScaleLinear<number, number>
|
159
|
+
textReverseTransformWithRotate: string,
|
160
|
+
minAndMax: [number, number]
|
161
|
+
}) {
|
162
|
+
|
163
|
+
const yAxisSelection = selection
|
164
|
+
.selectAll<SVGGElement, BaseValueAxisParams>(`g.${yAxisClassName}`)
|
165
|
+
.data([fullParams])
|
166
|
+
.join('g')
|
167
|
+
.classed(yAxisClassName, true)
|
116
168
|
|
117
169
|
const valueLength = minAndMax[1] - minAndMax[0]
|
118
170
|
|
@@ -120,6 +172,23 @@ function renderAxis ({ selection, yAxisClassName, textClassName, fullParams, tic
|
|
120
172
|
// .domain([0, 150])
|
121
173
|
// .range([416.5, 791.349])
|
122
174
|
|
175
|
+
// 刻度文字偏移
|
176
|
+
let tickPadding = 0
|
177
|
+
let textY = 0
|
178
|
+
if (fullDataFormatter.grid.valueAxis.position === 'left') {
|
179
|
+
tickPadding = fullParams.tickPadding
|
180
|
+
textY = 0
|
181
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'right') {
|
182
|
+
tickPadding = - fullParams.tickPadding
|
183
|
+
textY = 0
|
184
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'bottom') {
|
185
|
+
tickPadding = 0
|
186
|
+
textY = fullParams.tickPadding
|
187
|
+
} else if (fullDataFormatter.grid.valueAxis.position === 'top') {
|
188
|
+
tickPadding = 0
|
189
|
+
textY = - fullParams.tickPadding
|
190
|
+
}
|
191
|
+
|
123
192
|
// 設定Y軸刻度
|
124
193
|
const yAxis = d3.axisLeft(valueScale)
|
125
194
|
.scale(valueScale)
|
@@ -132,7 +201,7 @@ function renderAxis ({ selection, yAxisClassName, textClassName, fullParams, tic
|
|
132
201
|
.tickSize(fullParams.tickFullLine == true
|
133
202
|
? -gridAxesSize.width
|
134
203
|
: defaultTickSize)
|
135
|
-
.tickPadding(
|
204
|
+
.tickPadding(tickPadding)
|
136
205
|
|
137
206
|
const yAxisEl = yAxisSelection
|
138
207
|
.transition()
|
@@ -158,8 +227,14 @@ function renderAxis ({ selection, yAxisClassName, textClassName, fullParams, tic
|
|
158
227
|
.style('color', getColor(fullParams.tickTextColorType, fullChartParams))
|
159
228
|
.attr('text-anchor', tickTextAlign.textAnchor)
|
160
229
|
.attr('dominant-baseline', tickTextAlign.dominantBaseline)
|
161
|
-
.attr('
|
162
|
-
|
230
|
+
// .attr('dy', 0)
|
231
|
+
.attr('y', textY)
|
232
|
+
yText.style('transform', textReverseTransformWithRotate)
|
233
|
+
|
234
|
+
// 抵消掉預設的偏移
|
235
|
+
if (fullDataFormatter.grid.valueAxis.position === 'bottom' || fullDataFormatter.grid.valueAxis.position === 'top') {
|
236
|
+
yText.attr('dy', 0)
|
237
|
+
}
|
163
238
|
|
164
239
|
return yAxisSelection
|
165
240
|
}
|
@@ -263,7 +338,7 @@ export const createBaseValueAxis: BasePluginFn<BaseLinesContext> = (pluginName:
|
|
263
338
|
// layout$
|
264
339
|
// })
|
265
340
|
|
266
|
-
// const
|
341
|
+
// const textReverseTransform$: Observable<string> = new Observable(subscriber => {
|
267
342
|
// combineLatest({
|
268
343
|
// fullParams: fullParams$,
|
269
344
|
// layout: layout$
|
@@ -304,31 +379,35 @@ export const createBaseValueAxis: BasePluginFn<BaseLinesContext> = (pluginName:
|
|
304
379
|
// }
|
305
380
|
// }),
|
306
381
|
// )
|
307
|
-
const
|
308
|
-
fullParams: fullParams$,
|
309
|
-
fullDataFormatter: fullDataFormatter$,
|
382
|
+
const textReverseTransform$ = combineLatest({
|
310
383
|
gridAxesReverseTransform: gridAxesReverseTransform$,
|
311
384
|
gridContainerPosition: gridContainerPosition$
|
312
385
|
}).pipe(
|
313
386
|
takeUntil(destroy$),
|
314
387
|
switchMap(async (d) => d),
|
315
388
|
map(data => {
|
316
|
-
const axisReverseTranslateValue = `translate(${data.gridAxesReverseTransform.translate[0]}px, ${data.gridAxesReverseTransform.translate[1]}px)`
|
317
|
-
const
|
318
|
-
const
|
319
|
-
const
|
320
|
-
|
321
|
-
|
322
|
-
: data.fullParams.tickTextRotate
|
323
|
-
|
324
|
-
const textRotateValue = `rotate(${tickTextRotateDeg}deg)`
|
325
|
-
|
326
|
-
// 必須按照順序(先抵消外層rotate,再抵消最外層scale,最後再做本身的rotate)
|
327
|
-
return `${axisReverseTranslateValue} ${axisReverseRotateValue} ${containerScaleReverseScaleValue} ${textRotateValue}`
|
389
|
+
// const axisReverseTranslateValue = `translate(${data.gridAxesReverseTransform.translate[0]}px, ${data.gridAxesReverseTransform.translate[1]}px)`
|
390
|
+
const axesRotateXYReverseValue = `rotateX(${data.gridAxesReverseTransform.rotateX}deg) rotateY(${data.gridAxesReverseTransform.rotateY}deg)`
|
391
|
+
const axesRotateReverseValue = `rotate(${data.gridAxesReverseTransform.rotate}deg)`
|
392
|
+
const containerScaleReverseValue = `scale(${1 / data.gridContainerPosition[0].scale[0]}, ${1 / data.gridContainerPosition[0].scale[1]})`
|
393
|
+
// 必須按照順序(先抵消外層rotate,再抵消最外層scale)
|
394
|
+
return `${axesRotateXYReverseValue} ${axesRotateReverseValue} ${containerScaleReverseValue}`
|
328
395
|
}),
|
329
396
|
distinctUntilChanged()
|
330
397
|
)
|
331
398
|
|
399
|
+
const textReverseTransformWithRotate$ = combineLatest({
|
400
|
+
textReverseTransform: textReverseTransform$,
|
401
|
+
fullParams: fullParams$,
|
402
|
+
}).pipe(
|
403
|
+
takeUntil(destroy$),
|
404
|
+
switchMap(async (d) => d),
|
405
|
+
map(data => {
|
406
|
+
// 必須按照順序(先抵消外層rotate,再抵消最外層scale,最後再做本身的rotate)
|
407
|
+
return `${data.textReverseTransform} rotate(${data.fullParams.tickTextRotate}deg)`
|
408
|
+
})
|
409
|
+
)
|
410
|
+
|
332
411
|
const minAndMax$: Observable<[number, number]> = new Observable(subscriber => {
|
333
412
|
combineLatest({
|
334
413
|
fullDataFormatter: fullDataFormatter$,
|
@@ -383,23 +462,31 @@ export const createBaseValueAxis: BasePluginFn<BaseLinesContext> = (pluginName:
|
|
383
462
|
})
|
384
463
|
})
|
385
464
|
|
386
|
-
const tickTextAlign$: Observable<TextAlign> =
|
465
|
+
const tickTextAlign$: Observable<TextAlign> = combineLatest({
|
466
|
+
fullDataFormatter: fullDataFormatter$,
|
467
|
+
fullParams: fullParams$
|
468
|
+
}).pipe(
|
387
469
|
takeUntil(destroy$),
|
388
|
-
|
470
|
+
switchMap(async (d) => d),
|
471
|
+
map(data => {
|
389
472
|
let textAnchor: 'start' | 'middle' | 'end' = 'start'
|
390
473
|
let dominantBaseline: 'auto' | 'middle' | 'hanging' = 'hanging'
|
391
474
|
|
392
|
-
if (
|
475
|
+
if (data.fullDataFormatter.grid.valueAxis.position === 'left') {
|
393
476
|
textAnchor = 'end'
|
394
477
|
dominantBaseline = 'middle'
|
395
|
-
} else if (
|
478
|
+
} else if (data.fullDataFormatter.grid.valueAxis.position === 'right') {
|
396
479
|
textAnchor = 'start'
|
397
480
|
dominantBaseline = 'middle'
|
398
|
-
} else if (
|
399
|
-
textAnchor =
|
481
|
+
} else if (data.fullDataFormatter.grid.valueAxis.position === 'bottom') {
|
482
|
+
textAnchor = data.fullParams.tickTextRotate
|
483
|
+
? 'end'
|
484
|
+
: 'middle'
|
400
485
|
dominantBaseline = 'hanging'
|
401
|
-
} else if (
|
402
|
-
textAnchor =
|
486
|
+
} else if (data.fullDataFormatter.grid.valueAxis.position === 'top') {
|
487
|
+
textAnchor = data.fullParams.tickTextRotate
|
488
|
+
? 'start'
|
489
|
+
: 'middle'
|
403
490
|
dominantBaseline = 'auto'
|
404
491
|
}
|
405
492
|
return {
|
@@ -451,7 +538,8 @@ export const createBaseValueAxis: BasePluginFn<BaseLinesContext> = (pluginName:
|
|
451
538
|
fullDataFormatter: fullDataFormatter$,
|
452
539
|
fullChartParams: fullChartParams$,
|
453
540
|
valueScale: valueScale$,
|
454
|
-
|
541
|
+
textReverseTransform: textReverseTransform$,
|
542
|
+
textReverseTransformWithRotate: textReverseTransformWithRotate$,
|
455
543
|
minAndMax: minAndMax$
|
456
544
|
}).pipe(
|
457
545
|
takeUntil(destroy$),
|
@@ -461,17 +549,26 @@ export const createBaseValueAxis: BasePluginFn<BaseLinesContext> = (pluginName:
|
|
461
549
|
renderAxis({
|
462
550
|
selection: data.axisSelection,
|
463
551
|
yAxisClassName,
|
464
|
-
textClassName,
|
465
552
|
fullParams: data.fullParams,
|
466
553
|
tickTextAlign: data.tickTextAlign,
|
467
|
-
axisLabelAlign: data.axisLabelAlign,
|
468
554
|
gridAxesSize: data.gridAxesSize,
|
469
555
|
fullDataFormatter: data.fullDataFormatter,
|
470
556
|
fullChartParams: data.fullChartParams,
|
471
557
|
valueScale: data.valueScale,
|
472
|
-
|
558
|
+
textReverseTransformWithRotate: data.textReverseTransformWithRotate,
|
473
559
|
minAndMax: data.minAndMax
|
474
560
|
})
|
561
|
+
|
562
|
+
renderAxisLabel({
|
563
|
+
selection: data.axisSelection,
|
564
|
+
textClassName,
|
565
|
+
fullParams: data.fullParams,
|
566
|
+
axisLabelAlign: data.axisLabelAlign,
|
567
|
+
gridAxesSize: data.gridAxesSize,
|
568
|
+
fullDataFormatter: data.fullDataFormatter,
|
569
|
+
fullChartParams: data.fullChartParams,
|
570
|
+
textReverseTransform: data.textReverseTransform,
|
571
|
+
})
|
475
572
|
})
|
476
573
|
|
477
574
|
return () => {
|
package/src/grid/defaults.ts
CHANGED
@@ -39,7 +39,7 @@ export const DEFAULT_GROUP_AREA_PARAMS: GroupAuxParams = {
|
|
39
39
|
labelColorType: 'primary',
|
40
40
|
labelTextColorType: 'background',
|
41
41
|
labelTextFormat: text => text,
|
42
|
-
labelPadding:
|
42
|
+
labelPadding: 20,
|
43
43
|
labelRotate: 0
|
44
44
|
}
|
45
45
|
DEFAULT_GROUP_AREA_PARAMS.labelTextFormat.toString = () => `text => text`
|