Apache ECharts Samples

Comprehensive Apache ECharts examples including various chart types, advanced visualizations, and interactive dashboards

Key Facts

Category
Data Visualization
Items
3
Format Families
sample

Sample Overview

Comprehensive Apache ECharts examples including various chart types, advanced visualizations, and interactive dashboards This sample set belongs to Data Visualization and can be used to test related workflows inside Elysia Tools.

💻 ECharts Basic Charts html

🟢 simple

Essential Apache ECharts including bar, line, pie, and basic interactive charts with customization

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>ECharts Basic Charts Example</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
    <style>
        .chart-container {
            width: 600px;
            height: 400px;
            margin: 20px;
            border: 1px solid #ddd;
        }
        .controls {
            padding: 20px;
            background: #f5f5f5;
            margin: 20px;
        }
        button {
            padding: 8px 16px;
            margin: 5px;
            cursor: pointer;
            background: #4e79a7;
            color: white;
            border: none;
            border-radius: 4px;
        }
        button:hover {
            background: #3a5991;
        }
    </style>
</head>
<body>
    <div class="controls">
        <h3>ECharts Basic Chart Types</h3>
        <button onclick="showBarChart()">Bar Chart</button>
        <button onclick="showLineChart()">Line Chart</button>
        <button onclick="showPieChart()">Pie Chart</button>
        <button onclick="updateData()">Update Data</button>
    </div>

    <div id="chartContainer" class="chart-container"></div>

    <script>
        // Initialize chart instance
        const myChart = echarts.init(document.getElementById('chartContainer'));

        // Sample data
        const categories = ['January', 'February', 'March', 'April', 'May', 'June'];
        const dataValues = [120, 200, 150, 80, 70, 110];

        // Bar chart configuration
        function getBarOption() {
            return {
                title: {
                    text: 'Monthly Sales Data',
                    subtext: 'First Half 2024',
                    left: 'center'
                },
                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'shadow'
                    }
                },
                legend: {
                    data: ['Sales'],
                    top: 30
                },
                grid: {
                    left: '3%',
                    right: '4%',
                    bottom: '3%',
                    containLabel: true
                },
                xAxis: {
                    type: 'category',
                    data: categories,
                    axisTick: {
                        alignWithLabel: true
                    }
                },
                yAxis: {
                    type: 'value'
                },
                series: [{
                    name: 'Sales',
                    type: 'bar',
                    barWidth: '60%',
                    data: dataValues,
                    itemStyle: {
                        color: '#5470c6'
                    }
                }]
            };
        }

        // Line chart configuration
        function getLineOption() {
            return {
                title: {
                    text: 'Monthly Trend Analysis',
                    subtext: 'First Half 2024',
                    left: 'center'
                },
                tooltip: {
                    trigger: 'axis'
                },
                legend: {
                    data: ['Sales', 'Profit'],
                    top: 30
                },
                grid: {
                    left: '3%',
                    right: '4%',
                    bottom: '3%',
                    containLabel: true
                },
                xAxis: {
                    type: 'category',
                    boundaryGap: false,
                    data: categories
                },
                yAxis: {
                    type: 'value'
                },
                series: [{
                    name: 'Sales',
                    type: 'line',
                    data: dataValues,
                    smooth: true,
                    itemStyle: {
                        color: '#5470c6'
                    }
                }, {
                    name: 'Profit',
                    type: 'line',
                    data: dataValues.map(v => v * 0.3),
                    smooth: true,
                    itemStyle: {
                        color: '#91cc75'
                    }
                }]
            };
        }

        // Pie chart configuration
        function getPieOption() {
            return {
                title: {
                    text: 'Product Sales Distribution',
                    subtext: 'First Half 2024',
                    left: 'center'
                },
                tooltip: {
                    trigger: 'item',
                    formatter: '{a} <br/>{b}: {c} ({d}%)'
                },
                legend: {
                    orient: 'vertical',
                    left: 10,
                    top: 'center'
                },
                series: [{
                    name: 'Product Category',
                    type: 'pie',
                    radius: ['40%', '70%'],
                    avoidLabelOverlap: false,
                    label: {
                        show: false,
                        position: 'center'
                    },
                    emphasis: {
                        label: {
                            show: true,
                            fontSize: 18,
                            fontWeight: 'bold'
                        }
                    },
                    labelLine: {
                        show: false
                    },
                    data: categories.map((cat, index) => ({
                        value: dataValues[index],
                        name: cat
                    }))
                }]
            };
        }

        // Show different chart types
        function showBarChart() {
            myChart.setOption(getBarOption());
        }

        function showLineChart() {
            myChart.setOption(getLineOption());
        }

        function showPieChart() {
            myChart.setOption(getPieOption());
        }

        // Update data
        function updateData() {
            const newData = dataValues.map(() => Math.floor(Math.random() * 200) + 50);
            const currentOption = myChart.getOption();

            if (currentOption.series[0].type === 'bar') {
                myChart.setOption({
                    series: [{
                        data: newData
                    }]
                });
            } else if (currentOption.series[0].type === 'line') {
                myChart.setOption({
                    series: [{
                        data: newData
                    }, {
                        data: newData.map(v => v * 0.3)
                    }]
                });
            } else if (currentOption.series[0].type === 'pie') {
                myChart.setOption({
                    series: [{
                        data: categories.map((cat, index) => ({
                            value: newData[index],
                            name: cat
                        }))
                    }]
                });
            }
        }

        // Initialize with bar chart
        showBarChart();

        // Responsive handling
        window.addEventListener('resize', function() {
            myChart.resize();
        });
    </script>
</body>
</html>

💻 ECharts Interactive Dashboard html

🟡 intermediate

Advanced ECharts dashboard with multiple chart types, real-time updates, and interactive filters

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>ECharts Interactive Dashboard</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background: #f0f2f5;
        }
        .dashboard {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 20px;
            max-width: 1400px;
            margin: 0 auto;
        }
        .chart-box {
            background: white;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
        .chart-container {
            width: 100%;
            height: 300px;
        }
        .large-chart {
            grid-column: span 2;
        }
        .tall-chart {
            grid-row: span 2;
        }
        .header {
            text-align: center;
            margin-bottom: 30px;
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
        .controls {
            text-align: center;
            margin-bottom: 20px;
        }
        .date-range {
            margin: 0 10px;
        }
        h2 {
            margin: 0 0 10px 0;
            color: #333;
        }
        .chart-title {
            font-size: 14px;
            color: #666;
            margin-bottom: 10px;
        }
        button {
            padding: 8px 16px;
            margin: 0 5px;
            cursor: pointer;
            background: #4e79a7;
            color: white;
            border: none;
            border-radius: 4px;
        }
        button:hover {
            background: #3a5991;
        }
        @media (max-width: 1200px) {
            .dashboard {
                grid-template-columns: repeat(2, 1fr);
            }
            .large-chart {
                grid-column: span 1;
            }
        }
    </style>
</head>
<body>
    <div class="header">
        <h1>📊 Enterprise Data Analytics Dashboard</h1>
        <div class="controls">
            <label>Time Range:</label>
            <select class="date-range" onchange="updateTimeRange(this.value)">
                <option value="7">Last 7 days</option>
                <option value="30" selected>Last 30 days</option>
                <option value="90">Last 90 days</option>
            </select>
            <button onclick="refreshData()">🔄 Refresh Data</button>
            <button onclick="exportReport()">📥 Export Report</button>
        </div>
    </div>

    <div class="dashboard">
        <!-- Sales Trend Chart -->
        <div class="chart-box large-chart">
            <div class="chart-title">📈 Sales Trend Analysis</div>
            <div id="salesChart" class="chart-container"></div>
        </div>

        <!-- Product Distribution Pie Chart -->
        <div class="chart-box">
            <div class="chart-title">🎯 Product Sales Distribution</div>
            <div id="productChart" class="chart-container"></div>
        </div>

        <!-- Regional Distribution Map -->
        <div class="chart-box large-chart">
            <div class="chart-title">🗺️ Regional Sales Distribution</div>
            <div id="mapChart" class="chart-container"></div>
        </div>

        <!-- KPI Gauge Chart -->
        <div class="chart-box">
            <div class="chart-title">⚡ KPI Completion Rate</div>
            <div id="gaugeChart" class="chart-container"></div>
        </div>

        <!-- Sales Funnel Chart -->
        <div class="chart-box tall-chart">
            <div class="chart-title">🔍 Sales Funnel Analysis</div>
            <div id="funnelChart" class="chart-container"></div>
        </div>

        <!-- Sales Heatmap -->
        <div class="chart-box">
            <div class="chart-title">🔥 Sales Heatmap</div>
            <div id="heatmapChart" class="chart-container"></div>
        </div>
    </div>

    <script>
        // Chart instances storage
        const charts = {};

        // Initialize all charts
        function initCharts() {
            charts.sales = echarts.init(document.getElementById('salesChart'));
            charts.product = echarts.init(document.getElementById('productChart'));
            charts.map = echarts.init(document.getElementById('mapChart'));
            charts.gauge = echarts.init(document.getElementById('gaugeChart'));
            charts.funnel = echarts.init(document.getElementById('funnelChart'));
            charts.heatmap = echarts.init(document.getElementById('heatmapChart'));
        }

        // Generate mock data
        function generateSalesData(days = 30) {
            const dates = [];
            const sales = [];
            const profit = [];
            const today = new Date();

            for (let i = days - 1; i >= 0; i--) {
                const date = new Date(today);
                date.setDate(date.getDate() - i);
                dates.push(date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }));

                const baseSales = 1000 + Math.sin(i / 5) * 200;
                sales.push(Math.floor(baseSales + Math.random() * 500));
                profit.push(Math.floor(baseSales * 0.3 + Math.random() * 100));
            }

            return { dates, sales, profit };
        }

        // Sales trend chart configuration
        function getSalesOption(data) {
            return {
                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'cross',
                        label: {
                            backgroundColor: '#6a7985'
                        }
                    }
                },
                legend: {
                    data: ['Sales', 'Profit'],
                    top: 0
                },
                grid: {
                    left: '3%',
                    right: '4%',
                    bottom: '3%',
                    containLabel: true
                },
                xAxis: {
                    type: 'category',
                    boundaryGap: false,
                    data: data.dates
                },
                yAxis: [
                    {
                        type: 'value',
                        name: 'Sales',
                        position: 'left',
                        axisLabel: {
                            formatter: '{value}'
                        }
                    },
                    {
                        type: 'value',
                        name: 'Profit',
                        position: 'right',
                        axisLabel: {
                            formatter: '{value}'
                        }
                    }
                ],
                series: [
                    {
                        name: 'Sales',
                        type: 'line',
                        smooth: true,
                        lineStyle: {
                            width: 3
                        },
                        areaStyle: {
                            opacity: 0.3
                        },
                        emphasis: {
                            focus: 'series'
                        },
                        data: data.sales
                    },
                    {
                        name: 'Profit',
                        type: 'line',
                        smooth: true,
                        yAxisIndex: 1,
                        lineStyle: {
                            width: 3
                        },
                        areaStyle: {
                            opacity: 0.3
                        },
                        emphasis: {
                            focus: 'series'
                        },
                        data: data.profit
                    }
                ]
            };
        }

        // Product distribution pie chart configuration
        function getProductOption() {
            return {
                tooltip: {
                    trigger: 'item',
                    formatter: '{a} <br/>{b}: {c} ({d}%)'
                },
                legend: {
                    orient: 'vertical',
                    left: 'left'
                },
                series: [
                    {
                        name: 'Product Category',
                        type: 'pie',
                        radius: ['40%', '70%'],
                        center: ['60%', '50%'],
                        avoidLabelOverlap: false,
                        itemStyle: {
                            borderRadius: 10,
                            borderColor: '#fff',
                            borderWidth: 2
                        },
                        label: {
                            show: false,
                            position: 'center'
                        },
                        emphasis: {
                            label: {
                                show: true,
                                fontSize: 16,
                                fontWeight: 'bold'
                            }
                        },
                        labelLine: {
                            show: false
                        },
                        data: [
                            { value: 1048, name: 'Electronics' },
                            { value: 735, name: 'Clothing' },
                            { value: 580, name: 'Home & Garden' },
                            { value: 484, name: 'Sports' },
                            { value: 300, name: 'Others' }
                        ]
                    }
                ]
            };
        }

        // Initialize all charts with data
        function updateAllCharts() {
            const salesData = generateSalesData();

            charts.sales.setOption(getSalesOption(salesData));
            charts.product.setOption(getProductOption());

            // Additional chart configurations would go here
            // For brevity, showing placeholder configurations
            charts.map.setOption({
                title: { text: 'Regional Map', left: 'center' },
                xAxis: { type: 'category' },
                yAxis: { type: 'value' },
                series: [{
                    type: 'scatter',
                    data: [
                        [10, 20], [20, 30], [30, 25], [40, 35], [50, 40]
                    ]
                }]
            });

            charts.gauge.setOption({
                series: [{
                    type: 'gauge',
                    data: [{ value: 85, name: 'Completion Rate' }]
                }]
            });

            charts.funnel.setOption({
                series: [{
                    type: 'funnel',
                    data: [
                        { value: 100, name: 'Visitors' },
                        { value: 80, name: 'Clicks' },
                        { value: 60, name: 'Inquiries' },
                        { value: 25, name: 'Orders' }
                    ]
                }]
            });

            charts.heatmap.setOption({
                xAxis: {
                    type: 'category',
                    data: ['Mon', 'Tue', 'Wed']
                },
                yAxis: {
                    type: 'category',
                    data: ['Morning', 'Afternoon']
                },
                visualMap: {
                    min: 0,
                    max: 100,
                    calculable: true,
                    orient: 'horizontal',
                    left: 'center',
                    bottom: '5%'
                },
                series: [{
                    type: 'heatmap',
                    data: [
                        [0, 0, 10], [1, 0, 20], [2, 0, 30],
                        [0, 1, 20], [1, 1, 40], [2, 1, 60]
                    ]
                }]
            });
        }

        // Update time range
        function updateTimeRange(days) {
            const salesData = generateSalesData(parseInt(days));
            charts.sales.setOption(getSalesOption(salesData));
        }

        // Refresh data
        function refreshData() {
            Object.values(charts).forEach(chart => {
                chart.showLoading();
            });

            setTimeout(() => {
                updateAllCharts();
                Object.values(charts).forEach(chart => {
                    chart.hideLoading();
                });
            }, 1000);
        }

        // Export report
        function exportReport() {
            alert('Export functionality would be implemented here');
        }

        // Responsive handling
        window.addEventListener('resize', function() {
            Object.values(charts).forEach(chart => {
                chart.resize();
            });
        });

        // Initialize on load
        document.addEventListener('DOMContentLoaded', function() {
            initCharts();
            updateAllCharts();
        });
    </script>
</body>
</html>

💻 ECharts Advanced Visualization html

🔴 complex

Complex ECharts visualizations including 3D charts, animations, and custom components

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>ECharts Advanced Visualization</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts-gl.min.js"></script>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
        }
        .container {
            max-width: 1400px;
            margin: 0 auto;
        }
        .header {
            text-align: center;
            color: white;
            margin-bottom: 30px;
            padding: 20px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 15px;
            backdrop-filter: blur(10px);
        }
        .visualization-grid {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 20px;
            margin-bottom: 20px;
        }
        .viz-card {
            background: rgba(255, 255, 255, 0.95);
            border-radius: 15px;
            padding: 25px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
            backdrop-filter: blur(10px);
        }
        .viz-title {
            font-size: 18px;
            font-weight: bold;
            margin-bottom: 15px;
            color: #333;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .chart-container {
            width: 100%;
            height: 400px;
            position: relative;
        }
        .small-chart {
            height: 300px;
        }
        .controls {
            margin-top: 15px;
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
        }
        .control-btn {
            padding: 8px 16px;
            border: none;
            border-radius: 8px;
            background: linear-gradient(45deg, #667eea, #764ba2);
            color: white;
            cursor: pointer;
            font-size: 14px;
            transition: transform 0.2s;
        }
        .control-btn:hover {
            transform: translateY(-2px);
        }
        .full-width {
            grid-column: span 2;
        }
        @media (max-width: 900px) {
            .visualization-grid {
                grid-template-columns: 1fr;
            }
            .full-width {
                grid-column: span 1;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🎨 ECharts Advanced Visualization Lab</h1>
            <p>Explore 3D charts, dynamic effects, and custom components</p>
        </div>

        <div class="visualization-grid">
            <!-- 3D Scatter Plot -->
            <div class="viz-card">
                <div class="viz-title">🌐 3D Scatter Plot</div>
                <div id="scatter3D" class="chart-container"></div>
                <div class="controls">
                    <button class="control-btn" onclick="toggle3DRotation()">Toggle Rotation</button>
                    <button class="control-btn" onclick="change3DData()">Change Data</button>
                </div>
            </div>

            <!-- Network Graph -->
            <div class="viz-card">
                <div class="viz-title">🕸️ Dynamic Network Graph</div>
                <div id="graphChart" class="chart-container"></div>
                <div class="controls">
                    <button class="control-btn" onclick="addNode()">Add Node</button>
                    <button class="control-btn" onclick="removeNode()">Remove Node</button>
                </div>
            </div>

            <!-- 3D Surface Plot -->
            <div class="viz-card full-width">
                <div class="viz-title">🏔️ 3D Surface Plot</div>
                <div id="surface3D" class="chart-container small-chart"></div>
                <div class="controls">
                    <button class="control-btn" onclick="changeSurface()">Change Function</button>
                    <button class="control-btn" onclick="toggleWireframe()">Toggle Wireframe</button>
                </div>
            </div>
        </div>
    </div>

    <script>
        // Global variables
        const charts = {};
        let animationFrameId = null;
        let isRotating3D = false;

        // Initialize all charts
        function initCharts() {
            init3DScatter();
            initGraphChart();
            init3DSurface();
        }

        // 3D Scatter Plot
        function init3DScatter() {
            charts.scatter3D = echarts.init(document.getElementById('scatter3D'));

            const data = generate3DScatterData();

            const option = {
                backgroundColor: 'transparent',
                visualMap: {
                    show: true,
                    dimension: 2,
                    min: -5,
                    max: 5,
                    inRange: {
                        color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
                    }
                },
                xAxis3D: { type: 'value' },
                yAxis3D: { type: 'value' },
                zAxis3D: { type: 'value' },
                grid3D: {
                    viewControl: { projection: 'perspective' }
                },
                series: [{
                    type: 'scatter3D',
                    data: data,
                    symbolSize: 12,
                    itemStyle: { opacity: 0.8 }
                }]
            };

            charts.scatter3D.setOption(option);
        }

        function generate3DScatterData() {
            const data = [];
            for (let i = 0; i < 500; i++) {
                data.push([
                    Math.random() * 20 - 10,
                    Math.random() * 20 - 10,
                    Math.random() * 10 - 5
                ]);
            }
            return data;
        }

        function toggle3DRotation() {
            isRotating3D = !isRotating3D;

            if (isRotating3D) {
                let angle = 0;
                function rotate() {
                    if (!isRotating3D) return;

                    angle += 0.01;
                    charts.scatter3D.setOption({
                        grid3D: {
                            viewControl: {
                                beta: angle * 180 / Math.PI
                            }
                        }
                    });

                    animationFrameId = requestAnimationFrame(rotate);
                }
                rotate();
            } else {
                if (animationFrameId) {
                    cancelAnimationFrame(animationFrameId);
                }
            }
        }

        function change3DData() {
            const newData = generate3DScatterData();
            charts.scatter3D.setOption({
                series: [{ data: newData }]
            });
        }

        // Network Graph
        function initGraphChart() {
            charts.graph = echarts.init(document.getElementById('graphChart'));

            const option = {
                backgroundColor: 'transparent',
                series: [{
                    type: 'graph',
                    layout: 'force',
                    data: [
                        { name: 'Node 1', x: 300, y: 300, symbolSize: 50 },
                        { name: 'Node 2', x: 500, y: 300, symbolSize: 40 },
                        { name: 'Node 3', x: 400, y: 450, symbolSize: 45 },
                        { name: 'Node 4', x: 600, y: 400, symbolSize: 35 }
                    ],
                    links: [
                        { source: 0, target: 1 },
                        { source: 0, target: 2 },
                        { source: 1, target: 3 }
                    ],
                    roam: true,
                    force: { repulsion: 1000 }
                }]
            };

            charts.graph.setOption(option);
            charts.graph.nodeIdCounter = 4;
        }

        function addNode() {
            const option = charts.graph.getOption();
            const newNode = {
                name: `Node ${charts.graph.nodeIdCounter + 1}`,
                x: Math.random() * 400 + 200,
                y: Math.random() * 300 + 200,
                symbolSize: Math.random() * 30 + 20
            };

            option.series[0].data.push(newNode);

            // Connect to a random existing node
            if (option.series[0].data.length > 1) {
                const targetIndex = Math.floor(Math.random() * (option.series[0].data.length - 1));
                option.series[0].links.push({
                    source: option.series[0].data.length - 1,
                    target: targetIndex
                });
            }

            charts.graph.setOption(option);
            charts.graph.nodeIdCounter++;
        }

        function removeNode() {
            const option = charts.graph.getOption();
            if (option.series[0].data.length > 3) {
                option.series[0].data.pop();
                if (option.series[0].links.length > 0) {
                    option.series[0].links.pop();
                }
                charts.graph.setOption(option);
            }
        }

        // 3D Surface Plot
        function init3DSurface() {
            charts.surface3D = echarts.init(document.getElementById('surface3D'));
            update3DSurface();
        }

        function generateSurfaceData() {
            const data = [];
            for (let i = -10; i <= 10; i++) {
                for (let j = -10; j <= 10; j++) {
                    data.push([i, j, Math.sin(i / 2) * Math.cos(j / 2)]);
                }
            }
            return data;
        }

        function update3DSurface() {
            const data = generateSurfaceData();

            const option = {
                backgroundColor: 'transparent',
                visualMap: {
                    show: true,
                    dimension: 2,
                    min: -1,
                    max: 1,
                    inRange: {
                        color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf']
                    }
                },
                xAxis3D: { type: 'value' },
                yAxis3D: { type: 'value' },
                zAxis3D: { type: 'value' },
                grid3D: {
                    boxWidth: 200,
                    boxDepth: 200,
                    viewControl: { projection: 'perspective' }
                },
                series: [{
                    type: 'surface',
                    data: data,
                    wireframe: { show: true },
                    itemStyle: { opacity: 0.9 }
                }]
            };

            charts.surface3D.setOption(option);
        }

        function changeSurface() {
            update3DSurface();
        }

        function toggleWireframe() {
            const option = charts.surface3D.getOption();
            const currentWireframe = option.series[0].wireframe.show;
            option.series[0].wireframe.show = !currentWireframe;
            charts.surface3D.setOption(option);
        }

        // Responsive handling
        window.addEventListener('resize', function() {
            Object.values(charts).forEach(chart => {
                if (chart && chart.resize) {
                    chart.resize();
                }
            });
        });

        // Initialize on load
        document.addEventListener('DOMContentLoaded', function() {
            initCharts();
        });
    </script>
</body>
</html>