By the end of this lesson, you will:
Raw numbers from APIs can be overwhelming. Charts help users understand patterns, trends, and insights at a glance.
Chart.js is a popular, beginner-friendly charting library that works well with weather data.
Add Chart.js to your weather dashboard:
<!-- Add to your HTML head -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
Or using npm:
npm install chart.js
Every Chart.js chart follows this pattern:
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'line', // Chart type
data: {
labels: [], // X-axis labels
datasets: [{
label: 'Temperature',
data: [], // Y-axis data
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
}]
},
options: {
responsive: true
}
});
Before creating charts, transform your API data into chart-friendly formats.
function prepareTemperatureData(weatherData) {
// Extract hourly data from weather API
const hourlyData = weatherData.hourly.slice(0, 24); // Next 24 hours
const labels = hourlyData.map(hour => {
const date = new Date(hour.time);
return date.getHours() + ':00';
});
const temperatures = hourlyData.map(hour => hour.temperature);
return { labels, temperatures };
}
// Example weather data structure
const sampleWeatherData = {
hourly: [
{ time: '2024-01-15T00:00', temperature: 18, precipitation: 0, condition: 'clear' },
{ time: '2024-01-15T01:00', temperature: 17, precipitation: 0, condition: 'clear' },
{ time: '2024-01-15T02:00', temperature: 16, precipitation: 2, condition: 'rain' },
// ... more hours
]
};
Line charts are perfect for showing temperature changes over time.
<div class="chart-container">
<h3>24-Hour Temperature Trend</h3>
<canvas id="temperatureChart"></canvas>
</div>
function createTemperatureChart(weatherData) {
const { labels, temperatures } = prepareTemperatureData(weatherData);
const ctx = document.getElementById('temperatureChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Temperature (°C)',
data: temperatures,
borderColor: '#FF6B6B',
backgroundColor: 'rgba(255, 107, 107, 0.1)',
borderWidth: 3,
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
plugins: {
title: {
display: true,
text: 'Temperature Forecast'
}
},
scales: {
y: {
beginAtZero: false,
title: {
display: true,
text: 'Temperature (°C)'
}
},
x: {
title: {
display: true,
text: 'Time'
}
}
}
}
});
}
Bar charts effectively display precipitation amounts across different time periods.
<div class="chart-container">
<h3>Precipitation Forecast</h3>
<canvas id="precipitationChart"></canvas>
</div>
function preparePrecipitationData(weatherData) {
const hourlyData = weatherData.hourly.slice(0, 12); // Next 12 hours
const labels = hourlyData.map(hour => {
const date = new Date(hour.time);
return date.getHours() + ':00';
});
const precipitation = hourlyData.map(hour => hour.precipitation || 0);
return { labels, precipitation };
}
function createPrecipitationChart(weatherData) {
const { labels, precipitation } = preparePrecipitationData(weatherData);
const ctx = document.getElementById('precipitationChart').getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'Precipitation (mm)',
data: precipitation,
backgroundColor: '#4ECDC4',
borderColor: '#45B7B8',
borderWidth: 1
}]
},
options: {
responsive: true,
plugins: {
title: {
display: true,
text: 'Precipitation Forecast'
}
},
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'Precipitation (mm)'
}
}
}
}
});
}
Pie charts show the distribution of different weather conditions.
<div class="chart-container">
<h3>Weather Conditions Distribution</h3>
<canvas id="conditionsChart"></canvas>
</div>
function prepareConditionsData(weatherData) {
const hourlyData = weatherData.hourly.slice(0, 24);
// Count occurrences of each condition
const conditionCounts = {};
hourlyData.forEach(hour => {
const condition = hour.condition;
conditionCounts[condition] = (conditionCounts[condition] || 0) + 1;
});
const labels = Object.keys(conditionCounts);
const data = Object.values(conditionCounts);
return { labels, data };
}
function createConditionsChart(weatherData) {
const { labels, data } = prepareConditionsData(weatherData);
const ctx = document.getElementById('conditionsChart').getContext('2d');
new Chart(ctx, {
type: 'pie',
data: {
labels: labels,
datasets: [{
data: data,
backgroundColor: [
'#FFD93D', // Sunny
'#6BCF7F', // Cloudy
'#4D96FF', // Rainy
'#9B59B6', // Stormy
'#95A5A6' // Other
]
}]
},
options: {
responsive: true,
plugins: {
title: {
display: true,
text: '24-Hour Weather Distribution'
},
legend: {
position: 'bottom'
}
}
}
});
}
Ensure your charts look good on all devices.
.chart-container {
margin: 20px 0;
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.chart-container h3 {
margin-bottom: 15px;
color: #333;
text-align: center;
}
.chart-container canvas {
max-height: 400px;
}
const responsiveOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: window.innerWidth > 768 // Hide legend on mobile
}
}
};
Make charts interactive with tooltips and click events.
const chartOptions = {
interaction: {
intersect: false,
mode: 'index'
},
plugins: {
tooltip: {
callbacks: {
title: function(context) {
return `Time: ${context[0].label}`;
},
label: function(context) {
return `${context.dataset.label}: ${context.parsed.y}°C`;
}
}
}
}
};
const chart = new Chart(ctx, {
// ... chart configuration
options: {
onClick: (event, elements) => {
if (elements.length > 0) {
const clickedElement = elements[0];
const index = clickedElement.index;
console.log(`Clicked on data point ${index}`);
}
}
}
});
Create a comprehensive charting system for your weather dashboard.
class WeatherChartManager {
constructor() {
this.charts = {};
}
async updateAllCharts(weatherData) {
this.destroyExistingCharts();
this.charts.temperature = this.createTemperatureChart(weatherData);
this.charts.precipitation = this.createPrecipitationChart(weatherData);
this.charts.conditions = this.createConditionsChart(weatherData);
}
destroyExistingCharts() {
Object.values(this.charts).forEach(chart => {
if (chart) chart.destroy();
});
this.charts = {};
}
createTemperatureChart(weatherData) {
// Implementation from previous sections
}
createPrecipitationChart(weatherData) {
// Implementation from previous sections
}
createConditionsChart(weatherData) {
// Implementation from previous sections
}
}
// Initialize chart manager
const chartManager = new WeatherChartManager();
// Update charts when new weather data arrives
async function updateWeatherDashboard(city) {
try {
const weatherData = await fetchWeatherData(city);
// Update existing weather display
displayCurrentWeather(weatherData);
// Update charts
await chartManager.updateAllCharts(weatherData);
} catch (error) {
console.error('Error updating dashboard:', error);
}
}
💡 Tip: Charts can be memory-intensive. Always destroy previous charts before creating new ones to prevent memory leaks.
Create a chart showing both minimum and maximum temperatures:
Add functionality to compare weather between two cities:
Extend charts to show 7-day forecasts:
In this lesson, you've learned to:
Data visualization transforms numbers into insights, making your weather dashboard more engaging and useful for users.
In Concept 08, we'll explore Error Handling and User Feedback, learning how to gracefully handle API failures, network issues, and provide meaningful feedback to users when things go wrong.