找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

210

积分

0

好友

18

主题
发表于 17 小时前 | 查看: 3| 回复: 0

在数据驱动决策的时代,将静态数据转化为直观、动态的图表是提升洞察力的关键。ECharts作为一款强大的开源JavaScript可视化库,能够轻松实现这一目标。本文将深入讲解如何使用ECharts构建一个支持多条曲线动态生成与交互的可视化图表,并提供完整的代码实现。

核心代码实现与解析

以下是一个完整的HTML示例,它创建了一个可动态调整曲线数量、带有精美样式的折线图。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动态多条曲线图(实心数据点)</title>
    <!-- 引入ECharts库 -->

    <style>
        #chart-container {
            width: 100%;
            height: 600px;
            margin: 0 auto;
        }
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        .control-panel {
            margin: 20px 0;
            text-align: center;
        }
        button {
            margin: 5px;
            padding: 8px 16px;
            font-size: 14px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="control-panel">
        <button onclick="generateChart(1)">1条曲线</button>
        <button onclick="generateChart(3)">3条曲线</button>
        <button onclick="generateChart(5)">5条曲线</button>
        <button onclick="generateChart(10)">10条曲线</button>
        <button onclick="generateChart()">随机曲线数</button>
    </div>
    <div id="chart-container"></div>
    <script>
        // 初始化图表容器
        var chartDom = document.getElementById('chart-container');
        var myChart = echarts.init(chartDom);

        // 生成类别轴数据(日期或类别)
        function generateXAxisData() {
            var xData = [];
            // 生成10个类别,可以是日期或其它类别
            for (var i = 1; i <= 10; i++) {
                // 模拟日期格式,也可以改为其他类别如['A', 'B', 'C']
                xData.push('2024-0' + Math.ceil(i/2) + '-' + (i < 10 ? '0' + i : i));
            }
            return xData;
        }

        // 随机生成鲜艳颜色函数
        function generateVibrantColor() {
            var hue = Math.floor(Math.random() * 360);
            var saturation = 70 + Math.floor(Math.random() * 30);
            var lightness = 40 + Math.floor(Math.random() * 40);
            return 'hsl(' + hue + ', ' + saturation + '%, ' + lightness + '%)';
        }

        // 生成系列数据
        function generateSeriesData(seriesCount, xData) {
            var seriesArray = [];
            var legendData = [];
            var colors = [];
            for (var i = 0; i < seriesCount; i++) {
                var seriesData = [];
                // 为每个x点生成y值(85-100%的良率)
                for (var j = 0; j < xData.length; j++) {
                    var yValue = 85 + Math.random() * 15; // 85-100%
                    yValue = Math.round(yValue * 100) / 100; // 保留两位小数
                    seriesData.push(yValue);
                }
                seriesArray.push({
                    name: '产品系列 ' + (i + 1),
                    type: 'line',
                    data: seriesData,
                    smooth: true,
                    // 恢复为实心圆点
                    symbol: 'circle',
                    symbolSize: 8,
                    // 设置实心圆点样式
                    itemStyle: {
                        color: null, // 将使用系列颜色
                        borderWidth: 0 // 无边框
                    }
                });
                legendData.push('产品系列 ' + (i + 1));
                colors.push(generateVibrantColor());
            }
            return {
                series: seriesArray,
                legend: legendData,
                colors: colors
            };
        }

        // 生成图表
        function generateChart(seriesCount) {
            // 如果没有指定系列数量,随机生成1-10条
            if (!seriesCount) {
                seriesCount = Math.floor(Math.random() * 10) + 1;
            }
            var xAxisData = generateXAxisData();
            var chartData = generateSeriesData(seriesCount, xAxisData);

            // 配置项
            var option = {
                title: {
                    text: '动态多条曲线图 - ' + seriesCount + '条曲线',
                    left: 'center',
                    textStyle: {
                        color: '#333',
                        fontSize: 18
                    }
                },
                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'shadow'
                    },
                    formatter: function (params) {
                        var xValue = params[0].axisValue;
                        var result = '<div style="font-size: 14px; margin-bottom: 5px; font-weight: bold; color: #333;">时间点: ' + xValue + '</div>';
                        params.forEach(function (item) {
                            result += '<div style="margin: 5px 0;">';
                            result += '<span style="display: inline-block; width: 12px; height: 12px; background: ' +
                                       item.color + '; border-radius: 50%; margin-right: 8px;"></span>';
                            result += '<span style="color: ' + item.color + '; font-weight: bold;">' + item.seriesName + '</span>: <strong style="color: #e4393c;">' + item.value + '%</strong>';
                            result += '</div>';
                        });
                        return result;
                    }
                },
                legend: {
                    data: chartData.legend,
                    top: '3%', // 图例位置上移
                    textStyle: {
                        fontSize: 12,
                        color: '#2c3e50', // 图例文字颜色改为深蓝色
                        fontWeight: 'bold' // 加粗图例文字
                    },
                    itemGap: 15, // 增加图例项之间的间距
                    itemWidth: 25, // 增加图例标记的宽度
                    itemHeight: 14, // 增加图例标记的高度
                    type: seriesCount > 5 ? 'scroll' : 'plain' // 图例过多时启用滚动
                },
                grid: {
                    left: '3%',
                    right: '4%',
                    top: '15%', // 调整顶部间距以适应图例位置上移
                    bottom: '3%',
                    containLabel: true
                },
                xAxis: {
                    type: 'category',
                    data: xAxisData,
                    name: '日期',
                    nameTextStyle: {
                        fontSize: 12,
                        color: '#666'
                    },
                    axisLabel: {
                        rotate: 45, // 日期标签旋转45度,避免重叠
                        color: '#666'
                    },
                    axisLine: {
                        lineStyle: {
                            color: '#ccc'
                        }
                    }
                },
                yAxis: {
                    type: 'value',
                    name: '良率 (%)',
                    min: 80,
                    max: 100,
                    interval: 5,
                    axisLabel: {
                        formatter: '{value}%',
                        color: '#666'
                    },
                    nameTextStyle: {
                        fontSize: 12,
                        color: '#666'
                    },
                    splitLine: {
                        lineStyle: {
                            color: '#f0f0f0'
                        }
                    }
                },
                series: chartData.series
            };

            // 为每个系列设置颜色
            option.series.forEach(function(series, index) {
                // 设置线条颜色
                series.lineStyle = {
                    width: 2,
                    color: chartData.colors[index]
                };
                // 设置数据点为实心
                series.itemStyle = {
                    color: chartData.colors[index], // 填充颜色与线条颜色一致
                    borderWidth: 0 // 无边框
                };
                // 设置高亮状态下的样式
                series.emphasis = {
                    itemStyle: {
                        color: chartData.colors[index], // 高亮时保持原色
                        borderColor: '#fff', // 高亮时添加白色边框
                        borderWidth: 2
                    },
                    scale: 1.5 // 高亮时放大数据点
                };
                // 设置标签样式
                series.label = {
                    show: true,
                    formatter: '{c}%',
                    color: '#333',
                    fontSize: 10,
                    backgroundColor: 'rgba(255,255,255,0.7)',
                    borderColor: chartData.colors[index],
                    borderWidth: 1,
                    borderRadius: 3,
                    padding: [2, 4]
                };
            });

            // 应用配置并渲染图表
            myChart.setOption(option, true);
        }

        // 初始生成3条曲线
        generateChart(3);

        // 窗口大小改变时重绘图表
        window.addEventListener('resize', function() {
            myChart.resize();
        });
    </script>
</body>
</html>

动态多条曲线图效果展示

技术要点解析

  1. 动态数据生成generateSeriesData 函数是核心,它能根据指定的曲线数量(seriesCount)动态生成对应的随机数据序列,并分配唯一的系列名称与颜色。这使得图表能够灵活应对不同数据维度的需求。
  2. 可交互控制面板:通过一组按钮控件,用户可以即时更改图表中显示的数据系列数量(1、3、5、10条或随机),无需刷新页面即可看到可视化效果的实时变化,极大提升了用户体验。
  3. 视觉样式优化
    • 颜色:使用HSL色彩模型随机生成鲜艳且区分度高的颜色,避免图表线条颜色单调或相近。
    • 数据点:采用实心圆点(symbol: 'circle')并移除了边框,使焦点更清晰。在高亮交互时(emphasis),数据点会放大并添加白色边框,引导用户视线。
    • 标签与图例:为每条曲线的数据点添加了带背景的数值标签,并优化了图例的样式与布局(如颜色加深、加粗、自动滚动),使信息在多条曲线时仍保持可读性。
  4. 响应式设计:通过监听 windowresize 事件并调用 myChart.resize() 方法,确保图表在不同屏幕尺寸下都能自适应并完整显示。

应用场景与扩展

此图表模板非常适合需要对比多个指标随时间变化趋势的场景,例如:

  • 监控不同产品的质量良率走势。
  • 分析多个渠道的日活跃用户数(DAU)变化。
  • 跟踪公司内若干关键业绩指标(KPI)的完成进度。

你可以轻松地修改 generateXAxisDatagenerateSeriesData 函数中的数据源,将其替换为从后端API获取的真实数据,即可集成到实际的监控仪表盘或数据分析系统中。通过掌握ECharts的这些配置技巧,你可以构建出既美观又实用的专业级数据可视化应用。




上一篇:传统三层网络演进趋势解析:从SDN、零信任到云原生的现代架构
下一篇:MySQL锁等待与锁超时实战指南:深度解析与性能调优
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-6 20:03 , Processed in 0.083432 second(s), 36 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表