245 |
${title}
246 | ${content}
247 | `;
248 | },
249 | });
250 |
251 | view.legend({
252 | custom: true,
253 | items: [
254 | {
255 | value: 'Female',
256 | name: 'Female',
257 | marker: { symbol: 'circle', style: { fill: femaleColor, r: 5 } },
258 | },
259 | {
260 | value: 'Male',
261 | name: 'Male',
262 | marker: { symbol: 'circle', style: { fill: maleColor, r: 5 } },
263 | },
264 | {
265 | value: 'average',
266 | name: 'Average',
267 | marker: { symbol: 'circle', style: { fill: averageColor, r: 5 } },
268 | },
269 | {
270 | value: 'high-calories',
271 | name: 'High calories',
272 | marker: {
273 | symbol: 'circle',
274 | style: { fill: unhealthyColor, r: 5 },
275 | },
276 | },
277 | {
278 | value: 'low-calories',
279 | name: 'Low calories',
280 | marker: {
281 | symbol: 'square',
282 | style: { fill: healthyColor, r: 5 },
283 | },
284 | },
285 | ],
286 | });
287 |
288 | view.interaction('element-active');
289 | view.interaction('active-region');
290 | view.render();
291 | chart.render();
292 |
293 | const shapes = view.geometries[0].getShapes().reduce((result, shape) => {
294 | // @ts-ignore
295 | return [...result, ...shape.getChildren()];
296 | }, []);
297 |
298 | view.on('legend-item:click', e => {
299 | const delegateObject = e.gEvent.delegateObject;
300 | shapes.forEach(shape => {
301 | if (shape.get('name') === delegateObject.item.value) {
302 | shape.animate(
303 | {
304 | opacity: delegateObject.item.unchecked ? 1 : 0,
305 | },
306 | 200
307 | );
308 | }
309 | });
310 | });
311 |
312 | let size = 0;
313 | view.on('legend-item:mouseenter', e => {
314 | const delegateObject = e.gEvent.delegateObject;
315 | shapes.forEach(shape => {
316 | if (shape.get('name') === delegateObject.item.value) {
317 | size = shape.attr('r');
318 | shape.animate(
319 | {
320 | r: 6,
321 | },
322 | 200
323 | );
324 | }
325 | });
326 | });
327 |
328 | view.on('legend-item:mouseleave', e => {
329 | const delegateObject = e.gEvent.delegateObject;
330 | shapes.forEach(shape => {
331 | if (shape.get('name') === delegateObject.item.value) {
332 | shape.animate({ r: size }, 200);
333 | }
334 | });
335 | });
336 | });
337 |
--------------------------------------------------------------------------------
/src/dashboards/monitor-template.tsx:
--------------------------------------------------------------------------------
1 | import { StarFilled, AlertFilled, SettingFilled, AlertOutlined, FileTextOutlined } from '@ant-design/icons';
2 | import React from 'react';
3 | export const monitorJson = {
4 | theme: 'light',
5 | // layouts 部分,可以加上hash #mode=edit 然后页面拖拽调整完大小,替换保存就行(只需要 i、x、y、w、h)
6 | layouts: {
7 | root: {
8 | lg: [
9 | { w: 6, h: 5, x: 0, y: 0, i: 'a' },
10 | { w: 6, h: 5, x: 6, y: 0, i: 'b' },
11 | { w: 6, h: 5, x: 12, y: 0, i: 'c' },
12 | { w: 6, h: 5, x: 18, y: 0, i: 'd' },
13 | { w: 6, h: 11, x: 0, y: 5, i: "e" },
14 | { w: 18, h: 11, x: 6, y: 5, i: "f" },
15 | { w: 24, h: 11, x: 0, y: 16, i: "g" },
16 | { w: 24, h: 12, x: 0, y: 27, i: "h" },
17 | { w: 12, h: 11, x: 0, y: 40, i: "i" },
18 | { w: 12, h: 11, x: 12, y: 40, i: "j" },
19 | ],
20 | xs: [
21 | { w: 6, h: 4, x: 0, y: 0, i: "a" },
22 | { w: 6, h: 4, x: 6, y: 0, i: "b" },
23 | { w: 6, h: 4, x: 0, y: 4, i: "c" },
24 | { w: 6, h: 4, x: 6, y: 4, i: "d" },
25 | { w: 6, h: 10, x: 0, y: 8, i: "e" },
26 | { w: 12, h: 10, x: 0, y: 18, i: "f" },
27 | { w: 6, h: 10, x: 6, y: 8, i: "g" },
28 | { w: 12, h: 11, x: 0, y: 28, i: "h" },
29 | { w: 6, h: 10, x: 0, y: 39, i: "i" },
30 | { w: 6, h: 10, x: 6, y: 39, i: "j" },
31 | ],
32 | xxs: [
33 | { w: 4, h: 4, x: 0, y: 0, i: "a" },
34 | { w: 4, h: 4, x: 0, y: 4, i: "b" },
35 | { w: 4, h: 4, x: 0, y: 8, i: "c" },
36 | { w: 4, h: 4, x: 0, y: 12, i: "d" },
37 | { w: 4, h: 12, x: 0, y: 16, i: "e" },
38 | { w: 4, h: 20, x: 0, y: 25, i: "f" },
39 | { w: 4, h: 12, x: 0, y: 31, i: "g" },
40 | { w: 4, h: 20, x: 0, y: 42, i: "h" },
41 | { w: 4, h: 12, x: 0, y: 54, i: "i" },
42 | { w: 4, h: 12, x: 0, y: 66, i: "j" },
43 | ]
44 | },
45 | },
46 | content: {
47 | tag: 'panel',
48 | id: 'root',
49 | attributes: {},
50 | children: [
51 | {
52 | tag: 'statistic',
53 | id: 'a',
54 | attributes: {
55 | measures: ['monitor_count'],
56 | meta: {
57 | monitor_count: {
58 | alias: '监控总数',
59 | icon:
,
70 | },
71 | },
72 | data: [
73 | {
74 | monitor_count: 21,
75 | },
76 | ],
77 | },
78 | },
79 | {
80 | tag: 'statistic',
81 | id: 'b',
82 | attributes: {
83 | measures: ['healthy_app_count'],
84 | meta: {
85 | healthy_app_count: {
86 | alias: '健康应用数',
87 | icon:
96 |

97 |
,
98 | },
99 | },
100 | data: [
101 | {
102 | healthy_app_count: 19,
103 | },
104 | ],
105 | },
106 | },
107 | {
108 | tag: 'statistic',
109 | id: 'c',
110 | attributes: {
111 | measures: ['anomaly_app_counts'],
112 | meta: {
113 | anomaly_app_counts: {
114 | alias: '异常应用数',
115 | icon:
,
126 | },
127 | },
128 | data: [
129 | {
130 | anomaly_app_counts: 2,
131 | },
132 | ],
133 | },
134 | },
135 | {
136 | tag: 'statistic',
137 | id: 'd',
138 | attributes: {
139 | measures: ['custom_count'],
140 | meta: {
141 | custom_count: {
142 | alias: '自定义大盘',
143 | icon:
,
154 | },
155 | },
156 | data: [
157 | {
158 | custom_count: 5,
159 | },
160 | ],
161 | },
162 | },
163 | {
164 | tag: 'liquid',
165 | id: 'e',
166 | attributes: {
167 | title: '访问频次发布',
168 | width: 400,
169 | height: 400,
170 | autoFit: true,
171 | radius: 0.98,
172 | percent: 0.32,
173 | appendPadding: 0,
174 | wave: {
175 | legend: 40,
176 | },
177 | outline: {
178 | distance: 2,
179 | },
180 | statistic: {
181 | title: {
182 | formatter: () => '资源剩余',
183 | },
184 | content: {
185 | customHtml: (container, view, { percent }) => {
186 | const text = `${(percent * 100).toFixed(0)}%`;
187 | return text;
188 | }
189 | }
190 | }
191 | }
192 | },
193 | {
194 | tag: 'area',
195 | id: 'f',
196 | // 面积图扩展。attribues 扩展 explaination (注意下,屏幕小的时候,布局自动变换为 上下)
197 | attributes: {
198 | title: '整体流量趋势',
199 | data: [{ "value": 156183, "time": "2021-03-29" }, { "value": 274731, "time": "2021-04-29" }, { "value": 421680, "time": "2021-05-29" }, { "value": 694329, "time": "2021-06-29" }, { "value": 827597, "time": "2021-07-29" }, { "value": 878775, "time": "2021-08-29" }, { "value": 1204784, "time": "2021-09-29" }, { "value": 1044414, "time": "2021-10-29" }, { "value": 1301583, "time": "2021-11-29" }, { "value": 1826632, "time": "2021-12-29" }, { "value": 1979659, "time": "2022-01-29" }, { "value": 2262575, "time": "2022-02-28" }, { "value": 1598468, "time": "2022-03-28" }, { "value": 2124546, "time": "2022-04-28" }, { "value": 2848808, "time": "2022-05-28" }, { "value": 3065085, "time": "2022-06-28" }, { "value": 1993866, "time": "2022-07-28" }, { "value": 2415007, "time": "2022-08-28" }, { "value": 3268743, "time": "2022-09-28" }, { "value": 3083374, "time": "2022-10-28" }],
200 | xField: 'time',
201 | yField: 'value',
202 | color: ['#6193FA'],
203 | areaStyle: ({ type }) => ({
204 | fill: `l(90) 0.5:#6193FA 1:rgba(255,255,255,0.2)`
205 | }),
206 | // 抽取一个组件 Exlaination (组件注释下使用)
207 | explaination: {
208 | title: '专家分析',
209 | details: [
210 | {
211 | icon:
,
212 | title: '总体情况',
213 | description: '这里可以放几条分析结论。根据金融学理论,资产分散能降低风险。'
214 | },
215 | {
216 | icon:
,
217 | title: '值得关注',
218 | description: '这里可以放几条分析结论。资产分散能降低风险。'
219 | },
220 | {
221 | icon:
,
222 | title: '值得关注',
223 | description: '这里可以放几条分析结论。资产分散能降低风险。'
224 | },
225 | {
226 | icon:
,
227 | title: '值得关注',
228 | description: '这里可以放几条分析结论。资产分散能降低风险。'
229 | },
230 | ]
231 | }
232 | }
233 | },
234 | {
235 | tag: 'column',
236 | id: 'g',
237 | attributes: {
238 | title: '业务域报警发布',
239 | data: 'https://gw.alipayobjects.com/os/antfincdn/VpJKHWT3Yl/monitor-data1.json',
240 | isStack: true,
241 | xField: 'time',
242 | yField: 'value',
243 | seriesField: 'type',
244 | color: ['#740000', '#DC3535', '#ED4A15', '#F3971B'],
245 | legend: {
246 | position: 'top-left',
247 | },
248 | }
249 | },
250 | {
251 | tag: 'line',
252 | id: 'h',
253 | attributes: {
254 | title: '秒级总量监控',
255 | data: 'https://gw.alipayobjects.com/os/antfincdn/B%26OYH6JjXm/monitor-data1.json',
256 | xField: 'time',
257 | yField: 'value',
258 | seriesField: 'type',
259 | legend: false,
260 | isStack: false,
261 | color: ['#0362C5', '#ACBCD8', '#008CAF', '#6193FA', '#81ADFD', '#00A6CA', '#4DDCF4'],
262 | legendTable: {
263 | show: true,
264 | showColumnList: ['max', 'min']
265 | }
266 | }
267 | },
268 | {
269 | tag: 'area',
270 | id: 'i',
271 | attributes: {
272 | title: '分区秒级监控',
273 | data:
274 | 'https://gw.alipayobjects.com/os/antfincdn/dfW6g0i1Et/monitor-line-data1.json',
275 | xField: 'date',
276 | yField: 'value',
277 | seriesField: 'type',
278 | color: ['#00A6CA', '#18C1E4', '#3E7AE1', '#6193FA']
279 | }
280 | },
281 | {
282 | tag: 'area',
283 | id: 'j',
284 | attributes: {
285 | title: '分层秒级监控',
286 | data: 'https://gw.alipayobjects.com/os/antfincdn/PqzDdcD%26zL/monitor-line-data1.json',
287 | xField: 'date',
288 | yField: 'value',
289 | seriesField: 'type',
290 | meta: {
291 | value: {
292 | maxLimit: 55
293 | }
294 | },
295 | isStack: false,
296 | color: ['#6193FA', '#00A6CA',],
297 | areaStyle: ({ type }) => {
298 | return {
299 | fill: type === 'Web' ? '#6193FA' : 'transparent'
300 | }
301 | },
302 | }
303 | }
304 | ],
305 | },
306 | };
307 |
--------------------------------------------------------------------------------
/src/dashboards/dashboard-a.ts:
--------------------------------------------------------------------------------
1 | import { G2 } from '@antv/g2plot';
2 | import numeral from 'numeral';
3 |
4 | const TooltipContainerStyle = `z-index:20;display: flex;box-shadow:rgb(174, 174, 174) 0px 0px 10px; border-radius: 3px;font-size: 12px; line-height: 12px; padding: 0px 12px;pointer-events: none; padding:4px 10px;`;
5 | const TooltipMarkerStyle = `width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 8px;`;
6 |
7 | const GAUGE_1 = {
8 | percent: 0.87,
9 | appendPadding: [0, 0, 8, 0],
10 | startAngle: -Math.PI,
11 | endAngle: 0,
12 | range: {
13 | color: 'l(0) 0:#0099FF 0.25:#09ADDF 0.75:#15C8B7 1:#1EDB9A',
14 | },
15 | indicator: false,
16 | statistic: {
17 | title: {
18 | formatter: () => '目标完成度',
19 | offsetY: 24,
20 | style: {
21 | color: '#000',
22 | opacity: 0.65,
23 | fontSize: '12px',
24 | },
25 | },
26 | content: {
27 | formatter: ({ percent }) => `${(percent * 100).toFixed(0)}%`,
28 | style: {
29 | color: '#000',
30 | opacity: 0.85,
31 | fontSize: '24px',
32 | },
33 | },
34 | },
35 | };
36 |
37 | const GAUGE_2 = {
38 | percent: 0.87,
39 | radius: 1,
40 | innerRadius: 0.82,
41 | appendPadding: [0, 0, 8, 0],
42 | indicator: false,
43 | };
44 |
45 | export const reportJSON = {
46 | theme: 'light',
47 | layouts: {
48 | root: {
49 | lg: [
50 | { i: 'a', x: 0, y: 0, w: 24, h: 6 },
51 | { i: 'b', x: 0, y: 6, w: 17, h: 8 },
52 | { i: 'c', x: 17, y: 6, w: 7, h: 25 },
53 | { i: 'd', x: 0, y: 14, w: 11, h: 17 },
54 | { i: 'e', x: 11, y: 14, w: 6, h: 8 },
55 | { i: 'f', x: 11, y: 22, w: 6, h: 9 },
56 | { i: 'g', x: 0, y: 31, w: 10, h: 14 },
57 | { i: 'h', x: 10, y: 31, w: 14, h: 14 },
58 | { i: 'i', x: 0, y: 45, w: 12, h: 15 },
59 | { i: 'j', x: 12, y: 45, w: 12, h: 15 },
60 | { i: 'k', x: 0, y: 60, w: 12, h: 14 },
61 | { i: 'l', x: 12, y: 60, w: 12, h: 14 },
62 | ],
63 | xs: [
64 | { i: 'a', x: 0, y: 0, w: 12, h: 6 },
65 | { i: 'b', x: 0, y: 6, w: 12, h: 8 },
66 | { i: 'c', x: 7, y: 22, w: 5, h: 13 },
67 | { i: 'd', x: 0, y: 22, w: 7, h: 13 },
68 | { i: 'e', x: 0, y: 14, w: 6, h: 8 },
69 | { i: 'f', x: 6, y: 14, w: 6, h: 8 },
70 | { i: 'g', x: 6, y: 35, w: 6, h: 14 },
71 | { i: 'h', x: 0, y: 73, w: 6, h: 14 },
72 | { i: 'i', x: 0, y: 49, w: 12, h: 13 },
73 | { i: 'j', x: 0, y: 62, w: 12, h: 11 },
74 | { i: 'k', x: 6, y: 73, w: 6, h: 14 },
75 | { i: 'l', x: 0, y: 35, w: 6, h: 14 },
76 | ],
77 | xxs: [
78 | { x: 0, y: 0, i: 'a', w: 4, h: 16 },
79 | { x: 0, y: 16, i: 'b', w: 4, h: 13 },
80 | { x: 0, y: 47, i: 'c', w: 4, h: 13 },
81 | { x: 0, y: 60, i: 'd', w: 4, h: 13 },
82 | { x: 0, y: 29, i: 'e', w: 4, h: 9 },
83 | { x: 0, y: 38, i: 'f', w: 4, h: 9 },
84 | { x: 0, y: 73, i: 'g', w: 4, h: 14 },
85 | { x: 0, y: 125, i: 'h', w: 4, h: 14 },
86 | { x: 0, y: 101, i: 'i', w: 4, h: 13 },
87 | { x: 0, y: 114, i: 'j', w: 4, h: 11 },
88 | { x: 0, y: 139, i: 'k', w: 4, h: 14 },
89 | { x: 0, y: 87, i: 'l', w: 4, h: 14 },
90 | ],
91 | },
92 | },
93 | content: {
94 | tag: 'panel',
95 | id: 'root',
96 | attributes: {},
97 | children: [
98 | {
99 | tag: 'statistic',
100 | id: 'a',
101 | attributes: {
102 | title: '核心指标',
103 | measures: [
104 | 'uv',
105 | 'pv',
106 | 'new_users',
107 | 'latest_7_days_uv',
108 | 'latest_30_days_uv',
109 | ],
110 | meta: {
111 | uv: {
112 | alias: '今日 UV',
113 | },
114 | pv: {
115 | alias: '昨日 PV',
116 | },
117 | new_users: {
118 | alias: '新用户',
119 | },
120 | latest_7_days_uv: {
121 | alias: '近 7 日 UV',
122 | },
123 | latest_30_days_uv: {
124 | alias: '近 30 日 UV',
125 | },
126 | },
127 | data: [
128 | {
129 | uv: 79,
130 | pv: 3286,
131 | new_users: 35,
132 | latest_7_days_uv: 366,
133 | latest_30_days_uv: 1372,
134 | },
135 | ],
136 | },
137 | },
138 | {
139 | tag: 'ring-progress',
140 | id: 'b',
141 | attributes: {
142 | title: '店铺经营状况',
143 | measures: ['code1', 'code2', 'code3', 'code4'],
144 | meta: {
145 | code1: {
146 | icon:
147 | '
',
148 | },
149 | code2: {
150 | icon:
151 | "
",
152 | },
153 | code3: {
154 | icon:
155 | "
",
156 | },
157 | code4: {
158 | icon:
159 | "
",
160 | },
161 | },
162 | data: [
163 | {
164 | code1: 0.84,
165 | code2: 0.6,
166 | code3: 0.92,
167 | code4: 0.72,
168 | },
169 | ],
170 | },
171 | },
172 | {
173 | tag: 'bar',
174 | id: 'c',
175 | attributes: {
176 | title: '产品好评度排行',
177 | /** 非 G2Plot 树形,自定义条形图展示样式 */
178 | styleType: 'rank',
179 | data:
180 | 'https://gw.alipayobjects.com/os/antfincdn/R%26O2e0Z0w1/chanpinhaopingdupaihang-data.json',
181 | xField: 'value',
182 | yField: 'type',
183 | barStyle: { lineCap: 'round' },
184 | barBackground: { style: { fill: 'rgba(0,0,0,0.05)', radius: 10 } },
185 | minBarWidth: 10,
186 | maxBarWidth: 10,
187 | xAxis: false,
188 | yAxis: false,
189 | label: false,
190 | interactions: [{ type: 'active-region', enable: false }],
191 | tooltip: {
192 | showCrosshairs: false,
193 | showTitle: false,
194 | itemTpl: `
195 |
196 | {title}:
197 | {value}
198 | `,
199 | },
200 | },
201 | },
202 | {
203 | tag: 'column',
204 | id: 'd',
205 | attributes: {
206 | title: '顾客职业分布',
207 | data:
208 | 'https://gw.alipayobjects.com/os/antfincdn/PC3daFYjNw/column-data.json',
209 | xField: 'city',
210 | yField: 'value',
211 | seriesField: 'type',
212 | isGroup: 'true',
213 | columnStyle: {
214 | radius: [2, 2, 0, 0],
215 | },
216 | xAxis: { title: { text: '职业' } },
217 | yAxis: { title: { text: '顾客人数' } },
218 | meta: {
219 | value: {
220 | formatter: v => numeral(v).format('0,0'),
221 | },
222 | },
223 | minColumnWidth: 6,
224 | maxColumnWidth: 12,
225 | dodgePadding: 1,
226 | },
227 | },
228 | {
229 | tag: 'gauge',
230 | id: 'e',
231 | attributes: {
232 | title: '年度销售目标',
233 | options: [
234 | {
235 | ...GAUGE_1,
236 | radius: 1,
237 | innerRadius: 0.85,
238 | type: 'meter',
239 | meter: {
240 | steps: 30,
241 | stepRatio: 0.88,
242 | },
243 | },
244 | {
245 | ...GAUGE_1,
246 | innerRadius: 0.85,
247 | type: '',
248 | },
249 | ],
250 | },
251 | },
252 | {
253 | tag: 'gauge',
254 | id: 'f',
255 | attributes: {
256 | title: '店铺卫生状况',
257 | options: [
258 | {
259 | ...GAUGE_2,
260 | type: 'meter',
261 | meter: {
262 | steps: 4,
263 | stepRatio: 0.97,
264 | },
265 | axis: false,
266 | statistic: false,
267 | range: {
268 | ticks: [0, 0.25, 0.5, 0.75, 1],
269 | color: [
270 | 'r(0,0,1) 0:#FAAD14 1:#F4664A',
271 | 'r(0.1,1,1) 0:#FAAD14 1:#CBFF49',
272 | 'r(0,0,1) 0:#CEEE27 1:#30BF78',
273 | 'r(0,0,1) 0:#A0D911 1:#30BF78',
274 | ],
275 | },
276 | annotations: [
277 | {
278 | // fixme 完善 位置逻辑
279 | type: 'html',
280 | // 圆弧角度是 3 / 4 * Math.PI * 2
281 | position: ['50%', `${(Math.sqrt(2) / 8 + 0.5) * 100}%`],
282 | html: (container, view) => {
283 | const coordiante = view.views[0].getCoordinate();
284 | const radius =
285 | coordiante.getRadius() *
286 | coordiante.radius *
287 | coordiante.innerRadius;
288 | const size = radius * 1.5;
289 | const markerSize = 10;
290 | const offsetX = radius - markerSize / 2;
291 | // positionY: (Math.sqrt(2) / 8 + 0.5)
292 | const offsetY = markerSize * (Math.sqrt(2) / 8 + 0.5);
293 | return `
294 |
301 |
302 |
优秀
303 |
卫生评级
304 |
`;
305 | },
306 | },
307 | ],
308 | },
309 | // todo
310 | {
311 | ...GAUGE_2,
312 | type: '',
313 | axis: false,
314 | statistic: {},
315 | range: {
316 | ticks: [0, GAUGE_2.percent, 1],
317 | color:
318 | 'l(0) 0:#F4664A 0.2:#FAAD14 0.4:#CBFF49 0.6:#CEEE27 0.8:#A0D911 1:#30BF78',
319 | },
320 | annotations: [
321 | {
322 | type: 'html',
323 | position: ['50%', `${(Math.sqrt(2) / 8 + 0.5) * 100}%`],
324 | html: () => {
325 | return `
`;
329 | },
330 | },
331 | ],
332 | },
333 | ],
334 | },
335 | },
336 | {
337 | tag: 'radial-bar',
338 | id: 'g',
339 | attributes: {
340 | title: '店铺服务满意度',
341 | data: [
342 | { type: '不好', value: 100 },
343 | { type: '还可以', value: 400 },
344 | { type: '不太好', value: 600 },
345 | { type: '很满意', value: 800 },
346 | ],
347 | xField: 'type',
348 | yField: 'value',
349 | colorField: 'type',
350 | radius: 0.96,
351 | innerRadius: 0.55,
352 | barBackground: { style: { fill: 'rgb(0,0,0)', fillOpacity: 0.05 } },
353 | barStyle: { lineCap: 'round' },
354 | xAxis: false,
355 | // 关闭 tooltip,默认使用 annotations 展示所有信息
356 | tooltip: false,
357 | annotations: [
358 | {
359 | type: 'html',
360 | position: ['50%', '0%'],
361 | html: (container, view: G2.View) => {
362 | const width = 140;
363 | container.style.transform = `translate(${
364 | -width - 20
365 | }px, -10px)`;
366 | const models = view.geometries[0].elements.map(ele =>
367 | ele.getModel()
368 | );
369 |
370 | let content = '';
371 | // 降序
372 | models
373 | .sort((a, b) => b.data['value'] - a.data['value'])
374 | .forEach((model, index) => {
375 | content += `
376 |
377 |
378 | ${model.data['type']}
379 |
380 | ${model.data['value']}
381 |
`;
382 | });
383 | return `
`;
384 | },
385 | },
386 | {
387 | type: 'html',
388 | position: ['50%', '50%'],
389 | html: (container, view) => {
390 | const width = view.getCoordinate().getRadius() * 0.4;
391 | container.style.transform = `translate(-50%, -${width}px)`;
392 | return `
`;
393 | },
394 | },
395 | {
396 | type: 'html',
397 | position: ['50%', '50%'],
398 | html: (container, view) => {
399 | const width = view.getCoordinate().getRadius();
400 | // 🧙♀️ 魔法调整
401 | container.style.transform =
402 | width < 80
403 | ? 'translate(-50%, 0px) scale(0.8)'
404 | : 'translate(-50%, 8px)';
405 | const sum = view.getData().reduce((a, b) => a + b.value, 0);
406 | return `
407 | ${sum}
408 | 人
409 |
`;
410 | },
411 | },
412 | ],
413 | // 关闭元素激活交互
414 | interactions: [{ type: 'element-active', enable: false }],
415 | },
416 | },
417 | {
418 | tag: 'sankey',
419 | id: 'h',
420 | attributes: {
421 | title: '订单来源',
422 | data: [
423 | { source: '首页推荐', target: '跳转', value: 25 },
424 | { source: '我的', target: '跳转', value: 20 },
425 | { source: '财富', target: '跳转', value: 15 },
426 | { source: '公益', target: '跳转', value: 12 },
427 | { source: '其他', target: '跳转', value: 7 },
428 |
429 | { source: '跳转', target: '消息', value: 32 },
430 | { source: '跳转', target: '商家生活号', value: 28.8 },
431 | { source: '跳转', target: '其他渠道', value: 16.4 },
432 | ],
433 | sourceField: 'source',
434 | targetField: 'target',
435 | weightField: 'value',
436 | nodeWidthRatio: 0.008,
437 | nodePaddingRatio: 0.03,
438 | },
439 | },
440 | {
441 | tag: 'scatter',
442 | id: 'i',
443 | attributes: {
444 | title: '店内环境风格喜好',
445 | data: [
446 | { x: 1, y: 2, value: 10, type: '韩式清新', percentage: 0.048 },
447 | {
448 | x: 5,
449 | y: 1.5,
450 | value: 90,
451 | type: '北欧风格',
452 | percentage: 0.429,
453 | },
454 | { x: 3, y: 1, value: 60, type: '日式极简', percentage: 0.286 },
455 | { x: 8, y: 2, value: 30, type: '新中式', percentage: 0.143 },
456 | {
457 | x: 9,
458 | y: 0.5,
459 | value: 20,
460 | type: '美式复古',
461 | percentage: 0.095,
462 | },
463 | ],
464 | xField: 'x',
465 | yField: 'y',
466 | colorField: 'type',
467 | sizeField: 'value',
468 | size: [5, 100],
469 | shape: 'circle',
470 | meta: {
471 | x: { max: 10, min: 0 },
472 | y: { max: 3, min: 0 },
473 | value: { max: 90, min: 0 },
474 | percentage: {
475 | alias: '人数占比',
476 | formatter: v => `${(v * 100).toFixed(0)}%`,
477 | },
478 | },
479 | yAxis: false,
480 | xAxis: false,
481 | state: {
482 | active: {
483 | style: {
484 | shadowColor: 'rgba(0,0,0,0.25)',
485 | shadowBlur: 20,
486 | lineWidth: 0,
487 | },
488 | },
489 | },
490 | interactions: [{ type: 'element-active' }],
491 | pointStyle: {
492 | lineWidth: 0,
493 | },
494 | legend: { position: 'top-left' },
495 | tooltip: {
496 | showCrosshairs: false,
497 | containerTpl:
498 | '
',
499 | fields: ['percentage'],
500 | },
501 | label: {
502 | layout: [{ type: 'limit-in-shape' }],
503 | offsetY: 12,
504 | style: {
505 | fontSize: 18,
506 | textAlign: 'center',
507 | fill: '#fff',
508 | fontWeight: 500,
509 | },
510 | formatter: datum => `${(datum.percentage * 100).toFixed(0)}%`,
511 | },
512 | },
513 | },
514 | {
515 | tag: 'area',
516 | id: 'j',
517 | attributes: {
518 | title: '年度销售额趋势图',
519 | data:
520 | 'https://gw.alipayobjects.com/os/bmw-prod/360c3eae-0c73-46f0-a982-4746a6095010.json',
521 | xField: 'timePeriod',
522 | yField: 'value',
523 | xAxis: {
524 | range: [0.02, 0.98],
525 | },
526 | smooth: true,
527 | },
528 | },
529 | {
530 | tag: 'sankey',
531 | id: 'k',
532 | attributes: {
533 | title: '店内促销活动参与情况',
534 | sourceField: 'source',
535 | targetField: 'target',
536 | weightField: 'value',
537 | nodeWidthRatio: 0.02,
538 | nodePaddingRatio: 0.05,
539 | data: [
540 | { source: '参与游客', target: '游戏一', value: 16000 },
541 | { source: '参与游客', target: '游戏二', value: 19000 },
542 | { source: '参与游客', target: '游戏三', value: 18800 },
543 |
544 | { source: '游戏一', target: '全部通关', value: 2500 },
545 | { source: '游戏一', target: '通关过半', value: 9500 },
546 | { source: '游戏一', target: '未通关', value: 4000 },
547 |
548 | { source: '游戏二', target: '全部通关', value: 2500 },
549 | { source: '游戏二', target: '通关过半', value: 12500 },
550 | { source: '游戏二', target: '未通关', value: 4000 },
551 |
552 | { source: '游戏三', target: '全部通关', value: 2500 },
553 | { source: '游戏三', target: '通关过半', value: 12500 },
554 | { source: '游戏三', target: '未通关', value: 3800 },
555 | ],
556 | },
557 | },
558 | {
559 | tag: 'pie',
560 | id: 'l',
561 | attributes: {
562 | title: '基础环图',
563 | angleField: 'value',
564 | colorField: 'type',
565 | data: [
566 | { type: '分类一', value: 230 },
567 | { type: '分类二', value: 160 },
568 | { type: '分类三', value: 158 },
569 | { type: '分类四', value: 120 },
570 | ],
571 | radius: 0.85,
572 | innerRadius: 0.75,
573 | legend: { ' position': 'right-center' },
574 | label: false,
575 | pieStyle: { lineCap: 'round', lineWidth: 0 },
576 | interactions: [{ type: 'element-active' }],
577 | state: {
578 | active: {
579 | style: {
580 | shadowColor: 'rgba(0,0,0,0.25)',
581 | shadowBlur: 20,
582 | lineWidth: 0,
583 | },
584 | },
585 | },
586 | statistic: {
587 | title: {
588 | customHtml: (container, view) => {
589 | const width = view.getCoordinate().getRadius() * 0.4;
590 | container.style.transform = `translate(-50%, -${width}px)`;
591 | return `
`;
592 | },
593 | },
594 | content: {
595 | customHtml: (container, view, datum, data) => {
596 | const width = view.getCoordinate().getRadius();
597 | // 🧙♀️ 魔法调整
598 | container.style.transform =
599 | width < 80
600 | ? 'translate(-50%, 0px) scale(0.8)'
601 | : 'translate(-50%, 8px)';
602 | const sum = view.getData().reduce((a, b) => a + b.value, 0);
603 | return `
604 | ${sum}
605 | 人
606 |
`;
607 | },
608 | },
609 | },
610 | },
611 | },
612 | ],
613 | },
614 | };
615 |
--------------------------------------------------------------------------------