@orbcharts/plugins-basic 3.0.0-alpha.63 → 3.0.0-alpha.65

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.
@@ -31,6 +31,7 @@ interface BaseGroupAxisContext {
31
31
  }>;
32
32
  gridContainerPosition$: Observable<GridContainerPosition[]>;
33
33
  isSeriesSeprate$: Observable<boolean>;
34
+ textSizePx$: Observable<number>;
34
35
  }
35
36
  export declare const createBaseGroupAxis: BasePluginFn<BaseGroupAxisContext>;
36
37
  export {};
@@ -1,4 +1,3 @@
1
1
  export * from './defaults';
2
2
  export * from './types';
3
- export { Container } from './plugins/Container';
4
3
  export { Tooltip } from './plugins/Tooltip';
@@ -19,6 +19,6 @@ export type TooltipParams = {
19
19
  textColorType: ColorType;
20
20
  offset: [number, number];
21
21
  padding: number;
22
- textRenderFn: <T extends ChartType>(eventData: EventTypeMap<T>) => string[];
22
+ textRenderFn: <T extends ChartType>(eventData: EventTypeMap<T>) => string[] | string | null;
23
23
  svgRenderFn: (<T extends ChartType>(eventData: EventTypeMap<T>) => string) | null;
24
24
  };
@@ -21,6 +21,8 @@ export interface PieParams {
21
21
  startAngle: number;
22
22
  endAngle: number;
23
23
  padAngle: number;
24
+ strokeColorType: ColorType;
25
+ strokeWidth: number;
24
26
  cornerRadius: number;
25
27
  }
26
28
  export interface PieEventTextsParams {
@@ -43,9 +45,12 @@ export interface PieLabelsParams {
43
45
  }
44
46
  export interface RoseParams {
45
47
  outerRadius: number;
48
+ padAngle: number;
49
+ strokeColorType: ColorType;
50
+ strokeWidth: number;
46
51
  cornerRadius: number;
47
52
  arcScaleType: ArcScaleType;
48
- mouseoverAngleIncrease: number;
53
+ angleIncreaseWhileHighlight: number;
49
54
  }
50
55
  export interface RoseLabelsParams {
51
56
  outerRadius: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orbcharts/plugins-basic",
3
- "version": "3.0.0-alpha.63",
3
+ "version": "3.0.0-alpha.65",
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.58",
38
+ "@orbcharts/core": "^3.0.0-alpha.59",
39
39
  "d3": "^7.8.5",
40
40
  "rxjs": "^7.8.1"
41
41
  }
@@ -55,6 +55,7 @@ interface BaseGroupAxisContext {
55
55
  }>
56
56
  gridContainerPosition$: Observable<GridContainerPosition[]>
57
57
  isSeriesSeprate$: Observable<boolean>
58
+ textSizePx$: Observable<number>
58
59
  }
59
60
 
60
61
  interface TextAlign {
@@ -147,7 +148,7 @@ function renderAxisLabel ({ selection, groupingLabelClassName, fullParams, axisL
147
148
 
148
149
  }
149
150
 
150
- function renderAxis ({ selection, xAxisClassName, fullParams, tickTextAlign, gridAxesSize, fullDataFormatter, chartParams, groupScale, groupScaleDomain, groupLabels, textReverseTransformWithRotate }: {
151
+ function renderAxis ({ selection, xAxisClassName, fullParams, tickTextAlign, gridAxesSize, fullDataFormatter, chartParams, groupScale, groupScaleDomain, groupLabels, textReverseTransformWithRotate, textSizePx }: {
151
152
  selection: d3.Selection<SVGGElement, any, any, any>,
152
153
  xAxisClassName: string
153
154
  fullParams: BaseGroupAxisParams
@@ -159,6 +160,7 @@ function renderAxis ({ selection, xAxisClassName, fullParams, tickTextAlign, gri
159
160
  groupScaleDomain: number[]
160
161
  groupLabels: string[]
161
162
  textReverseTransformWithRotate: string
163
+ textSizePx: number
162
164
  }) {
163
165
 
164
166
  const xAxisSelection = selection
@@ -209,9 +211,34 @@ function renderAxis ({ selection, xAxisClassName, fullParams, tickTextAlign, gri
209
211
  const xAxisEl = xAxisSelection
210
212
  .transition()
211
213
  .duration(100)
212
- .call(xAxis)
213
- // .attr('text-anchor', () => params.tickTextRotate !== false ? 'end' : 'middle')
214
- // .attr('text-anchor', () => 'middle')
214
+ .call(xAxis)
215
+ .on('end', (self, t) => {
216
+ // 先等transition結束再處理文字,否則會被原本的文字覆蓋
217
+ xAxisEl
218
+ .selectAll('.tick text')
219
+ .each((d, groupIndex, n) => {
220
+ // -- 將原本單行文字改為多行文字 --
221
+ const groupLabel = groupLabels[groupIndex] ?? '' // 非整數index不顯示
222
+ const groupLabelTspans = groupLabel.split('\n')
223
+ const textSelection = d3.select(n[groupIndex])
224
+ .text(null) // 先清空原本的 text
225
+
226
+ const textX = Number(textSelection.attr('x'))
227
+ let textY = Number(textSelection.attr('y'))
228
+ if (fullDataFormatter.grid.groupAxis.position === 'top') {
229
+ // 當文字在上方時,要往上偏移第一行的高度
230
+ textY -= (groupLabelTspans.length - 1) * textSizePx
231
+ }
232
+
233
+ textSelection
234
+ .selectAll('tspan')
235
+ .data(groupLabelTspans)
236
+ .join('tspan')
237
+ .attr('x', textX)
238
+ .attr('y', (_d, _i) => textY + _i * textSizePx)
239
+ .text(d => d)
240
+ })
241
+ })
215
242
 
216
243
  xAxisEl.selectAll('line')
217
244
  .style('fill', 'none')
@@ -224,22 +251,7 @@ function renderAxis ({ selection, xAxisClassName, fullParams, tickTextAlign, gri
224
251
  .style('stroke', fullParams.axisLineVisible == true ? getColor(fullParams.axisLineColorType, chartParams) : 'none')
225
252
  .style('shape-rendering', 'crispEdges')
226
253
 
227
- // const xText = xAxisEl.selectAll('text')
228
- // xAxisSelection.each((d, i, g) => {
229
- // d3.select(g[i])
230
- // .selectAll('text')
231
- // .data([d])
232
- // .join('text')
233
- // .style('font-family', 'sans-serif')
234
- // .style('font-size', `${chartParams.styles.textSize}px`)
235
- // // .style('font-weight', 'bold')
236
- // .style('color', getColor(params.tickTextColorType, chartParams))
237
- // .attr('text-anchor', tickTextAlign.textAnchor)
238
- // .attr('dominant-baseline', tickTextAlign.dominantBaseline)
239
- // .attr('transform-origin', `0 -${params.tickPadding + defaultTickSize}`)
240
- // .style('transform', textReverseTransform)
241
- // })
242
- const xText = xAxisSelection.selectAll('text')
254
+ const xText = xAxisSelection.selectAll<SVGTextElement, BaseGroupAxisParams>('text')
243
255
  // .style('font-family', 'sans-serif')
244
256
  .attr('font-size', chartParams.styles.textSize)
245
257
  // .style('font-weight', 'bold')
@@ -269,6 +281,7 @@ export const createBaseGroupAxis: BasePluginFn<BaseGroupAxisContext> = ((pluginN
269
281
  gridAxesSize$,
270
282
  gridContainerPosition$,
271
283
  isSeriesSeprate$,
284
+ textSizePx$,
272
285
  }) => {
273
286
 
274
287
  const destroy$ = new Subject()
@@ -600,6 +613,7 @@ export const createBaseGroupAxis: BasePluginFn<BaseGroupAxisContext> = ((pluginN
600
613
  groupLabels: groupLabels$,
601
614
  textReverseTransform: textReverseTransform$,
602
615
  textReverseTransformWithRotate: textReverseTransformWithRotate$,
616
+ textSizePx: textSizePx$
603
617
  // tickTextFormatter: tickTextFormatter$
604
618
  }).pipe(
605
619
  takeUntil(destroy$),
@@ -618,6 +632,7 @@ export const createBaseGroupAxis: BasePluginFn<BaseGroupAxisContext> = ((pluginN
618
632
  groupScaleDomain: data.groupScaleDomain,
619
633
  groupLabels: data.groupLabels,
620
634
  textReverseTransformWithRotate: data.textReverseTransformWithRotate,
635
+ textSizePx: data.textSizePx
621
636
  })
622
637
 
623
638
  renderAxisLabel({
@@ -637,6 +637,7 @@ export const createBaseLegend: BasePluginFn<BaseLegendContext> = (pluginName: st
637
637
  itemSelection$.subscribe()
638
638
 
639
639
  return () => {
640
+ rootSelection.select(`g.${rootPositionClassName}`).remove()
640
641
  destroy$.next(undefined)
641
642
  }
642
643
  }
@@ -27,6 +27,7 @@ export const GroupAxis = defineGridPlugin(pluginName, DEFAULT_GROUP_AXIS_PARAMS)
27
27
  gridAxesSize$: observer.gridAxesSize$,
28
28
  gridContainerPosition$: observer.gridContainerPosition$,
29
29
  isSeriesSeprate$: observer.isSeriesSeprate$,
30
+ textSizePx$: observer.textSizePx$,
30
31
  })
31
32
 
32
33
  return () => {
@@ -58,6 +58,7 @@ export const MultiGroupAxis = defineMultiGridPlugin(pluginName, DEFAULT_MULTI_GR
58
58
  gridAxesSize$: d.gridAxesSize$,
59
59
  gridContainerPosition$: d.gridContainerPosition$,
60
60
  isSeriesSeprate$,
61
+ textSizePx$: observer.textSizePx$,
61
62
  })
62
63
  })
63
64
  })
@@ -47,6 +47,7 @@ export const OverlappingValueAxes = defineMultiGridPlugin(pluginName, DEFAULT_OV
47
47
  takeUntil(destroy$),
48
48
  switchMap(async (d) => d),
49
49
  map(data => {
50
+ console.log('data', data)
50
51
  if (!data.fullDataFormatter.gridList[data.secondGridIndex]) {
51
52
  data.fullDataFormatter.gridList[data.secondGridIndex] = Object.assign({}, data.fullDataFormatter.gridList[data.firstGridIndex])
52
53
  }
@@ -62,6 +63,7 @@ export const OverlappingValueAxes = defineMultiGridPlugin(pluginName, DEFAULT_OV
62
63
  } else if (position === 'right') {
63
64
  reversePosition = 'left'
64
65
  }
66
+ // console.log('reversePosition', reversePosition)
65
67
  return <DataFormatterGrid>{
66
68
  type: 'grid',
67
69
  visibleFilter: data.fullDataFormatter.visibleFilter as any,
@@ -116,6 +118,7 @@ export const OverlappingValueAxes = defineMultiGridPlugin(pluginName, DEFAULT_OV
116
118
  })
117
119
  return {
118
120
  ...observables,
121
+ dataFormatter$: secondGridDataFormatter$,
119
122
  gridAxesTransform$,
120
123
  gridAxesReverseTransform$,
121
124
  gridContainerPosition$,
@@ -117,6 +117,7 @@ export const OverlappingValueStackAxes = defineMultiGridPlugin(pluginName, DEFAU
117
117
  })
118
118
  return {
119
119
  ...observables,
120
+ dataFormatter$: secondGridDataFormatter$,
120
121
  gridAxesTransform$,
121
122
  gridAxesReverseTransform$,
122
123
  gridContainerPosition$,
@@ -1,4 +1,4 @@
1
1
  export * from './defaults'
2
2
  export * from './types'
3
- export { Container } from './plugins/Container'
3
+ // export { Container } from './plugins/Container'
4
4
  export { Tooltip } from './plugins/Tooltip'
@@ -34,15 +34,32 @@ const pluginName = 'Tooltip'
34
34
  const gClassName = getClassName(pluginName, 'g')
35
35
  const boxClassName = getClassName(pluginName, 'box')
36
36
 
37
- function textToSvg (textArr: string[], textStyle: TooltipStyle) {
37
+ function textToSvg (_textArr: string[] | string | null | undefined, textStyle: TooltipStyle) {
38
38
  const lineHeight = textStyle.textSizePx * 1.5
39
- return textArr
39
+
40
+ const textArr = _textArr == null
41
+ ? []
42
+ : Array.isArray(_textArr)
43
+ ? _textArr
44
+ : typeof _textArr === 'string'
45
+ ? _textArr.split('\n')
46
+ : [_textArr]
47
+
48
+ const tspan = textArr
40
49
  .filter(d => d != '')
41
50
  .map((text, i) => {
42
51
  const top = i * lineHeight
43
- return `<text font-size="${textStyle.textSize}" fill="${textStyle.textColor}" x="0" y="${top}" style="dominant-baseline:text-before-edge">${text}</text>`
52
+ return `<tspan x="0" y="${top}">${text}</tspan>`
44
53
  })
45
- .join()
54
+ .join('')
55
+
56
+ if (tspan) {
57
+ return `<text font-size="${textStyle.textSize}" fill="${textStyle.textColor}" x="0" y="0" style="dominant-baseline:text-before-edge">
58
+ ${tspan}
59
+ </text>`
60
+ } else {
61
+ return ''
62
+ }
46
63
  }
47
64
 
48
65
  function renderTooltip ({ rootSelection, pluginName, rootWidth, rootHeight, svgString, tooltipStyle, event }: {
@@ -234,14 +251,14 @@ export const Tooltip: PluginConstructor<any, string, any> = defineNoneDataPlugin
234
251
  }).pipe(
235
252
  takeUntil(destroy$),
236
253
  switchMap(async d => d),
237
- map(d => {
238
- if (d.fullParams.svgRenderFn) {
239
- return d.fullParams.svgRenderFn
254
+ map(data => {
255
+ if (data.fullParams.svgRenderFn) {
256
+ return data.fullParams.svgRenderFn
240
257
  }
241
258
  // 將textRenderFn回傳的資料使用<text>包裝起來
242
259
  return (eventData: EventTypeMap<any>) => {
243
- const textArr = d.fullParams.textRenderFn(eventData as any)
244
- return textToSvg(textArr, d.tooltipStyle)
260
+ const textArr = data.fullParams.textRenderFn(eventData as any)
261
+ return textToSvg(textArr, data.tooltipStyle)
245
262
  }
246
263
  })
247
264
  )
@@ -20,7 +20,7 @@ export type TooltipParams = {
20
20
  textColorType: ColorType
21
21
  offset: [number, number]
22
22
  padding: number
23
- textRenderFn: <T extends ChartType> (eventData: EventTypeMap<T>) => string[]
23
+ textRenderFn: <T extends ChartType> (eventData: EventTypeMap<T>) => string[] | string | null
24
24
  svgRenderFn: (<T extends ChartType> (eventData: EventTypeMap<T>) => string) | null
25
25
  }
26
26
 
@@ -31,14 +31,16 @@ export const DEFAULT_PIE_PARAMS: PieParams = {
31
31
  // bottom: 50,
32
32
  // left: 70
33
33
  // },
34
- outerRadius: 0.95,
34
+ outerRadius: 0.85,
35
35
  innerRadius: 0,
36
- outerRadiusWhileHighlight: 1,
36
+ outerRadiusWhileHighlight: 0.9,
37
37
  // label?: LabelStyle
38
38
  // enterDuration: 800,
39
39
  startAngle: 0,
40
40
  endAngle: Math.PI * 2,
41
- padAngle: 0.02,
41
+ padAngle: 0,
42
+ strokeColorType: 'background',
43
+ strokeWidth: 1,
42
44
  // padRadius: 100,
43
45
  cornerRadius: 0,
44
46
  // highlightTarget: 'datum',
@@ -99,13 +101,13 @@ DEFAULT_PIE_EVENT_TEXTS_PARAMS.eventFn.toString = () => `(eventData: EventSeries
99
101
  export const DEFAULT_PIE_LABELS_PARAMS: PieLabelsParams = {
100
102
  // solidColor: undefined,
101
103
  // colors: DEFAULT_COLORS,
102
- outerRadius: 0.95,
103
- outerRadiusWhileHighlight: 1,
104
+ outerRadius: 0.85,
105
+ outerRadiusWhileHighlight: 0.9,
104
106
  // innerRadius: 0,
105
107
  // enterDuration: 800,
106
108
  startAngle: 0,
107
109
  endAngle: Math.PI * 2,
108
- labelCentroid: 2.3,
110
+ labelCentroid: 2.1,
109
111
  // fontSize: 12,
110
112
  labelColorType: 'primary',
111
113
  labelFn: d => String(d.label),
@@ -113,15 +115,18 @@ export const DEFAULT_PIE_LABELS_PARAMS: PieLabelsParams = {
113
115
  DEFAULT_PIE_LABELS_PARAMS.labelFn.toString = () => `d => String(d.label)`
114
116
 
115
117
  export const DEFAULT_ROSE_PARAMS: RoseParams = {
116
- outerRadius: 0.95,
118
+ outerRadius: 0.85,
119
+ padAngle: 0,
120
+ strokeColorType: 'background',
121
+ strokeWidth: 0,
117
122
  cornerRadius: 0,
118
123
  arcScaleType: 'area',
119
- mouseoverAngleIncrease: 0.05
124
+ angleIncreaseWhileHighlight: 0.05
120
125
  }
121
126
 
122
127
  export const DEFAULT_ROSE_LABELS_PARAMS: RoseLabelsParams = {
123
- outerRadius: 0.95,
124
- labelCentroid: 2.5,
128
+ outerRadius: 0.85,
129
+ labelCentroid: 2.1,
125
130
  labelFn: d => String(d.label),
126
131
  labelColorType: 'primary',
127
132
  arcScaleType: 'area'
@@ -22,7 +22,7 @@ import {
22
22
  import { DEFAULT_PIE_PARAMS } from '../defaults'
23
23
  import { makePieData } from '../seriesUtils'
24
24
  import { getD3TransitionEase, makeD3Arc } from '../../utils/d3Utils'
25
- import { getClassName } from '../../utils/orbchartsUtils'
25
+ import { getDatumColor, getClassName } from '../../utils/orbchartsUtils'
26
26
  import { seriesCenterSelectionObservable } from '../seriesObservables'
27
27
 
28
28
 
@@ -87,11 +87,13 @@ function makePieRenderData (data: PieDatum[], startAngle: number, endAngle: numb
87
87
  })
88
88
  }
89
89
 
90
- function renderPie ({ selection, data, arc, pathClassName }: {
90
+ function renderPie ({ selection, data, arc, pathClassName, fullParams, fullChartParams }: {
91
91
  selection: d3.Selection<SVGGElement, unknown, any, unknown>
92
92
  data: PieDatum[]
93
93
  arc: d3.Arc<any, d3.DefaultArcObject>
94
94
  pathClassName: string
95
+ fullParams: PieParams
96
+ fullChartParams: ChartParams
95
97
  }): d3.Selection<SVGPathElement, PieDatum, any, any> {
96
98
  // console.log('data', data)
97
99
  const pathSelection: d3.Selection<SVGPathElement, PieDatum, any, any> = selection
@@ -101,6 +103,8 @@ function renderPie ({ selection, data, arc, pathClassName }: {
101
103
  .classed(pathClassName, true)
102
104
  .style('cursor', 'pointer')
103
105
  .attr('fill', (d, i) => d.data.color)
106
+ .attr('stroke', (d, i) => getDatumColor({ datum: d.data, colorType: fullParams.strokeColorType, fullChartParams }))
107
+ .attr('stroke-width', fullParams.strokeWidth)
104
108
  .attr('d', (d, i) => {
105
109
  return arc!(d as any)
106
110
  })
@@ -312,7 +316,9 @@ function createEachPie (pluginName: string, context: {
312
316
  selection: context.containerSelection,
313
317
  data: tweenData,
314
318
  arc: data.arc,
315
- pathClassName
319
+ pathClassName,
320
+ fullParams: data.fullParams,
321
+ fullChartParams: data.fullChartParams,
316
322
  })
317
323
 
318
324
  // @Q@ 想盡量減清效能負擔所以取消掉
@@ -345,7 +351,9 @@ function createEachPie (pluginName: string, context: {
345
351
  selection: context.containerSelection,
346
352
  data: tweenData,
347
353
  arc: data.arc,
348
- pathClassName
354
+ pathClassName,
355
+ fullParams: data.fullParams,
356
+ fullChartParams: data.fullChartParams,
349
357
  })
350
358
 
351
359
  // if (data.fullParams.highlightTarget && data.fullParams.highlightTarget != 'none') {