echarts优秀使用案例

52 篇文章 1 订阅
6 篇文章 0 订阅
echarts优秀使用案例

在这里插入图片描述
在这里插入图片描述

App.vue

<template>
    <div class="box">
        <a-card size="small" title="各类型监测设备利用率" class="center">
            <!-- color 值由组件外部进行传递(会重复修改的部分尽量减少逻辑复杂程度) -->
            <!-- type 值直接传输汉字(没有必要进行判断) -->
            <SmallChartVue :data="store.EquUseRatio" type="利用率" :color="['#66a6ff', '#89f7fe']" />
        </a-card>
    </div>
    <div class="box">
        <a-card size="small" title="各类型监测站在线率" class="center">
            <SmallChartVue :data="store.StationOnlineRatio" type="在线率" :color="['#84fab0', '#8fd3f4']" />
        </a-card>
    </div>
</template>
<script setup>
import SmallChartVue from './SmallChart.vue';
import { onUnmounted } from 'vue';
import { UseRateStore } from './store.js'
const store = UseRateStore();

// 初始化数据加载及获取
store.initData();


// 实时循环刷新数据
var Timer = setInterval(() => {
    store.initData();
}, 2000);

// 注销时,清除循环
onUnmounted(() => {
    clearInterval(Timer);
});
</script>
<style scoped>
.box {
    width: 310px;
    height: 175px;
    margin-bottom: 15px;
}

:deep(.ant-card) {
    background: #191a23;
}

:deep(.ant-card-head-title) {
    color: #fff;
    /* 标题内边距 */
    padding: 12px 0 !important;
    /* 字间距 */
    letter-spacing: 2px;
}

:deep(.ant-card) {
    border: 1px solid rgba(255, 255, 255, 0.1)
}

:deep(.ant-card-body) {
    height: 130px;
    padding: 5px;
}

:deep(.params-name) {
    text-align: left;
    color: rgba(255, 255, 255, 0.5);
}

:deep(.params-value) {
    text-align: right;
    color: #18be6b;
}

:deep(.w-100) {
    width: 100px;
}
</style>

SmallChart.vue

<template>
    <div ref="SmallDar" class="wh-100"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';
import chart from './SmallChart.js'

var _chart = null;

const props = defineProps({
    data: Object,
    type: String,
    color: Array,
})
const SmallDar = ref();

// 格式化数据方法
const buildChart = (res) => {
    // 哪怕 res.length 值为 0 ,只会不渲染数据,并不会阻止程序运行
    // 深拷贝位置更改
    let data = JSON.parse(JSON.stringify(res));
    var xAxisData = [];
    var SeriesData = [];
    for (var i = 0; i < data.length; i++) {
        xAxisData.push(data[i].name)
        SeriesData.push(data[i].value)
    }
    _chart.setData(xAxisData, SeriesData);
}

// 监听数据变化
watch(() => props.data, (res) => {
    buildChart(res);
})

// 初始化图表
onMounted(() => {
    _chart = new chart(SmallDar.value, {
        Grid: {
            top: 15,
            left: 30,
            right: 8,
            bottom: 25
        },
        type: props.type,
        Color: props.color,
    });
    buildChart(props.data);
})

// 组件注销时,删除图表
onUnmounted(() => {
    _chart.destroy()
})

</script>
<style scoped>
.wh-100 {
    width: 100%;
    height: 100%;
}
</style>

SmallChart.js

import * as echarts from 'echarts'

class BarEchart {
    constructor(view, option) {
        this.chart = echarts.init(view, 'dark');
        this.color = option.Color;
        this.grid = option.Grid;
        // type 值由外部传递
        this.type = option.type || '';
        // 给最大值最小值一个默认值
        this.MAX = option.MAX || 100;
        this.MIN = option.MIN || 0;
    }
    setData(xAxisData, SeriesData) {
        // 删除了 UI 中用不到的 Echart 配置项
        var option = {
            backgroundColor: '#191a23',
            tooltip: {
                trigger: 'axis',
                backgroundColor: "#191a23",
                borderColor: "rgba(255, 255, 255, 0.1)",
                axisPointer: {
                    type: 'shadow'
                },
                formatter: (params) => {
                    // 使用模板语法,看起来更好看一些
                    // 使他对其到左侧,为了实际输出代码时,减少左侧的字符串(其实没啥用)
                    return `
${params[0].name}<br/>
<div class="ant-row w-100">
    <div class="ant-col ant-col-12 params-name">${this.type}</div> 
    <div class="ant-col ant-col-12 params-value">${params[0].value}%</div>
</div>`;
                }
            },
            grid: this.grid,
            xAxis: {
                type: 'category',
                axisLine: {
                    show: true,
                    lineStyle: {
                        // 此处颜色改为实色,挡住最后一个分割中的虚线
                        color: 'rgba(80, 80, 80)',
                    },
                },
                axisTick: {
                    show: false
                },
                axisLabel: {
                    padding: [3, 0, 0, 0],
                    color: 'rgba(255, 255, 255, 0.5)',
                    // 修改文字大小
                    fontSize: 12,
                    // 强制显示X轴所有标签
                    interval: 0
                },
                data: xAxisData,
            },
            yAxis: {
                type: 'value',
                min: this.MIN,
                max: this.MAX,
                // 设置分割间隔
                interval: 25,
                axisLabel: {
                    show: true,
                    // 修改文字大小
                    fontSize: 11,
                    color: 'rgba(255, 255, 255, 0.5)'
                },
                splitLine: {
                    show: true,
                    // 虚线
                    lineStyle: {
                        type: [2, 1],
                    }
                },
            },
            series: [{
                name: '排名',
                type: 'bar',
                // 修改柱状条宽度
                barWidth: '35%',
                data: SeriesData,
                itemStyle: {
                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                        { offset: 0, color: this.color[0] },
                        { offset: 1, color: this.color[1] },
                    ])
                },
            }]
        };
        this.chart.setOption(option);
    }
    destroy() {
        // 修改了 注销方法
        this.chart.dispose();
    }
}
export default BarEchart

TestData.js

// 测试数据生成方法
// 用于接口伪装
const random = (min, max) => min + Math.floor(Math.random() * (max - min + 1))
let renderFunction = (label) => {
    var total = random(0, 100);
    var online = random(0, total);
    var working = random(0, online);
    return {
        label: label,
        total: total,
        online: online,
        working: working
    }
}
let LabelArray = ["一类", "二类", "三类", "四类", "监测", "船载", "便携", "传感器"];

const install = () => {
    // 数据由同步获取改为异步获取
    return new Promise((resolve, reject) => {
        let res = [];
        LabelArray.forEach(item => {
            res.push(renderFunction(item))
        });
        // 给数组一个随机函数,用来打乱数组顺序(给自己增加难度)
        res.sort((a, b) => Math.random() > 0.5 ? 1 : -1)
        resolve(res);
    });
}

export default install;

store.js

import { defineStore } from 'pinia'
import TestData from './TestData.js';

// 格式化数据方法
const Formatter = (_arr, callback) => {
    // 使用Array.prototype.map()方法生成新数组,可以省略创建数组的一步。
    // 如果严格要求效率的情况下,仍然建议使用For循环
    return _arr.map(item => {
        return {
            name: item.label,
            // 因为是计算属性,在不计较 ∞ 时,直接判断是否为真
            value: callback(item) || 0,
        }
    });
}

// 此处 store ID 是为了区分示例项目模块。请勿效仿
export const UseRateStore = defineStore('901_inspect', {
    state: () => {
        return {
            // 将两份数据分开进行存放,更贴合业务实际情况
            EquData: [],
            StationData: [],
        }
    },
    getters: {
        // 通过Getter 实时刷新数据
        EquUseRatio() {
            return Formatter(this.EquData, (stat) => {
                // 取两位小数并四舍五入(注,不用 Number.toFix(2) 方法的原因是这种方法会出现 20.00 的情况 )
                return Math.round(stat.working / stat.total * 10000) / 100;
            });
        },
        StationOnlineRatio() {
            return Formatter(this.StationData, (stat) => {
                return Math.round(stat.online / stat.total * 10000) / 100;
            });
        },
    },
    actions: {
        // 初始化数据方法,使数据可以实时刷新
        async initData() {
            // 假设数组返回值时乱序的,如何根据已有数据顺序排序返回值
            // Array 写在这个地方是为了方便大家寻找逻辑,实际情况请将 Array 对象放在全局中,防止重复创建 
            const LabelArray = ["一类", "二类", "三类", "四类", "监测", "船载", "便携", "传感器"];

            // 根据指定的 Key 值,在已经排序好的数组里面取 当前值的下标,
            // 下方为 indexOf 方法示例

            this.EquData = (await TestData()).sort((a, b) => {
                return LabelArray.indexOf(a.label) - LabelArray.indexOf(b.label)
            });


            // 如果 indexOf 的效率满足不了需求,还可以用 Mapping 结构提升效率查询值过程的效率
            // 注:Mapping 写在这个地方是为了方便大家寻找逻辑,实际情况请将 Mapping 对象放在全局中,防止重复创建 
            const LabelMapping = {
                "一类": 0,
                "二类": 1,
                "三类": 2,
                "四类": 3,
                "监测": 4,
                "船载": 5,
                "便携": 6,
                "传感器": 7
            }
            this.StationData = (await TestData()).sort((a, b) => {
                return LabelMapping[a.label] - LabelMapping[b.label]
            });;
        },
    }
});
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值