如何使用select/option标签实现多种Chart.js图表的切换展示?
Hey there! Let's get that chart switching feature up and running with your existing Chart.js graphs. I'll walk you through a clean, efficient solution that uses a <select> dropdown to toggle between your four charts—no messy multiple canvases needed (though I'll note an alternative if you prefer that route).
Step 1: Update Your HTML
First, add a dropdown selector and a single canvas element (we'll reuse this for all charts to keep things lean):
<!-- Chart Selector Dropdown --> <select id="chartSelector" style="padding: 8px; margin-bottom: 16px;"> <option value="population">温哥华人口折线图</option> <option value="precipitation">降水量柱状图</option> <option value="ethnicity">族群饼图</option> <option value="activity">居民活动雷达图</option> </select> <!-- Reusable Canvas for All Charts --> <canvas id="chartCanvas" width="600" height="400"></canvas>
Step 2: Refactor Your Chart JavaScript
We'll wrap each chart's initialization in a dedicated function, add a global variable to track the current chart instance (critical for avoiding Chart.js conflicts), and hook up the dropdown's change event.
Here's the full JS code (merge in your existing chart data if you have custom values):
// Track the current Chart.js instance to destroy it when switching let currentChart = null; // 1. 初始化温哥华人口折线图 function initPopulationChart() { const ctx = document.getElementById('chartCanvas').getContext('2d'); currentChart = new Chart(ctx, { type: 'line', data: { labels: ['2010', '2015', '2020', '2025'], datasets: [{ label: '温哥华人口', data: [603502, 631486, 662248, 690000], borderColor: 'rgb(75, 192, 192)', tension: 0.1 }] }, options: { responsive: true, title: { display: true, text: '温哥华人口变化趋势' } } }); } // 2. 初始化降水量柱状图 function initPrecipitationChart() { const ctx = document.getElementById('chartCanvas').getContext('2d'); currentChart = new Chart(ctx, { type: 'bar', data: { labels: ['1月', '2月', '3月', '4月', '5月', '6月'], datasets: [{ label: '月降水量(mm)', data: [149, 120, 112, 88, 65, 50], backgroundColor: 'rgba(255, 99, 132, 0.2)', borderColor: 'rgba(255, 99, 132, 1)', borderWidth: 1 }] }, options: { responsive: true, title: { display: true, text: '温哥华月降水量统计' }, scales: { y: { beginAtZero: true } } } }); } // 3. 初始化族群饼图 function initEthnicityChart() { const ctx = document.getElementById('chartCanvas').getContext('2d'); currentChart = new Chart(ctx, { type: 'pie', data: { labels: ['欧洲裔', '亚裔', '原住民', '其他'], datasets: [{ label: '族群占比', data: [46, 40, 2, 12], backgroundColor: [ 'rgba(255, 206, 86, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 99, 132, 0.2)', 'rgba(75, 192, 192, 0.2)' ], borderColor: [ 'rgba(255, 206, 86, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 99, 132, 1)', 'rgba(75, 192, 192, 1)' ], borderWidth: 1 }] }, options: { responsive: true, title: { display: true, text: '温哥华族群分布' } } }); } // 4. 初始化居民活动雷达图 function initActivityChart() { const ctx = document.getElementById('chartCanvas').getContext('2d'); currentChart = new Chart(ctx, { type: 'radar', data: { labels: ['工作', '休闲', '运动', '社交', '学习'], datasets: [{ label: '居民每日活动时长(小时)', data: [8, 3, 1.5, 2, 1], backgroundColor: 'rgba(153, 102, 255, 0.2)', borderColor: 'rgba(153, 102, 255, 1)', pointBackgroundColor: 'rgba(153, 102, 255, 1)', pointBorderColor: '#fff', pointHoverBackgroundColor: '#fff', pointHoverBorderColor: 'rgba(153, 102, 255, 1)' }] }, options: { responsive: true, title: { display: true, text: '温哥华居民日常活动分布' }, scales: { r: { beginAtZero: true, max: 10 } } } }); } // Initialize default chart and setup dropdown listener document.addEventListener('DOMContentLoaded', () => { // Start with the population line chart initPopulationChart(); // Handle dropdown selection changes const selector = document.getElementById('chartSelector'); selector.addEventListener('change', () => { // Destroy the current chart first to avoid Chart.js rendering conflicts if (currentChart) currentChart.destroy(); // Switch to the selected chart switch(selector.value) { case 'population': initPopulationChart(); break; case 'precipitation': initPrecipitationChart(); break; case 'ethnicity': initEthnicityChart(); break; case 'activity': initActivityChart(); break; default: initPopulationChart(); } }); });
Key Notes for Success
- Reuse a single canvas: This is more efficient than having multiple hidden canvases, and keeps your DOM clean.
- Destroy old charts: Always call
currentChart.destroy()before initializing a new one—this prevents Chart.js from throwing errors or rendering overlapping graphs. - Encapsulate chart logic: Wrapping each chart in its own function makes your code easier to debug and update later (e.g., if you need to tweak the population data, you only touch one function).
- DOMContentLoaded event: Ensures we don't try to initialize charts before the canvas element exists in the DOM.
Alternative: Multiple Canvases (If You Prefer)
If you want to keep separate canvases for each chart, you can:
- Add four canvas elements, each with a unique ID, and set
style="display:none;"on all except the default one. - In the dropdown's change event, hide all canvases, show the selected one, and initialize its chart if it hasn't been created yet.
- Still remember to destroy old chart instances if you reinitialize them.
内容的提问来源于stack exchange,提问作者Jun Jung

