工作中遇到的问题之——通过el-slider控制echarts折线图

176 阅读1分钟

业务需求

image.png 如上图所示,通过Smoothing值,重新计算data,生成新的折线图。

代码实现

<template>
    <div :class="'chart-box-' + index" class="chart-box" style="width: 100%;height: 320px;" :id="'chart-box-' + index"></div>
</template>

<script>
export default {
    data() {
        return {
            trainChart: {}
        };
    },
    props: {
        chartList: {
            type: Object,
            default: () => {}
        },
        index: {
            type: Number,
            default: 0
        },
        smooth: {
            type: Number,
            default: 0
        }
    },
    watch: {
    // 通过监听父组件传过来的smooth值和chartList值,刷新折线图
        smooth() {
            this.initChart(this.chartList);
        },
        chartList() {
            this.initChart(this.chartList);
        }
    },
    methods: {
        smoothAlgorithm(yData) {
            // 平滑算法
            let smooth = this.smooth;
            let smoothData = [];
            for (let i = 0; i < yData.length; i++) {
                if (i === 0) {
                    smoothData.push(yData[i][2]);
                } else {
                    smoothData.push((smoothData[i - 1] * smooth + yData[i][2]) / (smooth + 1));
                    smooth = (smooth + 1) * this.smooth;
                }
            }
            return smoothData;
        },
        formatRelativeTime(msTime) {
            const time = msTime / 1000;
            const hour = Math.floor(time / 3600) % 60;
            const minute = Math.floor(time / 60) % 60;
            const second = Math.floor(time) % 60;
            return hour ? `${hour}h${minute}m${second}s` : minute ? `${minute}m${second}s` : `${second}s`;
        },
        getLocalTime(nS) {
            return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/, " ");
        },
        initChart(chartData) {
            let { name, list } = chartData;
            let title = name.split("/")[1];
            let id = `chart-box-${this.index}`;
            this.trainChart = this.$echarts.init(document.getElementById(id));
            // 获取平滑数据
            let smoothValueList = this.smoothAlgorithm(list);
            // 将平滑数据加入到二维数组中的每一项
            list.forEach((item, index) => {
                if (item.length > 3) item.pop();
                item.push(smoothValueList[index]);
            });
            let smooth = this.smooth;
            let option = {
                dataset: {
                    dimensions: ["time", "step", "baseValue", "value"]
                },
                grid: {
                    left: 60,
                    right: 30,
                    bottom: 40
                },
                tooltip: {
                    trigger: "axis",
                    axisPointer: {
                        type: "shadow",
                        shadowStyle: {
                            color: "rgba(0, 0, 0, 0.1)"
                        }
                    },
                    backgroundColor: "rgba(0, 0, 0, 0.6)",
                    borderRadius: 4,
                    borderWidth: 0,
                    textStyle: { color: "#fff" },
                    renderMode: "html",
                    formatter: a => {
                        // console.log(a[1]);
                        let smoothData = a[1].data;
                        let value = smoothData[3] < 0.01 ? smoothData[3].toExponential(4) : smoothData[3].toFixed(4),
                            step = smoothData[1],
                            time = smoothData[0],
                            startTime = list[0][0],
                            relative = (time - startTime) * 1000;
                        relative = this.formatRelativeTime(relative);
                        time = this.getLocalTime(time);
                        let tipHTML = `
                                <div class="tooltip-box">
                                  <div class="tip-item">
                                    <div class="tip-label"></div>
                                  </div>
                                  <div class="tip-item">
                                    <h4 class="tip-title">Smoothed</h4>
                                    <div class="tip-con">${smooth}</div>
                                  </div>
                                  <div class="tip-item">
                                    <h4 class="tip-title">Value</h4>
                                    <p class="tip-con">${value}</p>
                                  </div>
                                  <div class="tip-item">
                                    <h4 class="tip-title">Step</h4>
                                    <p class="tip-con">${step}</p>
                                  </div>
                                  <div class="tip-item">
                                    <h4 class="tip-title">Time</h4>
                                    <p class="tip-con">${time}</p>
                                  </div>
                                  <div class="tip-item">
                                    <h4 class="tip-title">Relative</h4>
                                    <p class="tip-con">${relative}</p>
                                  </div>
                                </div>`;
                        return tipHTML;
                    }
                },
                title: {
                    show: true,
                    text: title + "\n" + "tag: " + name,
                    textStyle: {
                        color: "#2A2A32",
                        fontSize: 12,
                        lineHeight: 15,
                        fontWeight: 400
                    },
                    textAlign: "left",
                    padding: [15, 0, 0, 23]
                },
                xAxis: {
                    type: "category",
                    axisLine: { lineStyle: { color: "#DDDDDD" } },
                    axisLabel: { color: "#666666", interval: 9 },
                    axisTick: {
                        show: false
                    }
                },
                yAxis: {
                    type: "value",
                    axisLine: { lineStyle: { color: "#DDDDDD" } },
                    axisLabel: {
                        color: "#9B9BAC",
                        formatter: a => {
                        // toExponential转为科学计数法
                            return a < 0.01 ? a.toExponential() : a.toFixed(3);
                        }
                    },
                    splitLine: {
                        lineStyle: { color: "#DEE0E5", type: "dashed" }
                    },
                    scale: true // Y轴依据数据,自动缩放至视图大小
                },
                series: [
                    {
                        name: "base",
                        type: "line",
                        symbol: "circle",
                        lineStyle: {
                            color: "#b3baff"
                        },
                        itemStyle: {
                            color: "#fff",
                            borderColor: "#b3baff",
                            borderWidth: 1
                        },
                        encode: {
                            x: "step",
                            y: "baseValue"
                        }
                    },
                    {
                        name: "smooth",
                        type: "line",
                        symbol: "circle",
                        lineStyle: {
                            color: "#475AFF"
                        },
                        itemStyle: {
                            color: "#fff",
                            borderColor: "#475AFF",
                            borderWidth: 1
                        },
                        emphasis: {
                            scale: true
                        },
                        encode: {
                            x: "step",
                            y: "value"
                        }
                    }
                ]
            };
            option.dataset.source = list;
            option && this.trainChart.setOption(option);
        }
    },
    mounted() {
        this.initChart(this.chartList);
        // console.log(this.chartList);
    }
};
</script>

<style lang="scss">
.tooltip-box {
    display: flex;
    justify-content: space-around;
    .tip-item {
        padding-right: 30px;
        .tip-title {
            font-size: 14px;
            margin-bottom: 10px;
        }
        .tip-label {
            width: 16px;
            height: 16px;
            border-radius: 50%;
            background-color: #4f61ff;
            margin-top: 33px;
            margin-left: 10px;
        }
    }
}
</style>