@easyv/charts 1.8.23 → 1.8.25

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,205 +1,286 @@
1
- import React, { memo } from 'react'
2
- import { getFontStyle, getMargin, getTranslate3d, getTranslate2d, getIcon } from '../utils';
3
-
1
+ import React, { memo } from "react";
2
+ import {
3
+ getFontStyle,
4
+ getMargin,
5
+ getTranslate3d,
6
+ getTranslate2d,
7
+ getIcon,
8
+ } from "../utils";
4
9
 
5
10
  export const PieTooltip = memo((props) => {
6
- const { mousePos,domRef,
7
- pieCenter,
8
- config: {
9
- tip: {
10
- data: { lineHeight, iconSize, name,
11
- value: { show: valueIsShow, fontStyle: valueFont, suffix: valueSuffix, suffix: { show: valueSuffixIsShow } },
12
- percentage: { show: percentageIsShow, fontStyle: percentageFont, suffix: percentageSuffix, suffix: { show: percentageSuffixIsShow }, precision },
13
- },
14
- image,
15
- margin,
16
- size: { width: tipWidth, height: tipHeight },
17
- translate: translateTip,
18
- },
19
- },
20
- data,
21
- series } = props
22
- const screenRef = domRef.current.getBoundingClientRect();
23
- const Item = () => {
24
- const { data: { s, y }, percent } = data
25
- const { type, icon, displayName } = [...series.values()].find(
26
- (series) => series.name == s
27
- );
11
+ const {
12
+ mousePos,
13
+ domRef,
14
+ pieCenter,
15
+ config: {
16
+ tip: {
17
+ data: {
18
+ lineHeight,
19
+ iconSize,
20
+ name,
21
+ value: {
22
+ show: valueIsShow,
23
+ fontStyle: valueFont,
24
+ suffix: valueSuffix,
25
+ suffix: { show: valueSuffixIsShow },
26
+ },
27
+ percentage: {
28
+ show: percentageIsShow,
29
+ fontStyle: percentageFont,
30
+ suffix: percentageSuffix,
31
+ suffix: { show: percentageSuffixIsShow },
32
+ precision,
33
+ },
34
+ },
35
+ image,
36
+ margin,
37
+ size: { width: tipWidth, height: tipHeight },
38
+ translate: translateTip,
39
+ },
40
+ },
41
+ data,
42
+ series,
43
+ } = props;
44
+ const screenRef = domRef.current.getBoundingClientRect();
45
+ const Item = () => {
46
+ const {
47
+ data: { s, y },
48
+ percent,
49
+ } = data;
50
+ const { type, icon, displayName } = [...series.values()].find(
51
+ (series) => series.name == s
52
+ );
53
+
54
+ const renderSuffix = (suffix) => {
55
+ const { content, font: suffiixFont, translate: suffixTranslate } = suffix;
56
+ return (
57
+ <span
58
+ style={{
59
+ ...getFontStyle(suffiixFont),
60
+ display: "inline-block",
61
+ transform: getTranslate3d(suffixTranslate),
62
+ }}
63
+ >
64
+ {content}
65
+ </span>
66
+ );
67
+ };
68
+
69
+ const _icon = getIcon(type, icon);
70
+ return (
71
+ <dd
72
+ style={{
73
+ display: "flex",
74
+ justifyContent: "space-between",
75
+ lineHeight: lineHeight + "px",
76
+ }}
77
+ >
78
+ <span
79
+ style={{
80
+ // border: '1px solid red',
81
+ display: "flex",
82
+ alignItems: "center",
83
+ gap: icon.iconGap,
84
+ }}
85
+ >
86
+ <span
87
+ style={{
88
+ ..._icon,
89
+ width: iconSize + "px",
90
+ height: iconSize + "px",
91
+ }}
92
+ />
93
+ <span style={getFontStyle(name)}>{displayName || s}</span>
94
+ </span>
95
+ {valueIsShow && (
96
+ <span style={getFontStyle(valueFont)}>
97
+ {y}
98
+ {valueSuffixIsShow && renderSuffix(valueSuffix)}
99
+ </span>
100
+ )}
101
+ {percentageIsShow && (
102
+ <span style={getFontStyle(percentageFont)}>
103
+ {Number(percent).toFixed(precision)}
104
+ {percentageSuffixIsShow && renderSuffix(percentageSuffix)}
105
+ </span>
106
+ )}
107
+ </dd>
108
+ );
109
+ };
110
+ const getBigScreenScale = () => {
111
+ // 优先使用全局提供的方法
112
+ if (typeof window.getScreenScale === "function") {
113
+ try {
114
+ const result = window.getScreenScale();
115
+ if (Array.isArray(result) && result.length >= 6) {
116
+ return result;
117
+ }
118
+ } catch (e) {
119
+ console.error("调用全局 getScreenScale 出错:", e);
120
+ }
121
+ }
122
+
123
+ // 获取容器元素
124
+ const bigscreenDom = document.getElementById("bigscreen-container");
125
+
126
+ // 元素不存在时的处理
127
+ if (!bigscreenDom) {
128
+ return [1, 1, window.innerWidth, window.innerHeight, 0, 0];
129
+ }
130
+
131
+ // 确保元素可见(未被隐藏)
132
+ const isVisible =
133
+ window.getComputedStyle(bigscreenDom).display !== "none" &&
134
+ window.getComputedStyle(bigscreenDom).visibility !== "hidden";
135
+ if (!isVisible) {
136
+ return [1, 1, window.innerWidth, window.innerHeight, 0, 0];
137
+ }
138
+
139
+ // 获取元素的布局矩形(最可靠的尺寸获取方式)
140
+ const rect = bigscreenDom.getBoundingClientRect();
141
+
142
+ // 提取基础尺寸(从布局矩形获取,不受样式影响)
143
+ const screenWidth = rect.width || window.innerWidth;
144
+ const screenHeight = rect.height || window.innerHeight;
145
+ const screenLeft = rect.left || 0;
146
+ const screenTop = rect.top || 0;
28
147
 
29
- const renderSuffix = (suffix) => {
30
- const {
31
- content,
32
- font: suffiixFont,
33
- translate: suffixTranslate,
34
- } = suffix;
35
- return (
36
- <span
37
- style={{
38
- ...getFontStyle(suffiixFont),
39
- display: "inline-block",
40
- transform: getTranslate3d(suffixTranslate),
41
- }}
42
- >
43
- {content}
44
- </span>
45
- )
46
- }
148
+ // 处理缩放
149
+ let scaleX = 1;
150
+ let scaleY = 1;
47
151
 
48
- const _icon = getIcon(type, icon);
49
- return (
50
- <dd
51
- style={{
52
- display: 'flex',
53
- justifyContent: 'space-between',
54
- lineHeight: lineHeight + 'px',
55
- }}
152
+ try {
153
+ const computedStyle = window.getComputedStyle(bigscreenDom);
154
+ const transform = computedStyle.transform;
56
155
 
57
- >
58
- <span
59
- style={{
60
- // border: '1px solid red',
61
- display: 'flex',
62
- alignItems: 'center',
63
- gap: icon.iconGap,
64
- }}
65
- >
66
- <span
67
- style={{
68
- ..._icon,
69
- width: iconSize + 'px',
70
- height: iconSize + 'px',
71
- }}
72
- />
73
- <span style={getFontStyle(name)}>{displayName || s}</span>
74
- </span>
75
- {valueIsShow && <span style={getFontStyle(valueFont)}>
76
- {y}
77
- {valueSuffixIsShow && renderSuffix(valueSuffix)}
78
- </span>}
79
- {percentageIsShow && <span style={getFontStyle(percentageFont)}>
80
- {Number(percent).toFixed(precision)}
81
- {percentageSuffixIsShow && renderSuffix(percentageSuffix)}
82
- </span>}
83
- </dd>
84
- );
85
- }
86
- const getBigScreenScale = () => {
87
- // 优先使用全局提供的方法
88
- if (typeof window.getScreenScale === 'function') {
89
- try {
90
- const result = window.getScreenScale();
91
- if (Array.isArray(result) && result.length >= 6) {
92
- return result;
93
- }
94
- } catch (e) {
95
- console.error('调用全局 getScreenScale 出错:', e);
96
- }
97
- }
98
-
99
- // 获取容器元素
100
- const bigscreenDom = document.getElementById('bigscreen-container');
101
-
102
- // 元素不存在时的处理
103
- if (!bigscreenDom) {
104
- console.warn('未找到 bigscreen-container 元素,使用视口尺寸');
105
- return [1, 1, window.innerWidth, window.innerHeight, 0, 0];
106
- }
107
-
108
- // 确保元素可见(未被隐藏)
109
- const isVisible = window.getComputedStyle(bigscreenDom).display !== 'none'
110
- && window.getComputedStyle(bigscreenDom).visibility !== 'hidden';
111
- if (!isVisible) {
112
- console.warn('bigscreen-container 元素不可见,使用视口尺寸');
113
- return [1, 1, window.innerWidth, window.innerHeight, 0, 0];
114
- }
115
-
116
- // 获取元素的布局矩形(最可靠的尺寸获取方式)
117
- const rect = bigscreenDom.getBoundingClientRect();
118
-
119
- // 提取基础尺寸(从布局矩形获取,不受样式影响)
120
- const screenWidth = rect.width || window.innerWidth;
121
- const screenHeight = rect.height || window.innerHeight;
122
- const screenLeft = rect.left || 0;
123
- const screenTop = rect.top || 0;
124
-
125
- // 处理缩放
126
- let scaleX = 1;
127
- let scaleY = 1;
128
-
129
- try {
130
- const computedStyle = window.getComputedStyle(bigscreenDom);
131
- const transform = computedStyle.transform;
132
-
133
- if (transform && transform !== 'none') {
134
- // 解析 transform matrix
135
- const matrix = new DOMMatrix(transform);
136
- scaleX = matrix.a; // 缩放X因子
137
- scaleY = matrix.d; // 缩放Y因子
138
- }
139
- } catch (e) {
140
- console.error('解析缩放样式出错:', e);
141
- }
142
-
143
- // 最终返回值(确保不会有undefined)
144
- const result = [
145
- isNaN(scaleX) ? 1 : scaleX,
146
- isNaN(scaleY) ? 1 : scaleY,
147
- isNaN(screenWidth) ? window.innerWidth : screenWidth,
148
- isNaN(screenHeight) ? window.innerHeight : screenHeight,
149
- isNaN(screenLeft) ? 0 : screenLeft,
150
- isNaN(screenTop) ? 0 : screenTop
151
- ];
152
- return result;
153
- };
154
- const [scaleX, scaleY,screenWidth,screenHeight,screenLeft,screenTop] = getBigScreenScale()
155
- const { x, y } = mousePos
156
- const mouseX=x/scaleX
157
- const mouseY=y/scaleY
158
- const { x: centerX, y: centerY } = pieCenter
159
- const getTipPos = () => {
160
- const tipPosMap = {
161
- rightTop: `translate(${(screenRef.x+translateTip.x+tipWidth)/scaleX+ mouseX-screenLeft/scaleX>(screenWidth/scaleX)?mouseX - tipWidth - translateTip.x:mouseX + translateTip.x}px,${(screenRef.y-translateTip.y-tipHeight)/scaleY+ mouseY-screenTop/scaleY<0?mouseY + translateTip.y:mouseY - tipHeight - translateTip.y}px)`,
162
- leftTop: `translate(${(screenRef.x-translateTip.x-tipWidth)/scaleX+ mouseX-screenLeft/scaleX<0?mouseX + translateTip.x:mouseX - translateTip.x-tipWidth}px,${(screenRef.y-translateTip.y-tipHeight)/scaleY+ mouseY-screenTop/scaleY<0?mouseY + translateTip.y:mouseY - tipHeight - translateTip.y}px)`,
163
- leftBottom: `translate(${(screenRef.x-translateTip.x-tipWidth)/scaleX+ mouseX-screenLeft/scaleX<0?mouseX + translateTip.x:mouseX - translateTip.x-tipWidth}px,${(screenRef.y+translateTip.y+tipHeight)/scaleY+ mouseY-screenTop/scaleY>(screenHeight/scaleY)?mouseY - translateTip.y-tipHeight:mouseY + translateTip.y}px)`,
164
- rightBottom: `translate(${(screenRef.x+translateTip.x+tipWidth)/scaleX+ mouseX-screenLeft/scaleX>(screenWidth/scaleX)?mouseX - tipWidth - translateTip.x:mouseX + translateTip.x}px,${(screenRef.y+translateTip.y+tipHeight)/scaleY+ mouseY-screenTop/scaleY>(screenHeight/scaleY)?mouseY - translateTip.y-tipHeight:mouseY + translateTip.y}px)`,
165
- }
166
- if (mouseX < centerX && mouseY < centerY) {
167
- return tipPosMap.leftTop
168
- } else if (mouseX > centerX && mouseY < centerY) {
169
- return tipPosMap.rightTop
170
- } else if (mouseX >= centerX && mouseY >= centerY) {
171
- return tipPosMap.rightBottom
172
- } else {
173
- return tipPosMap.leftBottom
174
- }
175
- }
156
+ if (transform && transform !== "none") {
157
+ // 解析 transform matrix
158
+ const matrix = new DOMMatrix(transform);
159
+ scaleX = matrix.a; // 缩放X因子
160
+ scaleY = matrix.d; // 缩放Y因子
161
+ }
162
+ } catch (e) {
163
+ console.error("解析缩放样式出错:", e);
164
+ }
176
165
 
177
- return <div
178
- className='__easyv-tooltip'
179
- style={{
180
- pointerEvents: 'none',
181
- transform: getTipPos(mousePos, pieCenter),
182
- width: tipWidth,
183
- height: tipHeight,
184
- padding: getMargin(margin),
185
- background: image
186
- ? '50% 50% / 100% 100% no-repeat url(' +
187
- window.appConfig.ASSETS_URL +
188
- image +
189
- ')'
190
- : 'rgba(48, 55, 66, 0.85)',
191
- }}
192
- >
193
- <dl
194
- style={{
195
- display: 'flex',
196
- flexDirection: 'column',
197
- justifyContent: 'space-between',
198
- height: '100%',
199
- }}
200
- >
201
- {Item()}
202
- </dl>
166
+ // 最终返回值(确保不会有undefined)
167
+ const result = [
168
+ isNaN(scaleX) ? 1 : scaleX,
169
+ isNaN(scaleY) ? 1 : scaleY,
170
+ isNaN(screenWidth) ? window.innerWidth : screenWidth,
171
+ isNaN(screenHeight) ? window.innerHeight : screenHeight,
172
+ isNaN(screenLeft) ? 0 : screenLeft,
173
+ isNaN(screenTop) ? 0 : screenTop,
174
+ ];
175
+ return result;
176
+ };
177
+ const [scaleX, scaleY, screenWidth, screenHeight, screenLeft, screenTop] =
178
+ getBigScreenScale();
179
+ const { x, y } = mousePos;
180
+ const mouseX = x / scaleX;
181
+ const mouseY = y / scaleY;
182
+ const { x: centerX, y: centerY } = pieCenter;
183
+ const getTipPos = () => {
184
+ const tipPosMap = {
185
+ rightTop: `translate(${
186
+ (screenRef.x + translateTip.x + tipWidth) / scaleX +
187
+ mouseX -
188
+ screenLeft / scaleX >
189
+ screenWidth / scaleX
190
+ ? mouseX - tipWidth - translateTip.x
191
+ : mouseX + translateTip.x
192
+ }px,${
193
+ (screenRef.y - translateTip.y - tipHeight) / scaleY +
194
+ mouseY -
195
+ screenTop / scaleY <
196
+ 0
197
+ ? mouseY + translateTip.y
198
+ : mouseY - tipHeight - translateTip.y
199
+ }px)`,
200
+ leftTop: `translate(${
201
+ (screenRef.x - translateTip.x - tipWidth) / scaleX +
202
+ mouseX -
203
+ screenLeft / scaleX <
204
+ 0
205
+ ? mouseX + translateTip.x
206
+ : mouseX - translateTip.x - tipWidth
207
+ }px,${
208
+ (screenRef.y - translateTip.y - tipHeight) / scaleY +
209
+ mouseY -
210
+ screenTop / scaleY <
211
+ 0
212
+ ? mouseY + translateTip.y
213
+ : mouseY - tipHeight - translateTip.y
214
+ }px)`,
215
+ leftBottom: `translate(${
216
+ (screenRef.x - translateTip.x - tipWidth) / scaleX +
217
+ mouseX -
218
+ screenLeft / scaleX <
219
+ 0
220
+ ? mouseX + translateTip.x
221
+ : mouseX - translateTip.x - tipWidth
222
+ }px,${
223
+ (screenRef.y + translateTip.y + tipHeight) / scaleY +
224
+ mouseY -
225
+ screenTop / scaleY >
226
+ screenHeight / scaleY
227
+ ? mouseY - translateTip.y - tipHeight
228
+ : mouseY + translateTip.y
229
+ }px)`,
230
+ rightBottom: `translate(${
231
+ (screenRef.x + translateTip.x + tipWidth) / scaleX +
232
+ mouseX -
233
+ screenLeft / scaleX >
234
+ screenWidth / scaleX
235
+ ? mouseX - tipWidth - translateTip.x
236
+ : mouseX + translateTip.x
237
+ }px,${
238
+ (screenRef.y + translateTip.y + tipHeight) / scaleY +
239
+ mouseY -
240
+ screenTop / scaleY >
241
+ screenHeight / scaleY
242
+ ? mouseY - translateTip.y - tipHeight
243
+ : mouseY + translateTip.y
244
+ }px)`,
245
+ };
246
+ if (mouseX < centerX && mouseY < centerY) {
247
+ return tipPosMap.leftTop;
248
+ } else if (mouseX > centerX && mouseY < centerY) {
249
+ return tipPosMap.rightTop;
250
+ } else if (mouseX >= centerX && mouseY >= centerY) {
251
+ return tipPosMap.rightBottom;
252
+ } else {
253
+ return tipPosMap.leftBottom;
254
+ }
255
+ };
203
256
 
204
- </div>
205
- })
257
+ return (
258
+ <div
259
+ className="__easyv-tooltip"
260
+ style={{
261
+ pointerEvents: "none",
262
+ transform: getTipPos(mousePos, pieCenter),
263
+ width: tipWidth,
264
+ height: tipHeight,
265
+ padding: getMargin(margin),
266
+ background: image
267
+ ? "50% 50% / 100% 100% no-repeat url(" +
268
+ window.appConfig.ASSETS_URL +
269
+ image +
270
+ ")"
271
+ : "rgba(48, 55, 66, 0.85)",
272
+ }}
273
+ >
274
+ <dl
275
+ style={{
276
+ display: "flex",
277
+ flexDirection: "column",
278
+ justifyContent: "space-between",
279
+ height: "100%",
280
+ }}
281
+ >
282
+ {Item()}
283
+ </dl>
284
+ </div>
285
+ );
286
+ });