はじめに
どうもSeiyaです!前回天気アプリを作りましたね。次は人口アプリを作成します!
コード
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>人口ダッシュボード</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
color: #333;
text-align: center;
transition: 0.3s;
}
.container {
max-width: 600px;
margin: auto;
padding: 20px;
background: white;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
border-radius: 10px;
}
input, button {
padding: 10px;
margin: 10px;
font-size: 16px;
}
button {
cursor: pointer;
}
.dark-mode {
background-color: #333;
color: white;
}
.dark-mode .container {
background: #444;
}
.dark-mode button {
background: #666;
color: white;
}
</style>
</head>
<body>
<div class="container">
<h1>🌍 世界人口ダッシュボード</h1>
<input type="text" id="search-input" placeholder="国名を入力(例: JP, US, CN)">
<button id="search-button">検索</button>
<button id="dark-mode-toggle">🌙 ダークモード</button>
<div id="population-display"></div>
<h2>📊 人口推移グラフ</h2>
<canvas id="populationChart"></canvas>
<h2>🏆 人口ランキング</h2>
<ul id="ranking-list"></ul>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
const searchInput = document.getElementById("search-input");
const searchButton = document.getElementById("search-button");
const populationDisplay = document.getElementById("population-display");
const rankingList = document.getElementById("ranking-list");
const darkModeToggle = document.getElementById("dark-mode-toggle");
const body = document.body;
const ctx = document.getElementById("populationChart").getContext("2d");
let chart;
// ダークモードの状態を初期化
if (localStorage.getItem("dark-mode") === "enabled") {
body.classList.add("dark-mode");
}
darkModeToggle.addEventListener("click", () => {
body.classList.toggle("dark-mode");
localStorage.setItem("dark-mode", body.classList.contains("dark-mode") ? "enabled" : "disabled");
});
searchButton.addEventListener("click", async () => {
const country = searchInput.value.trim().toUpperCase();
if (!country) return;
const data = await fetchPopulationData(country);
if (data) {
displayPopulation(data);
updateChart(data.history);
}
});
async function fetchPopulationData(country) {
try {
const response = await fetch(`https://api.worldbank.org/v2/country/${country}/indicator/SP.POP.TOTL?format=json&date=2010:2020`);
const data = await response.json();
if (data[1]) {
return {
name: country,
population: data[1][0].value,
history: data[1].map(entry => ({ year: entry.date, value: entry.value })).reverse()
};
}
} catch (error) {
console.error("Error fetching data:", error);
}
return null;
}
function displayPopulation(data) {
populationDisplay.innerHTML = `<h2>${data.name}</h2><p>人口: ${data.population.toLocaleString()}</p>`;
}
function updateChart(history) {
if (chart) chart.destroy();
chart = new Chart(ctx, {
type: "line",
data: {
labels: history.map(h => h.year),
datasets: [{
label: "人口推移",
data: history.map(h => h.value),
borderColor: "blue",
borderWidth: 2,
}]
}
});
}
async function fetchPopulationRanking() {
try {
const response = await fetch(`https://api.worldbank.org/v2/country/all/indicator/SP.POP.TOTL?format=json&date=2020`);
const data = await response.json();
if (data[1]) {
const ranking = data[1].sort((a, b) => b.value - a.value).slice(0, 10);
rankingList.innerHTML = ranking.map((entry, index) => `<li>${index + 1}. ${entry.country.value}: ${entry.value.toLocaleString()}</li>`).join("");
}
} catch (error) {
console.error("Error fetching ranking:", error);
}
}
fetchPopulationRanking();
});
</script>
</body>
</html>
解説
HTML
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>人口ダッシュボード</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<div class="container">
<h1>🌍 世界人口ダッシュボード</h1>
<input type="text" id="search-input" placeholder="国名を入力(例: JP, US, CN)">
<button id="search-button">検索</button>
<button id="dark-mode-toggle">🌙 ダークモード</button>
<div id="population-display"></div>
<h2>📊 人口推移グラフ</h2>
<canvas id="populationChart"></canvas>
<h2>🏆 人口ランキング</h2>
<ul id="ranking-list"></ul>
</div>
<script>
// JavaScriptコード(後述)
</script>
</body>
</html>
<input>
と <button>
で国コードを入力・検索<canvas>
で人口推移グラフを表示<ul>
に世界の人口ランキングを表示Chart.js
をCDNで読み込み(グラフ描画用)
CSS
HTML
<style>
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
color: #333;
text-align: center;
transition: 0.3s;
}
.container {
max-width: 600px;
margin: auto;
padding: 20px;
background: white;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
border-radius: 10px;
}
input, button {
padding: 10px;
margin: 10px;
font-size: 16px;
}
button {
cursor: pointer;
}
/* ダークモード */
body.dark-mode {
background-color: #333;
color: white;
}
body.dark-mode .container {
background: #444;
}
body.dark-mode button {
background: #666;
color: white;
}
</style>
.container
で中央寄せ&デザイン設定.dark-mode
でダークモードを適用
JavaScript
HTML
<script>
document.addEventListener("DOMContentLoaded", () => {
const searchInput = document.getElementById("search-input");
const searchButton = document.getElementById("search-button");
const populationDisplay = document.getElementById("population-display");
const rankingList = document.getElementById("ranking-list");
const darkModeToggle = document.getElementById("dark-mode-toggle");
const body = document.body;
const ctx = document.getElementById("populationChart").getContext("2d");
let chart;
// ダークモードの状態を保存・復元
if (localStorage.getItem("dark-mode") === "enabled") {
body.classList.add("dark-mode");
}
darkModeToggle.addEventListener("click", () => {
body.classList.toggle("dark-mode");
localStorage.setItem("dark-mode", body.classList.contains("dark-mode") ? "enabled" : "disabled");
});
searchButton.addEventListener("click", async () => {
const country = searchInput.value.trim().toUpperCase();
if (!country) return;
const data = await fetchPopulationData(country);
if (data) {
displayPopulation(data);
updateChart(data.history);
}
});
async function fetchPopulationData(country) {
try {
const response = await fetch(`https://api.worldbank.org/v2/country/${country}/indicator/SP.POP.TOTL?format=json&date=2010:2020`);
const data = await response.json();
if (data[1]) {
return {
name: country,
population: data[1][0].value,
history: data[1].map(entry => ({ year: entry.date, value: entry.value })).reverse()
};
}
} catch (error) {
console.error("Error fetching data:", error);
}
return null;
}
function displayPopulation(data) {
populationDisplay.innerHTML = `<h2>${data.name}</h2><p>人口: ${data.population.toLocaleString()}</p>`;
}
function updateChart(history) {
if (chart) chart.destroy();
chart = new Chart(ctx, {
type: "line",
data: {
labels: history.map(h => h.year),
datasets: [{
label: "人口推移",
data: history.map(h => h.value),
borderColor: "blue",
borderWidth: 2,
}]
}
});
}
async function fetchPopulationRanking() {
try {
const response = await fetch(`https://api.worldbank.org/v2/country/all/indicator/SP.POP.TOTL?format=json&date=2020`);
const data = await response.json();
if (data[1]) {
const ranking = data[1].sort((a, b) => b.value - a.value).slice(0, 10);
rankingList.innerHTML = ranking.map((entry, index) => `<li>${index + 1}. ${entry.country.value}: ${entry.value.toLocaleString()}</li>`).join("");
}
} catch (error) {
console.error("Error fetching ranking:", error);
}
}
fetchPopulationRanking();
});
</script>
ダークモード
localStorage
に設定を保存- 初回ロード時に状態を復元
- クリック時に
classList.toggle("dark-mode")
人口データ取得
fetchPopulationData()
で World Bank API から人口データを取得displayPopulation()
で画面に表示
グラフ更新
updateChart()
で Chart.js を利用し、人口推移を折れ線グラフで表示
人口ランキング
fetchPopulationRanking()
で 2020年の世界人口ランキング を取得sort()
で並び替え、上位10カ国を表示
おわりに
人口アプリを作成できましたでしょうか?2アプリを作って少しづつ実力が付いてきているのはないでしょうか。