0%

ECharts旭日图及轮播效果实现

最近使用了 sunburst 旭日图,但 ECharts 的配置项实在是太多,边学习便记录。以官网 gallery 中的推荐 demo——2018 豆瓣中国大陆影视剧评分排行——为例,分析 sunburst 旭日图类型的实现,修改了原 demo 的一些错误和冗余,并给图表添加自定义的动态轮播效果,效果如下所示:

基本结构

引入 ECharts

首先,参照 ECharts 官方入门引导——5 分钟上手 ECharts,通过jsDelivr CDN 方式引入 echarts.min.js

1
<script src="https://cdn.jsdelivr.net/npm/echarts@4.6.0/dist/echarts.min.js"></script>

页面结构

其次,构建基础的 HTML 标签和 CSS。为了实现轮播,对原 demo 进行了修改,布局使用的是 CSS3 的Flex 布局,将页面分成上下两部分,div#detail-container 部分存放轮播内容,div#echarts-container 部分存放旭日图图表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
div#container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
background: #2e2733;
}
div#detail-container {
width: 100%;
height: 20%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
div#detail-container .kind {
color: #ffae57;
}
div#detail-container .title {
color: #ff7853;
font-size: 120%;
font-weight: bold;
}
div#echarts-container {
width: 100%;
height: 100%;
}
</style>
<div id="container">
<div id="detail-container"></div>
<div id="echarts-container"></div>
</div>

ECharts API

接着参照入门引导,将 EChart init 实例化setOption设定配置项

1
2
3
4
5
6
7
8
// 基于准备好的dom,初始化echarts实例
let chartSunburst = echarts.init(document.getElementById('echarts-container'));
// 指定图表的配置项和数据
let option = {
// ...配置项内容
};
// 使用刚指定的配置项和数据显示图表。
chartSunburst.setOption(option);

旭日图配置

ECharts 是一个配置式的库,API 的文档内容比较短,而所有的图表的配置项非常之长。配置项是 ECharts 的核心。

准备工作

颜色

colors 主要是给后续代码做取色用,同时也是配置项中的调色盘颜色列表,如果图表没有设置颜色,则会依次循环从该列表中取颜色作为系列颜色。

itemStyle 中给影视剧星级从 15 都分配了不同的颜色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 颜色序列
const colors = ['#FFAE57', '#FF7853', '#EA5151', '#CC3F57', '#9A2555'];
// 背景颜色
const bgColor = '#2E2733';
// 给不同星级分配不同颜色
let itemStyle = {
star5: {
color: colors[0]
},
star4: {
color: colors[1]
},
star3: {
color: colors[2]
},
star2: {
color: colors[3]
},
star1: {
color: colors[4]
}
};

原数据

sunburst 旭日图类型的数据应该是树状的,每一级都含有一个 name 属性作为标签名,可选一个 value(值)itemStyle(数据样式配置项)label(标签配置项),如果不是最后一级,都应该有一个 children(子树)

代码所示数据举例,级别为电视剧 > 现代 > 5☆ > 大江大河

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
// sunburst 旭日图树状数据

let data = [
{
name: '电视剧',
itemStyle: {
// normal: {
color: colors[1]
// }
},
children: [
{
name: '现代',
children: [
{
name: '5☆',
children: [
{
name: '大江大河'
},
{
name: '疯人院'
},
{
name: '天坑鹰猎'
}
]
},
{
name: '4☆',
children: [
{
name: 'SCI谜案集'
},
{
name: '古董局中局'
},
{
name: '乡村爱情协奏曲'
}
]
},
{
name: '3☆',
children: [
{
name: '上海女子图鉴'
}
]
}
]
},
{
name: '古装',
children: [
{
name: '5☆',
children: [
{
name: '天盛长歌'
}
]
},
{
name: '4☆',
children: [
{
name: '小戏骨:水浒传'
},
{
name: '香蜜沉沉烬如霜'
}
]
},
{
name: '3☆',
children: [
{
name: '知否知否应是绿肥红瘦'
}
]
}
]
}
]
},
{
name: '电影',
itemStyle: {
color: colors[2]
},
children: [
{
name: '喜剧',
children: [
{
name: '5☆',
children: [
{
name: '我不是药神'
}
]
},
{
name: '4☆',
children: [
{
name: '无名之辈'
},
{
name: '阿浪的远方'
}
]
},
{
name: '3☆',
children: [
{
name: '一出好戏'
}
]
}
]
},
{
name: '剧情',
children: [
{
name: '5☆',
children: [
{
name: '无双'
}
]
},
{
name: '4☆',
children: [
{
name: '大象席地而坐'
},
{
name: '风中有朵雨做的云'
},
{
name: '过春天'
}
]
},
{
name: '3☆',
children: [
{
name: '无问西东'
}
]
}
]
},
{
name: '爱情',
children: [
{
name: '5☆',
children: [
{
name: '江湖儿女'
}
]
},
{
name: '4☆',
children: [
{
name: '地球最后的夜晚'
},
{
name: '你好之华'
}
]
},
{
name: '3☆'
},
{
name: '2☆',
children: [
{
name: '后来的我们'
}
]
}
]
},
{
name: '动作',
children: [
{
name: '4☆',
children: [
{
name: '红海行动'
},
{
name: '影'
},
{
name: '动物世界'
}
]
}
]
},
{
name: '动画',
children: [
{
name: '5☆',
children: [
{
name: '夜思'
}
]
},
{
name: '4☆',
children: [
{
name: '切尔诺贝利之春'
},
{
name: '女他'
}
]
},
{
name: '3☆',
children: [
{
name: '风雨咒'
}
]
}
]
},
{
name: '惊悚',
children: [
{
name: '4☆',
children: [
{
name: '灵魂摆渡·黄泉'
}
]
}
]
},
{
name: '武侠',
children: [
{
name: '3☆',
children: [
{
name: '夺命剑之风云再起'
}
]
},
{
name: '2☆',
children: [
{
name: '狄仁杰之四大天王'
}
]
}
]
}
]
}
];

处理数据

上述的原始数据缺少了必填项,每个叶子节点处的 name 必须配有一个 value,有 value 才能给其分配一个弧度;其次,demo 作者想把不同星级的影视剧使用不同颜色区分开,所以还需要给星级节点和叶子节点都设置一个 itemStyle。下述代码就是四层循环实现这两个目的。

需要注意的地方:

  • 第一,修改了 style 属性,从原 demo 的立即执行函数改为了更简单的拼凑字符串直接取色;
  • 第二,去除了 label 下的 downplay,原作者应该是想给标签设置 downplay,但是根据配置项手册这样是不生效的;
  • 第三,去除了 bookScorebookScoreId 相关的内容,我猜作者可能是想用这两个属性来给非叶子节点配置 value,后来发现不是必需的,就没有写完。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// 循环处理数据,为了给不同的星级做区分
for (let j = 0; j < data.length; ++j) {
// level1是电视剧分类下古装、现代这个级别的数组
// [
// {
// name: "现代",
// children: [...]
// },
// {
// name: "古装",
// children: [...]
// }
// ];
let level1 = data[j].children;

// level1中继续循环
for (let i = 0; i < level1.length; ++i) {
// block是现代分类下的5☆4☆2☆级别的数组
// [
// {
// name: "5☆",
// children: [
// {
// name: "大江大河"
// },
// {
// name: "疯人院"
// },
// {
// name: "天坑鹰猎"
// }
// ]
// },
// {
// name: "4☆",
// children: [
// {
// name: "SCI谜案集"
// },
// {
// name: "古董局中局"
// },
// {
// name: "乡村爱情协奏曲"
// }
// ]
// },
// {
// name: "3☆",
// children: [
// {
// name: "上海女子图鉴"
// }
// ]
// }
// ];
let block = level1[i].children;

for (let star = 0; star < block.length; ++star) {
// 对demo进行了优化,直接拼凑字符串从itemStyle中取对应颜色
style = itemStyle['star' + parseInt(block[star].name)];
// 给不同星级文字label设置不同的颜色
block[star].label = {
color: style.color
};
// 如果该星级下有影视剧,就继续对下级循环
if (block[star].children) {
// 继续给星级下级分配相同颜色
style = {
opacity: 1,
color: style.color
};
// 循环
block[star].children.forEach(book => {
// 同一星级下的每个影视剧value都设为1,用于平分扇形
book.value = 1;
book.itemStyle = style;
book.label = {
color: style.color
};
});
}
}
level1[i].itemStyle = {
color: data[j].itemStyle.color
};
}
}

option 配置

option 的配置才是 ECharts 的核心,在这个 demo 中,大部分的配置项都可以根据名字一眼看懂,把主要的几个配置项的文档列出来:

代码如下,需要注意的一点是,在旭日图中如果几个配置项对某一项样式同时做出了配置,那么优先级是:downplay 或 highlight > data > levels > series

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
let option = {
backgroundColor: bgColor,
// 设置调色盘颜色
// https://www.echartsjs.com/zh/option.html#color
color: colors,
// https://www.echartsjs.com/zh/option.html#series-sunburst
series: [
{
// 旭日图
type: 'sunburst',
// 中心位置
center: ['50%', '50%'],
// 数据来源
data: data,
// 排序时,如果是第一层深度,靠value排序,其余情况dataIndex排序
// https://www.echartsjs.com/zh/option.html#series-sunburst.sort
sort: (a, b) => {
if (a.depth === 1) {
return b.getValue() - a.getValue();
} else {
return a.dataIndex - b.dataIndex;
}
},
// 每一个标签样式
// https://www.echartsjs.com/zh/option.html#series-sunburst.label
label: {
// 径向旋转
rotate: 'radial',
color: bgColor,
opacity: 0.9
},
// 每一项的样式
// https://www.echartsjs.com/zh/option.html#series-sunburst.itemStyle
itemStyle: {
borderColor: bgColor,
borderWidth: 2,
opacity: 0.9
},
// 未选中的样式
// https://www.echartsjs.com/zh/option.html#series-sunburst.downplay
downplay: {
itemStyle: {
opacity: 0.7
},
label: {
opacity: 0.7
}
},
// 选中的样式
// https://www.echartsjs.com/zh/option.html#series-sunburst.highlight
highlight: {
itemStyle: {
opacity: 1
},
label: {
opacity: 1
}
},
// 给每个级别单独设置
// https://www.echartsjs.com/zh/option.html#series-sunburst.levels
levels: [
// 这个空对象其实是第0级
{},
// 第1级
{
// r0时内半径,r是外半径
r0: 0,
r: 40,
label: {
rotate: 0
}
},
// 第2级
{
r0: 40,
r: 105
},
// 第3级
{
r0: 115,
r: 140,
// 单独给第三圈设置了边框样式和背景样式
itemStyle: {
shadowBlur: 2,
shadowColor: colors[2],
color: 'transparent'
},
// 给该层设置切向旋转
label: {
rotate: 'tangential',
fontSize: 10,
color: colors[0]
}
},
// 第4级
{
r0: 140,
r: 145,
itemStyle: {
// 烟雾状的blur
shadowBlur: 80,
shadowColor: colors[0]
},
label: {
// 最外圈把标签设置到了最外层
position: 'outside',
textShadowBlur: 5,
textShadowColor: '#333'
}
}
]
}
]
};

轮播效果

经过上述已经能实现原 demo 的样式,在这里继续给 demo 添加轮播效果。

数据扁平化

因为定时器按固定时间间隔遍历对象的叶子节点很麻烦,所以在这里先把数据四层循环由对象扁平化为数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 首先把整个树状结构的数据扁平化,形成一个由level1、2、3、4组成的数组
let dataArrSorted = [];
data.forEach(level1 => {
if (level1.children) {
level1.children.forEach(level2 => {
if (level2.children) {
level2.children.forEach(level3 => {
if (level3.children) {
level3.children.forEach(level4 => {
dataArrSorted.push({
level1: level1.name,
level2: level2.name,
level3: level3.name,
level4: level4.name
});
});
}
});
}
});
}
});

添加事件监听

监听Echarts 的旭日图实例 chartSunburst 上的 highlight 事件,并把回调的参数拼凑 dom 片段插入 body

1
2
3
4
5
6
// 监听chartSunburst的highlight事件,在回调函数中拿到params组成一个dom片段插入
chartSunburst.on('highlight', params => {
document.querySelector(
'#detail-container'
).innerHTML = `<p class="kind">${params.level1} > ${params.level2} > ${params.level3}</p><p class="title">${params.level4}</p>`;
});

定时器派发事件

使用 setInterval 定时器,每两秒派发一个 highlight 事件namedataArrSorted[i].level4,并把整个 dataArrSorted[i]解构成参数传出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 设置一个定时器,每2秒派发一个highlight事件,name是level4,再把整个dataArrSorted[i]对象解构进去发送
i = 0;
const key = setInterval(() => {
if (i < dataArrSorted.length) {
chartSunburst.dispatchAction({
type: 'highlight',
name: dataArrSorted[i].level4,
...dataArrSorted[i]
});
} else {
// 当循环完成,清除定时器
clearInterval(key);
}
i++;
}, 2000);

全部代码

全部代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.jsdelivr.net/npm/echarts@4.6.0/dist/echarts.min.js"></script>
<title>echarts sunburst旭日图轮播</title>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
div#container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
background: #2e2733;
}
div#detail-container {
width: 100%;
height: 20%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
div#detail-container .kind {
color: #ffae57;
}
div#detail-container .title {
color: #ff7853;
font-size: 120%;
font-weight: bold;
}
div#echarts-container {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="container">
<div id="detail-container"></div>
<div id="echarts-container"></div>
</div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
let chartSunburst = echarts.init(
document.getElementById('echarts-container')
);
// 指定图表的配置项和数据
// 颜色序列
const colors = ['#FFAE57', '#FF7853', '#EA5151', '#CC3F57', '#9A2555'];
// 背景颜色
const bgColor = '#2E2733';
// 给不同星级分配不同颜色
let itemStyle = {
star5: {
color: colors[0]
},
star4: {
color: colors[1]
},
star3: {
color: colors[2]
},
star2: {
color: colors[3]
},
star1: {
color: colors[4]
}
};
// sunburst 旭日图树状数据
// https://www.echartsjs.com/zh/option.html#series-sunburst.data
let data = [
{
name: '电视剧',
itemStyle: {
// normal: {
color: colors[1]
// }
},
children: [
{
name: '现代',
children: [
{
name: '5☆',
children: [
{
name: '大江大河'
},
{
name: '疯人院'
},
{
name: '天坑鹰猎'
}
]
},
{
name: '4☆',
children: [
{
name: 'SCI谜案集'
},
{
name: '古董局中局'
},
{
name: '乡村爱情协奏曲'
}
]
},
{
name: '3☆',
children: [
{
name: '上海女子图鉴'
}
]
}
]
},
{
name: '古装',
children: [
{
name: '5☆',
children: [
{
name: '天盛长歌'
}
]
},
{
name: '4☆',
children: [
{
name: '小戏骨:水浒传'
},
{
name: '香蜜沉沉烬如霜'
}
]
},
{
name: '3☆',
children: [
{
name: '知否知否应是绿肥红瘦'
}
]
}
]
}
]
},
{
name: '电影',
itemStyle: {
color: colors[2]
},
children: [
{
name: '喜剧',
children: [
{
name: '5☆',
children: [
{
name: '我不是药神'
}
]
},
{
name: '4☆',
children: [
{
name: '无名之辈'
},
{
name: '阿浪的远方'
}
]
},
{
name: '3☆',
children: [
{
name: '一出好戏'
}
]
}
]
},
{
name: '剧情',
children: [
{
name: '5☆',
children: [
{
name: '无双'
}
]
},
{
name: '4☆',
children: [
{
name: '大象席地而坐'
},
{
name: '风中有朵雨做的云'
},
{
name: '过春天'
}
]
},
{
name: '3☆',
children: [
{
name: '无问西东'
}
]
}
]
},
{
name: '爱情',
children: [
{
name: '5☆',
children: [
{
name: '江湖儿女'
}
]
},
{
name: '4☆',
children: [
{
name: '地球最后的夜晚'
},
{
name: '你好之华'
}
]
},
{
name: '3☆'
},
{
name: '2☆',
children: [
{
name: '后来的我们'
}
]
}
]
},
{
name: '动作',
children: [
{
name: '4☆',
children: [
{
name: '红海行动'
},
{
name: '影'
},
{
name: '动物世界'
}
]
}
]
},
{
name: '动画',
children: [
{
name: '5☆',
children: [
{
name: '夜思'
}
]
},
{
name: '4☆',
children: [
{
name: '切尔诺贝利之春'
},
{
name: '女他'
}
]
},
{
name: '3☆',
children: [
{
name: '风雨咒'
}
]
}
]
},
{
name: '惊悚',
children: [
{
name: '4☆',
children: [
{
name: '灵魂摆渡·黄泉'
}
]
}
]
},
{
name: '武侠',
children: [
{
name: '3☆',
children: [
{
name: '夺命剑之风云再起'
}
]
},
{
name: '2☆',
children: [
{
name: '狄仁杰之四大天王'
}
]
}
]
}
]
}
];
// 循环处理数据,为了给不同的星级做区分
for (let j = 0; j < data.length; ++j) {
// level1是电视剧分类下古装、现代这个级别的数组
// [
// {
// name: "现代",
// children: [...]
// },
// {
// name: "古装",
// children: [...]
// }
// ];
let level1 = data[j].children;

// level1中继续循环
for (let i = 0; i < level1.length; ++i) {
// block是现代分类下的5☆4☆2☆级别的数组
// [
// {
// name: "5☆",
// children: [
// {
// name: "大江大河"
// },
// {
// name: "疯人院"
// },
// {
// name: "天坑鹰猎"
// }
// ]
// },
// {
// name: "4☆",
// children: [
// {
// name: "SCI谜案集"
// },
// {
// name: "古董局中局"
// },
// {
// name: "乡村爱情协奏曲"
// }
// ]
// },
// {
// name: "3☆",
// children: [
// {
// name: "上海女子图鉴"
// }
// ]
// }
// ];
let block = level1[i].children;

for (let star = 0; star < block.length; ++star) {
// 对demo进行了优化,直接拼凑字符串从itemStyle中取对应颜色
style = itemStyle['star' + parseInt(block[star].name)];
// 给不同星级文字label设置不同的颜色
block[star].label = {
color: style.color
};
// 如果该星级下有影视剧,就继续对下级循环
if (block[star].children) {
// 继续给星级下级分配相同颜色
style = {
opacity: 1,
color: style.color
};
// 循环
block[star].children.forEach(book => {
// 同一星级下的每个影视剧value都设为1,用于平分扇形
book.value = 1;
book.itemStyle = style;
book.label = {
color: style.color
};
});
}
}
level1[i].itemStyle = {
color: data[j].itemStyle.color
};
}
}
let option = {
backgroundColor: bgColor,
// 设置调色盘颜色
// https://www.echartsjs.com/zh/option.html#color
color: colors,
// https://www.echartsjs.com/zh/option.html#series-sunburst
series: [
{
// 旭日图
type: 'sunburst',
// 中心位置
center: ['50%', '50%'],
// 数据来源
data: data,
// 排序时,如果是第一层深度,靠value排序,其余情况dataIndex排序
// https://www.echartsjs.com/zh/option.html#series-sunburst.sort
sort: (a, b) => {
if (a.depth === 1) {
return b.getValue() - a.getValue();
} else {
return a.dataIndex - b.dataIndex;
}
},
// 每一个标签样式
// https://www.echartsjs.com/zh/option.html#series-sunburst.label
label: {
// 径向旋转
rotate: 'radial',
color: bgColor,
opacity: 0.9
},
// 每一项的样式
// https://www.echartsjs.com/zh/option.html#series-sunburst.itemStyle
itemStyle: {
borderColor: bgColor,
borderWidth: 2,
opacity: 0.9
},
// 未选中的样式
// https://www.echartsjs.com/zh/option.html#series-sunburst.downplay
downplay: {
itemStyle: {
opacity: 0.7
},
label: {
opacity: 0.7
}
},
// 选中的样式
// https://www.echartsjs.com/zh/option.html#series-sunburst.highlight
highlight: {
itemStyle: {
opacity: 1
},
label: {
opacity: 1
}
},
// 给每个级别单独设置
// https://www.echartsjs.com/zh/option.html#series-sunburst.levels
levels: [
// 这个空对象其实是第0级
{},
// 第1级
{
// r0时内半径,r是外半径
r0: 0,
r: 40,
label: {
rotate: 0
}
},
// 第2级
{
r0: 40,
r: 105
},
// 第3级
{
r0: 115,
r: 140,
// 单独给第三圈设置了边框样式和背景样式
itemStyle: {
shadowBlur: 2,
shadowColor: colors[2],
color: 'transparent'
},
// 给该层设置切向旋转
label: {
rotate: 'tangential',
fontSize: 10,
color: colors[0]
}
},
// 第4级
{
r0: 140,
r: 145,
itemStyle: {
// 烟雾状的blur
shadowBlur: 80,
shadowColor: colors[0]
},
label: {
// 最外圈把标签设置到了最外层
position: 'outside',
textShadowBlur: 5,
textShadowColor: '#333'
}
}
]
}
]
};
// 使用刚指定的配置项和数据显示图表。
chartSunburst.setOption(option);
// 下面是轮播效果
// 首先把整个树状结构的数据扁平化,形成一个由level1、2、3、4组成的数组
let dataArrSorted = [];
data.forEach(level1 => {
if (level1.children) {
level1.children.forEach(level2 => {
if (level2.children) {
level2.children.forEach(level3 => {
if (level3.children) {
level3.children.forEach(level4 => {
dataArrSorted.push({
level1: level1.name,
level2: level2.name,
level3: level3.name,
level4: level4.name
});
});
}
});
}
});
}
});
// https://www.echartsjs.com/zh/api.html#echartsInstance.on
// 监听chartSunburst的highlight事件,在回调函数中拿到params组成一个dom片段插入
chartSunburst.on('highlight', params => {
document.querySelector(
'#detail-container'
).innerHTML = `<p class="kind">${params.level1} > ${params.level2} > ${params.level3}</p><p class="title">${params.level4}</p>`;
});
// 设置一个定时器,每2秒派发一个highlight事件,name是level4,再把整个dataArrSorted[i]对象解构进去发送
// https://www.echartsjs.com/zh/api.html#action.highlight
i = 0;
const key = setInterval(() => {
if (i < dataArrSorted.length) {
chartSunburst.dispatchAction({
type: 'highlight',
name: dataArrSorted[i].level4,
...dataArrSorted[i]
});
} else {
// 当循环完成,清除定时器
clearInterval(key);
}
i++;
}, 2000);
</script>
</body>
</html>
👆 全文结束,棒槌时间到 👇