首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >ECharts 实现一个水滴效果的数据可视化图表

ECharts 实现一个水滴效果的数据可视化图表

原创
作者头像
小焱
发布2025-09-02 17:48:43
发布2025-09-02 17:48:43
12000
代码可运行
举报
文章被收录于专栏:前端开发前端开发
运行总次数:0
代码可运行
代码语言:javascript
代码运行次数:0
运行
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ECharts 水滴效果</title>
    <!-- 引入 Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入 Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <!-- 引入 ECharts -->
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
    
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#3B82F6',
                        secondary: '#0EA5E9',
                        accent: '#22D3EE',
                        dark: '#0F172A',
                    },
                    fontFamily: {
                        inter: ['Inter', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .glass {
                background: rgba(255, 255, 255, 0.25);
                backdrop-filter: blur(10px);
                -webkit-backdrop-filter: blur(10px);
            }
            .water-animation {
                animation: waterMove 8s infinite ease-in-out;
            }
            @keyframes waterMove {
                0%, 100% { transform: translateY(0); }
                50% { transform: translateY(-10px); }
            }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen font-inter text-dark">
    <div class="container mx-auto px-4 py-8 max-w-6xl">
        <header class="text-center mb-12">
            <h1 class="text-[clamp(2rem,5vw,3rem)] font-bold text-dark mb-3">ECharts 水滴效果可视化</h1>
            <p class="text-gray-600 text-lg max-w-2xl mx-auto">使用 ECharts 实现的动态水滴效果,可用于展示水位、进度或其他液体相关数据</p>
        </header>
        
        <main class="grid grid-cols-1 lg:grid-cols-3 gap-8">
            <!-- 水滴图表容器 -->
            <div class="lg:col-span-2 bg-white rounded-2xl shadow-xl overflow-hidden">
                <div class="p-6 border-b border-gray-100">
                    <h2 class="text-xl font-semibold flex items-center">
                        <i class="fa fa-tint text-primary mr-2"></i>水滴效果演示
                    </h2>
                </div>
                <div class="p-4 md:p-6">
                    <div id="dropChart" class="w-full h-[500px]"></div>
                </div>
            </div>
            
            <!-- 控制面板 -->
            <div class="bg-white rounded-2xl shadow-xl overflow-hidden">
                <div class="p-6 border-b border-gray-100">
                    <h2 class="text-xl font-semibold flex items-center">
                        <i class="fa fa-sliders text-primary mr-2"></i>控制面板
                    </h2>
                </div>
                <div class="p-6 space-y-6">
                    <div>
                        <label for="waterLevel" class="block text-sm font-medium text-gray-700 mb-2">
                            水位控制: <span id="levelValue">65%</span>
                        </label>
                        <input 
                            type="range" 
                            id="waterLevel" 
                            min="0" 
                            max="100" 
                            value="65" 
                            class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-primary"
                        >
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-2">水滴颜色</label>
                        <div class="grid grid-cols-4 gap-3">
                            <button class="color-btn w-10 h-10 rounded-full bg-blue-500 border-2 border-transparent hover:border-gray-300 transition-all" data-color="#3B82F6"></button>
                            <button class="color-btn w-10 h-10 rounded-full bg-green-500 border-2 border-transparent hover:border-gray-300 transition-all" data-color="#22C55E"></button>
                            <button class="color-btn w-10 h-10 rounded-full bg-purple-500 border-2 border-transparent hover:border-gray-300 transition-all" data-color="#A855F7"></button>
                            <button class="color-btn w-10 h-10 rounded-full bg-red-500 border-2 border-transparent hover:border-gray-300 transition-all" data-color="#EF4444"></button>
                        </div>
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-2">动画速度</label>
                        <select id="animationSpeed" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary">
                            <option value="slow">慢</option>
                            <option value="medium" selected>中等</option>
                            <option value="fast">快</option>
                        </select>
                    </div>
                    
                    <div class="pt-4">
                        <button id="randomData" class="w-full bg-primary hover:bg-primary/90 text-white font-medium py-2 px-4 rounded-lg transition-all flex items-center justify-center">
                            <i class="fa fa-random mr-2"></i>随机数据
                        </button>
                    </div>
                </div>
            </div>
            
            <!-- 数据信息 -->
            <div class="lg:col-span-3 bg-white rounded-2xl shadow-xl overflow-hidden">
                <div class="p-6 border-b border-gray-100">
                    <h2 class="text-xl font-semibold flex items-center">
                        <i class="fa fa-info-circle text-primary mr-2"></i>关于水滴效果
                    </h2>
                </div>
                <div class="p-6">
                    <p class="text-gray-700 mb-4">
                        这个水滴效果使用 ECharts 的自定义系列和贝塞尔曲线实现,模拟了水滴的自然形态。通过控制面板,您可以调整水位高度、更改水滴颜色和动画速度。
                    </p>
                    <p class="text-gray-700">
                        水滴图表非常适合展示与液体相关的数据,如水库水位、油箱油量、进度指标等。您可以根据实际需求进一步定制水滴的形状、颜色和动画效果。
                    </p>
                </div>
            </div>
        </main>
        
        <footer class="mt-12 text-center text-gray-500 text-sm">
            <p>© 2023 ECharts 水滴效果演示 | 使用 ECharts、Tailwind CSS 和 Font Awesome 构建</p>
        </footer>
    </div>

    <script>
        // 初始化图表
        const chartDom = document.getElementById('dropChart');
        const myChart = echarts.init(chartDom);
        let option;
        
        // 初始配置
        let waterLevel = 65; // 0-100
        let waterColor = '#3B82F6';
        let animationDuration = 2000; // 默认中等速度
        
        // 生成水滴形状的函数
        function getDropShape(level) {
            // 归一化水位到 0-1 范围
            const normalizedLevel = level / 100;
            
            // 水滴的控制点 - 贝塞尔曲线
            const points = [
                [50, 100 - normalizedLevel * 80], // 顶部点,随水位变化
                
                // 右侧曲线控制点
                [70, 100 - normalizedLevel * 60],
                [90, 100 - normalizedLevel * 30],
                [95, 100],
                
                // 底部点
                [50, 110],
                
                // 左侧曲线控制点
                [5, 100],
                [20, 100 - normalizedLevel * 40],
                [30, 100 - normalizedLevel * 70],
                
                // 闭合路径
                [50, 100 - normalizedLevel * 80]
            ];
            
            // 转换为 ECharts 路径格式
            let path = 'M' + points[0][0] + ',' + points[0][1];
            
            // 右侧曲线
            path += ' Q' + points[1][0] + ',' + points[1][1] + ' ' + points[2][0] + ',' + points[2][1];
            path += ' T' + points[3][0] + ',' + points[3][1];
            
            // 底部曲线
            path += ' Q' + points[4][0] + ',' + points[4][1] + ' ' + points[5][0] + ',' + points[5][1];
            
            // 左侧曲线
            path += ' T' + points[6][0] + ',' + points[6][1];
            path += ' T' + points[7][0] + ',' + points[7][1];
            
            return path;
        }
        
        // 更新图表函数
        function updateChart() {
            const dropPath = getDropShape(waterLevel);
            
            option = {
                backgroundColor: 'transparent',
                tooltip: {
                    formatter: `水位: ${waterLevel}%`
                },
                graphic: {
                    elements: [
                        // 水滴阴影
                        {
                            type: 'path',
                            shape: {
                                d: dropPath
                            },
                            style: {
                                fill: 'rgba(0, 0, 0, 0.1)',
                            },
                            left: 'center',
                            top: 'center',
                            z: 0,
                            transform: 'translate(5px, 5px) scale(0.95)'
                        },
                        // 水滴本体
                        {
                            type: 'path',
                            shape: {
                                d: dropPath
                            },
                            style: {
                                fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                                    { offset: 0, color: waterColor + 'CC' },
                                    { offset: 1, color: waterColor }
                                ]),
                                stroke: waterColor,
                                lineWidth: 2
                            },
                            left: 'center',
                            top: 'center',
                            z: 1,
                            // 添加水波纹动画
                            animation: true,
                            animationDuration: animationDuration,
                            animationEasing: 'sinusoidalInOut',
                            animationLoop: true
                        },
                        // 水面波纹效果
                        {
                            type: 'circle',
                            shape: {
                                cx: 50,
                                cy: 100 - waterLevel * 0.8,
                                r: 15 + Math.sin(Date.now() / 500) * 3
                            },
                            style: {
                                fill: 'rgba(255, 255, 255, 0.3)',
                                opacity: 0.7
                            },
                            left: 'center',
                            top: 'center',
                            z: 2,
                            // 波纹动画
                            animation: true,
                            animationDuration: animationDuration * 2,
                            animationEasing: 'sinusoidalInOut',
                            animationLoop: true
                        },
                        // 小波纹
                        {
                            type: 'circle',
                            shape: {
                                cx: 50 + Math.sin(Date.now() / 800) * 10,
                                cy: 100 - waterLevel * 0.8 + Math.cos(Date.now() / 800) * 5,
                                r: 8 + Math.sin(Date.now() / 600) * 2
                            },
                            style: {
                                fill: 'rgba(255, 255, 255, 0.2)',
                                opacity: 0.5
                            },
                            left: 'center',
                            top: 'center',
                            z: 2,
                            animation: true,
                            animationDuration: animationDuration * 3,
                            animationEasing: 'sinusoidalInOut',
                            animationLoop: true
                        },
                        // 水位文本
                        {
                            type: 'text',
                            left: 'center',
                            top: 'center',
                            style: {
                                text: waterLevel + '%',
                                fontSize: 36,
                                fontWeight: 'bold',
                                fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                                    { offset: 0, color: '#fff' },
                                    { offset: 1, color: 'rgba(255, 255, 255, 0.7)' }
                                ]),
                                textShadow: '0 2px 4px rgba(0, 0, 0, 0.1)'
                            },
                            z: 3
                        }
                    ]
                },
                series: []
            };
            
            myChart.setOption(option);
        }
        
        // 初始化图表
        updateChart();
        
        // 响应窗口大小变化
        window.addEventListener('resize', function() {
            myChart.resize();
        });
        
        // 水位控制
        const levelSlider = document.getElementById('waterLevel');
        const levelValue = document.getElementById('levelValue');
        
        levelSlider.addEventListener('input', function() {
            waterLevel = parseInt(this.value);
            levelValue.textContent = waterLevel + '%';
            updateChart();
        });
        
        // 颜色选择
        const colorButtons = document.querySelectorAll('.color-btn');
        colorButtons.forEach(btn => {
            btn.addEventListener('click', function() {
                // 移除所有按钮的选中状态
                colorButtons.forEach(b => b.classList.remove('ring-4', 'ring-gray-200'));
                // 添加当前按钮的选中状态
                this.classList.add('ring-4', 'ring-gray-200');
                
                waterColor = this.getAttribute('data-color');
                updateChart();
            });
        });
        
        // 默认选中第一个颜色
        colorButtons[0].classList.add('ring-4', 'ring-gray-200');
        
        // 动画速度控制
        const speedSelect = document.getElementById('animationSpeed');
        speedSelect.addEventListener('change', function() {
            switch(this.value) {
                case 'slow':
                    animationDuration = 4000;
                    break;
                case 'medium':
                    animationDuration = 2000;
                    break;
                case 'fast':
                    animationDuration = 1000;
                    break;
            }
            updateChart();
        });
        
        // 随机数据按钮
        const randomBtn = document.getElementById('randomData');
        randomBtn.addEventListener('click', function() {
            waterLevel = Math.floor(Math.random() * 100);
            levelSlider.value = waterLevel;
            levelValue.textContent = waterLevel + '%';
            
            // 随机选择一个颜色
            const randomColor = colorButtons[Math.floor(Math.random() * colorButtons.length)];
            colorButtons.forEach(b => b.classList.remove('ring-4', 'ring-gray-200'));
            randomColor.classList.add('ring-4', 'ring-gray-200');
            waterColor = randomColor.getAttribute('data-color');
            
            updateChart();
        });
    </script>
</body>
</html>

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档