データ活用&Webアプリ作成プログラム 人口アプリ

JavaScript

はじめに

どうも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アプリを作って少しづつ実力が付いてきているのはないでしょうか。

タイトルとURLをコピーしました