@easyv/charts 1.8.24 → 1.8.26

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.
@@ -1,18 +1,26 @@
1
1
  /**
2
2
  * 总入口,通过外面传进来的type来确定渲染哪种图表,饼环图表为“pie”,否则为轴类图表
3
3
  */
4
- import React, { memo, useMemo, useRef, createRef, useState, useEffect, useCallback } from 'react';
5
- import { chartContext } from '../context';
6
- import { PieChart, CartesianChart } from '.';
7
- import { group } from 'd3v7';
4
+ import React, {
5
+ memo,
6
+ useMemo,
7
+ useRef,
8
+ createRef,
9
+ useState,
10
+ useEffect,
11
+ useCallback,
12
+ } from "react";
13
+ import { chartContext } from "../context";
14
+ import { PieChart, CartesianChart } from ".";
15
+ import { group } from "d3v7";
8
16
 
9
- const getCallbackData = (action,callbacks, data) => {
10
- const callbackData={};
17
+ const getCallbackData = (action, callbacks, data) => {
18
+ const callbackData = {};
11
19
  if (callbacks && Array.isArray(callbacks) && callbacks.length && data) {
12
- callbacks.forEach(({ origin, target, actions:_action }) => {
13
- if(action === _action){
14
- callbackData[target] = data[origin];
15
- }
20
+ callbacks.forEach(({ origin, target, actions: _action }) => {
21
+ if (action === _action) {
22
+ callbackData[target] = origin ? data[origin] : data;
23
+ }
16
24
  });
17
25
  }
18
26
  return callbackData;
@@ -30,7 +38,7 @@ const Chart = memo(
30
38
  },
31
39
  interaction,
32
40
  },
33
- data:originData,
41
+ data: originData,
34
42
  onRelative,
35
43
  emit,
36
44
  emitEvent,
@@ -46,13 +54,14 @@ const Chart = memo(
46
54
  const chartWidth = width - marginLeft - marginRight;
47
55
  const chartHeight = height - marginTop - marginBottom;
48
56
  const [active, setActive] = useState(true);
49
- const scaleRef = useRef([1,1]);
57
+ const scaleRef = useRef([1, 1]);
58
+ const screenPosRef = useRef({ left: 0, top: 0 });
50
59
  const triggerOnRelative = useCallback(
51
- (action,data) => {
60
+ (action, data) => {
52
61
  if (!interaction) return;
53
62
  const { callbacks, remoteControls } = interaction;
54
63
  const callbackData = getCallbackData(action, callbacks, data);
55
- if (JSON.stringify(callbackData)!="{}") {
64
+ if (Object.keys(callbackData).length > 0) {
56
65
  onRelative && onRelative(id, callbackData);
57
66
  remoteControls &&
58
67
  emitEvent &&
@@ -61,30 +70,31 @@ const Chart = memo(
61
70
  if (
62
71
  control.screen &&
63
72
  control.type &&
64
- control.type === 'callback'
73
+ control.type === "callback"
65
74
  ) {
66
75
  emitEvent({
67
76
  screen: control.screen,
68
- type: 'callback',
77
+ type: "callback",
69
78
  callbackData,
70
79
  });
71
80
  }
72
81
  });
73
82
  }
74
83
  },
75
- [ JSON.stringify(interaction)]
84
+ [JSON.stringify(interaction)]
76
85
  );
77
86
 
78
87
  const onEmit = useCallback(
79
- (type = 'click', data) => emit && emit(type, data),
88
+ (type = "click", data) => emit && emit(type, data),
80
89
  [emit]
81
90
  );
82
91
 
83
92
  const context = useMemo(
84
93
  () => ({
85
94
  id,
86
- isIOS:isIOS.current, //是否为IOS设备
87
- scale:scaleRef, //大屏的缩放比
95
+ isIOS: isIOS.current, //是否为IOS设备
96
+ scale: scaleRef, //大屏的缩放比
97
+ screenPos: screenPosRef, //大屏的偏移位置
88
98
  width: chartWidth,
89
99
  height: chartHeight,
90
100
  triggerOnRelative,
@@ -93,62 +103,86 @@ const Chart = memo(
93
103
  }),
94
104
  [id, chartWidth, chartHeight, triggerOnRelative, svg, onEmit]
95
105
  );
96
-
97
- useEffect(()=>{
98
- let isAnimation = window.screenConfig?window.screenConfig.isAnimation:true; //大屏的全局设置是否允许开启动画,false为不允许
99
- if(!isAnimation) setActive(false);
100
- const activeHandler=(e)=>{
106
+
107
+ useEffect(() => {
108
+ let isAnimation = window.screenConfig
109
+ ? window.screenConfig.isAnimation
110
+ : true; //大屏的全局设置是否允许开启动画,false为不允许
111
+ if (!isAnimation) setActive(false);
112
+ const activeHandler = (e) => {
101
113
  const { dynamicData = true } = e;
102
114
  isAnimation && setActive(dynamicData);
103
- }
115
+ };
104
116
  getScreenScale();
105
- document.addEventListener(`switchActive_${id}`,activeHandler);
106
- document.addEventListener("resize",getScreenScale);
107
- return ()=>{
108
- document.removeEventListener(`switchActive_${id}`,activeHandler);
109
- document.removeEventListener("resize",getScreenScale);
110
- }
111
- },[]);
112
-
117
+ document.addEventListener(`switchActive_${id}`, activeHandler);
118
+ document.addEventListener("resize", getScreenScale);
119
+ return () => {
120
+ document.removeEventListener(`switchActive_${id}`, activeHandler);
121
+ document.removeEventListener("resize", getScreenScale);
122
+ };
123
+ }, []);
124
+
113
125
  let data = checkData(originData);
114
-
126
+
115
127
  return (
116
128
  <chartContext.Provider value={context}>
117
- {type == 'pie' ? (
118
- <PieChart id={id} config={config} data={data} active={active} {...props} />
129
+ {type == "pie" ? (
130
+ <PieChart
131
+ id={id}
132
+ config={config}
133
+ data={data}
134
+ active={active}
135
+ {...props}
136
+ />
119
137
  ) : (
120
- <CartesianChart id={id} config={config} data={data} active={active} {...props} />
121
- )}
138
+ <CartesianChart
139
+ id={id}
140
+ config={config}
141
+ data={data}
142
+ active={active}
143
+ {...props}
144
+ />
145
+ )}
122
146
  </chartContext.Provider>
123
-
124
147
  );
125
148
  //获取大屏缩放系数
126
- function getScreenScale(){
127
- setTimeout(()=>{
128
- //获取大屏缩放系数
129
- let dom = document.getElementById("bigscreen-container") || document.getElementById("m-simulator");
130
- if(dom){
131
- const transform = dom.style.transform;
132
- const scale = transform?transform.match(/^scale\((.+)\)$/)[1]:"1,1";
133
- const arr = scale.split(",");
134
- scaleRef.current = [1/arr[0],1/(arr.length===1?arr[0]:arr[1])]; //这里做一次除法,后面就可以用乘法计算值了
135
- }
136
- },50);
149
+ function getScreenScale() {
150
+ setTimeout(() => {
151
+ //获取大屏缩放系数
152
+ let dom =
153
+ document.getElementById("bigscreen-container") ||
154
+ document.getElementById("m-simulator");
155
+ if (dom) {
156
+ const transform = dom.style.transform;
157
+ const scale = transform
158
+ ? transform.match(/^scale\((.+)\)$/)[1]
159
+ : "1,1";
160
+ const arr = scale.split(",");
161
+ scaleRef.current = [
162
+ 1 / arr[0],
163
+ 1 / (arr.length === 1 ? arr[0] : arr[1]),
164
+ ]; //这里做一次除法,后面就可以用乘法计算值了
165
+ screenPosRef.current = {
166
+ left: parseFloat(dom.style.left),
167
+ top: parseFloat(dom.style.top),
168
+ };
169
+ }
170
+ }, 100);
137
171
  }
138
172
  //预检数据格式是否规范
139
- function checkData(data){
140
- try{
141
- const hasS = data.some(d=>d.s);
142
- if(!hasS){
143
- return data.map(d=>{
173
+ function checkData(data) {
174
+ try {
175
+ const hasS = data.some((d) => d.s);
176
+ if (!hasS) {
177
+ return data.map((d) => {
144
178
  return {
145
179
  ...d,
146
- s:"系列一"
147
- }
148
- })
180
+ s: "系列一",
181
+ };
182
+ });
149
183
  }
150
184
  return data;
151
- }catch(e){}
185
+ } catch (e) {}
152
186
  return [];
153
187
  }
154
188
  }
@@ -3,7 +3,12 @@
3
3
  */
4
4
  import { memo, useContext } from "react";
5
5
  import { min, max } from "d3v7";
6
- import { getTranslate2d, getSeriesInfo, getFontStyle, formatFont } from "../utils";
6
+ import {
7
+ getTranslate2d,
8
+ getSeriesInfo,
9
+ getFontStyle,
10
+ formatFont,
11
+ } from "../utils";
7
12
  import { chartContext } from "../context";
8
13
 
9
14
  const getHighlightData = (data, extent) => {
@@ -31,8 +36,8 @@ export default memo(
31
36
  config: {
32
37
  seriesIntervalWidth: paddingInner = 0,
33
38
  paddingInner: paddingOuter = 0,
34
- showType:seriesType = 'bar',
35
- highlight: { show: showHighlight, extent, ...highlightStyle }={},//配置项不存在的处理
39
+ showType: seriesType = "bar",
40
+ highlight: { show: showHighlight, extent, ...highlightStyle } = {}, //配置项不存在的处理
36
41
  ...other
37
42
  },
38
43
  config,
@@ -40,27 +45,30 @@ export default memo(
40
45
  selectStyle,
41
46
  bandLength = 0,
42
47
  data,
43
- xAxis: { scaler: xScaler, step, direction },
48
+ xAxis: { scaler: normalScaler, step:normalStep, direction,controlStep,controlDragScaler },
44
49
  yAxis: { scaler: yScaler, isClipAxis, clipValue },
45
- triggerClick
50
+ triggerEvents,
51
+ isControlChart
46
52
  }) => {
53
+ const step = isControlChart ? controlStep : normalStep;
54
+ const xScaler = isControlChart ? controlDragScaler : normalScaler;
47
55
  let selectConfig = other;
48
- if(selectStyle){
49
- const { show, showType, icon, numlabel:label } = selectStyle;
50
- if(show && seriesType==showType){
51
- if(showType=="bar"){
56
+ if (selectStyle) {
57
+ const { show, showType, icon, numlabel: label } = selectStyle;
58
+ if (show && seriesType == showType) {
59
+ if (showType == "bar") {
52
60
  selectConfig = { label };
53
- }else{
61
+ } else {
54
62
  selectConfig = { icon, label };
55
63
  }
56
64
  }
57
65
  }
58
66
  let highlightConfig = other;
59
- if(highlightStyle){
60
- highlightConfig = { ...other, label:highlightStyle.numlabel };
67
+ if (highlightStyle) {
68
+ highlightConfig = { ...other, label: highlightStyle.numlabel };
61
69
  }
62
70
  const lineType = config.hasOwnProperty("line"); // 堆叠处理
63
-
71
+
64
72
  if (!data.length) return null;
65
73
  const { width, height } = useContext(chartContext);
66
74
 
@@ -72,19 +80,27 @@ export default memo(
72
80
  });
73
81
  const _data = showHighlight ? getHighlightData(data, extent) : data;
74
82
  const isVertical = direction === "vertical";
75
-
83
+
76
84
  return (
77
85
  <g className="__easyv-label">
78
86
  {_data.map(
79
87
  (
80
- { flag, index, bound: [start, end], data, data: { x, y, showY, s } },
88
+ {
89
+ flag,
90
+ index,
91
+ bound: [start, end],
92
+ data,
93
+ data: { x, y, showY, s },
94
+ },
81
95
  i
82
96
  ) => {
83
97
  let y1, y2;
84
- const { icon, label } = x==curXLabel?selectConfig:flag?highlightConfig:other;
98
+ const { icon, label } =
99
+ x == curXLabel ? selectConfig : flag ? highlightConfig : other;
85
100
  const showIcon = icon && icon.show;
86
101
  const showLabel = label && label.show;
87
- const { position:_position="outerStart", reverse=true } = label || {};
102
+ const { position: _position = "outerStart", reverse = true } =
103
+ label || {};
88
104
  if (isClipAxis) {
89
105
  if (end > +clipValue) {
90
106
  y1 = yScaler[1](start);
@@ -104,11 +120,12 @@ export default memo(
104
120
  }
105
121
 
106
122
  // const y2 = yScaler(isVertical ? start : end);
107
- const positionX =
108
- xScaler(x) - step / 2 + seriesStart + index * seriesStep;
123
+ const positionX =xScaler(x)- step / 2+seriesStart+ index * seriesStep;
109
124
 
110
125
  if (isNaN(positionX)) return null;
111
- const position =isXRepeat?positionX + (config.line ? step : seriesWidth) / 2: xScaler(x);
126
+ const position = isXRepeat
127
+ ? positionX + (config.line ? step : seriesWidth) / 2
128
+ : xScaler(x);
112
129
  const labelPosition = isVertical
113
130
  ? getVerticalLabel({
114
131
  position: _position,
@@ -116,7 +133,7 @@ export default memo(
116
133
  y1,
117
134
  y2,
118
135
  width,
119
- reverse
136
+ reverse,
120
137
  })
121
138
  : getHorizontalLabel({
122
139
  position: _position,
@@ -124,7 +141,7 @@ export default memo(
124
141
  y1,
125
142
  y2,
126
143
  height,
127
- reverse
144
+ reverse,
128
145
  });
129
146
  const attr = isVertical
130
147
  ? {
@@ -140,14 +157,23 @@ export default memo(
140
157
  return (
141
158
  <g
142
159
  key={i}
143
- onClick={e=>triggerClick(e,"setCurrent")}
160
+ onClick={(e) => triggerEvents(e, "setCurrent")}
161
+ onMouseMove={(e) => triggerEvents(e, "mouseenter")}
162
+ onMouseLeave={(e) => triggerEvents(e, "mouseleave")}
144
163
  style={{ cursor: "pointer" }}
145
164
  data-data={JSON.stringify(data)}
146
165
  >
147
166
  {showIcon && !isNaN(attr.y) && (
148
167
  <Icon cx={attr.x} cy={y2} config={icon} />
149
168
  )}
150
- {showLabel && <Label value={showY} config={label} reverse={reverse} {...attr} />}
169
+ {showLabel && (
170
+ <Label
171
+ value={showY}
172
+ config={label}
173
+ reverse={reverse}
174
+ {...attr}
175
+ />
176
+ )}
151
177
  </g>
152
178
  );
153
179
  }
@@ -164,13 +190,15 @@ const Label = ({
164
190
  config: {
165
191
  font,
166
192
  translate: { x: translateX = 0, y: translateY = 0 },
167
- suffix:{
168
- content, font:suffixFont, translate:{ x:suffixX, y:suffixY }
169
- }
193
+ suffix: {
194
+ content,
195
+ font: suffixFont,
196
+ translate: { x: suffixX, y: suffixY },
197
+ },
170
198
  },
171
199
  textAnchor = "middle",
172
200
  dominantBaseline = "middle",
173
- reverse
201
+ reverse,
174
202
  }) => {
175
203
  return (
176
204
  <text
@@ -182,12 +210,18 @@ const Label = ({
182
210
  })}
183
211
  textAnchor={textAnchor}
184
212
  dominantBaseline={dominantBaseline}
185
- style={{...formatFont(font,"svg")}}
213
+ style={{ ...formatFont(font, "svg") }}
186
214
  >
187
215
  <tspan>{value}</tspan>
188
- <tspan dx={suffixX} dy={suffixY} style={{
189
- ...getFontStyle(suffixFont,"svg")
190
- }}>{content}</tspan>
216
+ <tspan
217
+ dx={suffixX}
218
+ dy={suffixY}
219
+ style={{
220
+ ...getFontStyle(suffixFont, "svg"),
221
+ }}
222
+ >
223
+ {content}
224
+ </tspan>
191
225
  </text>
192
226
  );
193
227
  };
@@ -227,13 +261,20 @@ const Circle = ({ cx, cy, color, radius }) => (
227
261
  <circle cx={cx} cy={cy} fill={color} r={radius} stroke="none" />
228
262
  );
229
263
 
230
- const getVerticalLabel = ({ position = "outerStart", width, y, y1, y2, reverse = true }) => {
231
- const needReverse = reverse && y<0;
264
+ const getVerticalLabel = ({
265
+ position = "outerStart",
266
+ width,
267
+ y,
268
+ y1,
269
+ y2,
270
+ reverse = true,
271
+ }) => {
272
+ const needReverse = reverse && y < 0;
232
273
  switch (position) {
233
274
  case "start":
234
275
  return {
235
276
  x: y2,
236
- textAnchor: needReverse?"end":"start",
277
+ textAnchor: needReverse ? "end" : "start",
237
278
  };
238
279
  case "middle":
239
280
  return {
@@ -243,12 +284,12 @@ const getVerticalLabel = ({ position = "outerStart", width, y, y1, y2, reverse =
243
284
  case "end":
244
285
  return {
245
286
  x: y1,
246
- textAnchor: needReverse?"start":"end",
287
+ textAnchor: needReverse ? "start" : "end",
247
288
  };
248
289
  case "outerStart":
249
290
  return {
250
291
  x: y1,
251
- textAnchor: needReverse?"end":"start",
292
+ textAnchor: needReverse ? "end" : "start",
252
293
  };
253
294
  case "chartStart":
254
295
  return {
@@ -257,13 +298,20 @@ const getVerticalLabel = ({ position = "outerStart", width, y, y1, y2, reverse =
257
298
  };
258
299
  }
259
300
  };
260
- const getHorizontalLabel = ({ position = "outerStart", height, y, y1, y2, reverse = true }) => {
261
- const needReverse = reverse && y<0;
301
+ const getHorizontalLabel = ({
302
+ position = "outerStart",
303
+ height,
304
+ y,
305
+ y1,
306
+ y2,
307
+ reverse = true,
308
+ }) => {
309
+ const needReverse = reverse && y < 0;
262
310
  switch (position) {
263
311
  case "start":
264
312
  return {
265
313
  y: y1,
266
- dominantBaseline: needReverse?"text-before-edge":"text-after-edge",
314
+ dominantBaseline: needReverse ? "text-before-edge" : "text-after-edge",
267
315
  };
268
316
  case "middle":
269
317
  return {
@@ -273,12 +321,12 @@ const getHorizontalLabel = ({ position = "outerStart", height, y, y1, y2, revers
273
321
  case "end":
274
322
  return {
275
323
  y: y2,
276
- dominantBaseline: needReverse?"text-after-edge":"text-before-edge",
324
+ dominantBaseline: needReverse ? "text-after-edge" : "text-before-edge",
277
325
  };
278
326
  case "outerStart":
279
327
  return {
280
328
  y: y2,
281
- dominantBaseline: needReverse?"text-before-edge":"text-after-edge",
329
+ dominantBaseline: needReverse ? "text-before-edge" : "text-after-edge",
282
330
  };
283
331
  case "chartStart":
284
332
  return {
@@ -34,6 +34,7 @@ const Area = ({
34
34
  },
35
35
  xScaler,
36
36
  yScaler,
37
+ opacity:Areaopacity
37
38
  }) => {
38
39
  const [height] = yScaler.range();
39
40
  const area = useMemo(() => getColorList(fill), [fill]);
@@ -51,7 +52,7 @@ const Area = ({
51
52
 
52
53
  return (
53
54
  <>
54
- <path d={areaGen(data)} style={{pointerEvents:"none"}} stroke='none' fill={'url(#' + id + ')'} />
55
+ <path d={areaGen(data)} style={{pointerEvents:"none",opacity:Areaopacity}} stroke='none' fill={'url(#' + id + ')'} />
55
56
  <defs>
56
57
  {type && type == 'pattern' ? (
57
58
  <pattern id={id} patternUnits="userSpaceOnUse" width={patternW} height={patternH}>
@@ -69,6 +70,9 @@ export default memo(
69
70
  ({
70
71
  type,
71
72
  config: {
73
+ areaColor:{linear:{
74
+ opacity
75
+ }},
72
76
  line: {
73
77
  type: lineType,
74
78
  lineWidth,
@@ -144,6 +148,7 @@ export default memo(
144
148
  config={{ ...area, curve, tension }}
145
149
  xScaler={xScaler}
146
150
  yScaler={yScaler}
151
+ opacity={opacity}
147
152
  />
148
153
  )}
149
154
  {showLighter && <Lighter path={path} config={lighter} />}