前言
接到一個需求,需要展示一個橫向的柱狀圖,按數量從大到小排序,并定時刷新
使用react配合echarts進行實現。
react引入echarts
import React, { useEffect, useRef } from 'react';
import * as echarts from 'echarts';
import DeviceApi from '@/api/screen/DeviceApi';const CenterRank = (props) => {const chartRef = useRef(null);const initEcharts = () => {if (chartRef.current) {const chart = echarts.init(chartRef.current);const option = {legend: {show: true},grid: { //控制圖形大小top: '12%',left: '3%',right: '8%',bottom: '3%',containLabel: true},xAxis: {max: 'dataMax',type: 'value',boundaryGap: [0, 0.01],axisLine: {show: false},axisTick: {show: false},splitLine: {show: false},axisLabel: {show: false}},yAxis: [{type: 'category',data: [],inverse: true,animationDuration: 0,animationDurationUpdate: 500,axisLabel: {show: true,inside: true,interval: 0,splitNumber: 50,textStyle: {color: '#9FFFFD',verticalAlign: 'bottom',fontSize: '0.8rem',align: 'left',padding: [0, 0, 8, -5] //y軸在柱子上方},formatter: function (value) {const top = value.split(' ')[0];const center = value.split(' ')[1];if (value.startsWith("Top1") || value.startsWith("Top2") || value.startsWith("Top3")) {return '{' + top + '|' + top + '}' + ' {center|' + center + '}';} else {return '{other|' + top + '}' + ' {center|' + center + '}';}},rich: { //富文本樣式,配置Top1 2 3的不同樣式Top1: {padding: 2,color: '#FA5151',backgroundColor: 'rgba(250,81,81,0.24)',},Top2: {padding: 2,color: '#FF8F1F',backgroundColor: 'rgba(255,143,31,0.24)',},Top3: {padding: 2,color: '#FFC300',backgroundColor: 'rgba(255,195,0,0.24)',},other: {padding: 2,color: '#9FFFFD',backgroundColor: 'rgba(159,255,253,0.24)',},}},axisLine: {show: false},axisTick: {show: false},splitLine: {show: false}},{ //配兩個y軸,可以做出label在柱子末端展示的效果type: 'category',position: 'top',data: [],axisLabel: {show: true,color: '#fff',formatter: (value, index) => {return `${value}h`;},},axisLine: {show: false},axisTick: {show: false},},],series: [{realtimeSort: true,type: 'bar',data: [],label: {show: false,position: 'right',valueAnimation: true,formatter: '{c}h',fontSize: '0.8rem',color: '#fff'},barWidth: 6, // 條形的寬度itemStyle: {borderRadius: 0,color: function (params) { // 設置顏色為線性漸變return new echarts.graphic.LinearGradient(1, 0, 0, 0,[{ offset: 0, color: '#2FFFFD' },{ offset: 1, color: 'rgba(47,255,253,0)' }],false);},},showBackground: true, //柱子的背景色backgroundStyle: {color: 'rgba(159,255,253,0.3)'}}],animationDuration: 3000,animationDurationUpdate: 5000,animationEasing: 'linear',animationEasingUpdate: 'linear'};chart.setOption(option);const fetchData = async () => {try {const response = await DeviceApi.getUsageRank();response.sort((a, b) => b.occupyTime - a.occupyTime) //根據occupyTime進行排序const data = { labels: response.map(item => item.orgName), values: response.map(item => item.occupyTime) }data.labels = data.labels.map((item, index) => {return `Top${index + 1} ${item}`})chart.setOption({yAxis: [{data: data.labels},{data: response.map(item => item.occupyTime).reverse()}],series: [{data: data.values}]});} catch (error) {console.error('Error fetching data:', error);}}fetchData();const intervalId = setInterval(fetchData, 60 * 60 * 1000); //1小時刷新一次window.addEventListener('resize', chart.resize);return () => {window.removeEventListener('resize', chart.resize);clearInterval(intervalId);chart.dispose();};}};useEffect(() => {initEcharts();}, []);return (<div title="使用時長排名"><div ref={chartRef} style={{ height: '100%', width: '100%' }} /></div>)
}export default CenterRank;