iT邦幫忙

2024 iThome 鐵人賽

DAY 30
0
JavaScript

Javascript網頁程式管理系統系列 第 30

day 30 javascript腳踏車路線紀錄分享給車友網頁程式管理系統

  • 分享至 

  • xImage
  •  

今天是第三十天我們可以寫一個javascript腳踏車路線紀錄分享給車友網頁程式管理系統,這次非常謝謝iT邦幫忙能給我這次的機會去做三十天的javascript程式碼複習的挑戰,不能太久沒寫程式碼跟文章會有點生疏,以下是第三十天的程式碼

系統功能需求

  1. 用戶註冊/登入: 允許使用者創建帳號和登入,以便紀錄和管理自己的路線。
  2. 路線紀錄: 使用者可以上傳或手動紀錄他們的騎行路線(包括距離、時間、速度等)。
  3. 路線分享: 使用者可以將路線分享給其他使用者或公開分享。
  4. 查看和管理路線: 用戶可以查看過去的騎行路線,並管理(編輯、刪除)這些資料。
  5. 地圖顯示: 路線可以顯示在互動地圖上,例如使用 Google Maps API 或 OpenStreetMap。
  6. 後端管理系統: 管理者可以查看所有使用者的路線並進行管理。

基本技術

  • 前端技術: HTML, CSS, JavaScript, Google Maps API/OpenStreetMap API
  • 後端技術: Node.js, Express.js
  • 資料庫: MongoDB/MySQL
  • 版本控制: Git/GitHub

前端基本範例:HTML 和 JavaScript

<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>腳踏車路線紀錄分享系統</title>
    <style>
        body { font-family: Arial, sans-serif; }
        .container { max-width: 800px; margin: auto; padding: 20px; }
        h1 { text-align: center; }
        #map { height: 400px; width: 100%; }
        .route-info { margin-top: 20px; }
    </style>
</head>
<body>

<div class="container">
    <h1>腳踏車路線紀錄分享</h1>

    <!-- 地圖顯示區域 -->
    <div id="map"></div>

    <!-- 路線資訊顯示區域 -->
    <div class="route-info">
        <h2>路線資訊</h2>
        <p><strong>距離:</strong><span id="distance">0 公里</span></p>
        <p><strong>時間:</strong><span id="time">0 分鐘</span></p>
        <p><strong>速度:</strong><span id="speed">0 公里/小時</span></p>
    </div>

    <!-- 分享按鈕 -->
    <button id="shareRoute">分享路線</button>
</div>

<!-- Google Maps API 加載 -->
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_MAPS_API_KEY"></script>
<script>
    let map;
    let routePath;

    function initMap() {
        // 初始地圖位置
        map = new google.maps.Map(document.getElementById('map'), {
            center: { lat: 25.0330, lng: 121.5654 }, // 台北101座標
            zoom: 14
        });

        // 假設有一條預定義的路線資料 (這裡應該從伺服器獲取)
        const routeCoordinates = [
            { lat: 25.0330, lng: 121.5654 }, // 起點
            { lat: 25.0370, lng: 121.5684 }, // 途中
            { lat: 25.0420, lng: 121.5700 }  // 終點
        ];

        routePath = new google.maps.Polyline({
            path: routeCoordinates,
            geodesic: true,
            strokeColor: '#FF0000',
            strokeOpacity: 1.0,
            strokeWeight: 2
        });

        routePath.setMap(map);

        // 計算並顯示路線資訊
        calculateRouteInfo(routeCoordinates);
    }

    function calculateRouteInfo(coordinates) {
        // 假設我們可以計算距離、時間、速度 (這裡用假數據)
        const distance = 5; // 公里
        const time = 20; // 分鐘
        const speed = distance / (time / 60); // 公里/小時

        document.getElementById('distance').innerText = `${distance} 公里`;
        document.getElementById('time').innerText = `${time} 分鐘`;
        document.getElementById('speed').innerText = `${speed.toFixed(2)} 公里/小時`;
    }

    // 分享路線按鈕的事件處理
    document.getElementById('shareRoute').addEventListener('click', () => {
        alert('路線已成功分享給車友!');
        // 這裡可以添加實際的分享邏輯,例如發送到後端伺服器
    });

    // 加載地圖
    window.onload = initMap;
</script>

</body>
</html>

後端(Node.js + Express.js)範例

安裝 Node.js 和 Express:

npm init -y
npm install express mongoose

建立基本的 Express 伺服器:

const express = require('express');
const mongoose = require('mongoose');
const app = express();

// 連接 MongoDB 資料庫
mongoose.connect('mongodb://localhost:27017/bike_routes', {
    useNewUrlParser: true,
    useUnifiedTopology: true,
});

// 建立路線 Schema 和 Model
const routeSchema = new mongoose.Schema({
    user: String,
    routeCoordinates: Array,
    distance: Number,
    time: Number,
    speed: Number,
    shared: Boolean,
});

const Route = mongoose.model('Route', routeSchema);

// 中介軟體
app.use(express.json());

// 路線紀錄 API
app.post('/api/routes', async (req, res) => {
    try {
        const newRoute = new Route(req.body);
        await newRoute.save();
        res.status(201).send(newRoute);
    } catch (error) {
        res.status(400).send(error);
    }
});

// 獲取所有分享的路線 API
app.get('/api/routes', async (req, res) => {
    try {
        const routes = await Route.find({ shared: true });
        res.send(routes);
    } catch (error) {
        res.status(500).send(error);
    }
});

// 伺服器啟動
app.listen(3000, () => {
    console.log('伺服器在 http://localhost:3000 上運行');
});

資料庫

  • MongoDB:適合處理地理坐標資料和使用者路線記錄,可以儲存騎行數據,並通過後端 API 檢索和分享。

要在這個腳踏車路線紀錄分享系統中添加 MongoDB 支援,並且讓資料能夠存儲和分享給車友,我們需要編寫伺服器端來處理數據的儲存和檢索。我將會用 Node.js 和 MongoDB 來構建這個後端系統。

MongoDB + Node.js 後端程式碼

  1. 步驟一:安裝需要的套件
    首先,我需要在專案中安裝以下套件:

    npm install express mongoose body-parser cors
    
  2. 步驟二:建立伺服器端程式碼

    在專案的根目錄中創建一個檔案 server.js,並在其中編寫如下程式碼:

    const express = require('express');
    const mongoose = require('mongoose');
    const bodyParser = require('body-parser');
    const cors = require('cors');
    
    const app = express();
    const port = 3000;
    
    // 使用 CORS 允許跨域請求
    app.use(cors());
    
    // 解析 JSON 格式的請求資料
    app.use(bodyParser.json());
    
    // MongoDB 連線
    mongoose.connect('mongodb://localhost:27017/cyclingRoutes', {
        useNewUrlParser: true,
        useUnifiedTopology: true
    }).then(() => console.log('MongoDB 連線成功'))
      .catch(err => console.log(err));
    
    // 定義路線資料的 Schema
    const routeSchema = new mongoose.Schema({
        coordinates: Array,
        distance: Number,
        time: Number,
        speed: Number,
        sharedBy: String,
        dateShared: { type: Date, default: Date.now }
    });
    
    // 建立路線模型
    const Route = mongoose.model('Route', routeSchema);
    
    // API: 儲存路線
    app.post('/api/routes', async (req, res) => {
        try {
            const newRoute = new Route(req.body);
            const savedRoute = await newRoute.save();
            res.status(200).json(savedRoute);
        } catch (error) {
            res.status(400).json({ error: '無法儲存路線' });
        }
    });
    
    // API: 獲取所有共享的路線
    app.get('/api/routes', async (req, res) => {
        try {
            const routes = await Route.find();
            res.status(200).json(routes);
        } catch (error) {
            res.status(400).json({ error: '無法獲取路線' });
        }
    });
    
    // 啟動伺服器
    app.listen(port, () => {
        console.log(`伺服器正在 ${port} 埠運行...`);
    });
    

程式碼解釋

  1. 安裝和設置伺服器:

    • 使用 express 作為 HTTP 伺服器框架。
    • mongoose 用於連接 MongoDB 資料庫並處理數據儲存。
    • body-parser 幫助解析 JSON 格式的請求數據。
    • cors 允許跨域請求,這樣前端可以與伺服器通信。
  2. MongoDB 連線:

    • 使用 mongoose.connect 連接本地的 MongoDB 伺服器(你也可以將 mongodb://localhost:27017/cyclingRoutes 更改為你的雲端 MongoDB 連接字串)。
    • 如果連線成功,會顯示 "MongoDB 連線成功"。
  3. 資料模型定義:

    • 我們定義了一個 routeSchema,包含了共享的路線資料,如:
      • coordinates:路線的經緯度數據。
      • distance:路線的距離(公里)。
      • time:所花時間(分鐘)。
      • speed:平均速度(公里/小時)。
      • sharedBy:分享者的名稱。
      • dateShared:自動記錄的分享日期。
  4. API 端點:

    • POST /api/routes:接收從前端傳來的路線數據,並儲存在 MongoDB 中。
    • GET /api/routes:返回所有已分享的路線數據。
  5. 啟動伺服器:

    • 伺服器會在本地端的 3000 埠運行,可以在瀏覽器或 Postman 中通過 http://localhost:3000 訪問。

前端與伺服器整合

在前端程式中,當用戶按下 "分享路線" 按鈕時,我們需要將路線資訊發送到後端的 API。請修改之前的前端程式碼,讓其在按下按鈕後,將資料發送到伺服器。

// 分享路線按鈕的事件處理
document.getElementById('shareRoute').addEventListener('click', () => {
    const routeData = {
        coordinates: [
            { lat: 25.0330, lng: 121.5654 },
            { lat: 25.0370, lng: 121.5684 },
            { lat: 25.0420, lng: 121.5700 }
        ],
        distance: 5,  // 假設的距離數據
        time: 20,     // 假設的時間數據
        speed: 15,    // 假設的速度數據
        sharedBy: "車友A"  // 假設的分享者名稱
    };

    // 發送 POST 請求到伺服器端
    fetch('http://localhost:3000/api/routes', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(routeData)
    })
    .then(response => response.json())
    .then(data => {
        alert('路線已成功分享給車友!');
        console.log('分享的路線資料:', data);
    })
    .catch(error => {
        console.error('分享路線時發生錯誤:', error);
        alert('無法分享路線,請稍後再試。');
    });
});

整合後的工作流程

  1. 使用者按下 "分享路線" 按鈕。
  2. 前端 JavaScript 會將路線數據(包括座標、距離、時間、速度和分享者名稱)發送到後端伺服器。
  3. 後端伺服器將收到的數據儲存到 MongoDB 中。
  4. 當儲存成功後,伺服器回應前端,並顯示 "路線已成功分享" 的提示給使用者。

運行步驟

  1. 啟動 MongoDB 伺服器,若在本地使用 MongoDB,請確保它正在運行。
  2. 執行 Node.js 伺服器:
    node server.js
    
  3. 在瀏覽器中加載前端頁面並測試分享路線功能。

這樣我就可以建立一個完整的腳踏車路線分享系統,並通過 MongoDB 儲存路線數據。
我會逐步解釋你提供的程式碼及我補充的 MongoDB 伺服器部分,幫助你了解每個部分的功能和工作原理。

前端部分

這部分是 HTML 和 JavaScript,用來顯示路線記錄並與後端互動,將路線資料分享給車友。

1. HTML 結構

<h1>腳踏車路線記錄分享系統</h1>
<button id="shareRoute">分享路線</button>
  • <h1>: 顯示頁面標題「腳踏車路線記錄分享系統」。
  • <button>: 這個按鈕當用戶點擊時會觸發 "分享路線" 的功能。

2. JavaScript 分享邏輯

document.getElementById('shareRoute').addEventListener('click', () => {
    const routeData = {
        coordinates: [
            { lat: 25.0330, lng: 121.5654 },
            { lat: 25.0370, lng: 121.5684 },
            { lat: 25.0420, lng: 121.5700 }
        ],
        distance: 5,
        time: 20,
        speed: 15,
        sharedBy: "車友A"
    };

    fetch('http://localhost:3000/api/routes', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(routeData)
    })
    .then(response => response.json())
    .then(data => {
        alert('路線已成功分享給車友!');
        console.log('分享的路線資料:', data);
    })
    .catch(error => {
        console.error('分享路線時發生錯誤:', error);
        alert('無法分享路線,請稍後再試。');
    });
});
  • document.getElementById('shareRoute').addEventListener('click', ...:當按下「分享路線」按鈕時觸發的事件處理器。

  • const routeData = { ... }:這段定義了要分享的路線資料。裡面包含:

    • coordinates:一個包含 GPS 座標的陣列,記錄路線的經緯度。
    • distance:這條路線的距離(單位:公里)。
    • time:所花的時間(單位:分鐘)。
    • speed:平均速度(單位:公里/小時)。
    • sharedBy:分享者的名稱。
  • fetch('http://localhost:3000/api/routes', {...}:這是將路線資料送到伺服器的 POST 請求。

    • method: 'POST':指定這是一個 POST 請求,用來將資料傳到伺服器。
    • headers: { 'Content-Type': 'application/json' }:設定請求頭,告訴伺服器我們送的是 JSON 資料。
    • body: JSON.stringify(routeData):將 routeData 轉換為 JSON 格式並放在請求的主體中傳送到伺服器。
  • then(response => response.json()):當伺服器成功處理請求並返回資料時,將返回的資料轉換成 JSON 格式。

  • alert('路線已成功分享給車友!'):顯示一個提示,告訴使用者路線已經成功分享。

  • catch(error => {...}):若有錯誤發生,將顯示錯誤訊息。

後端 (伺服器端) 程式碼

這部分是基於 Node.js 和 MongoDB,處理前端發送的路線數據並儲存在 MongoDB 資料庫中。

1. 引入套件

const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cors = require('cors');
  • express:Node.js 的伺服器框架,用於建立 HTTP API 和處理請求。
  • mongoose:MongoDB 驅動,用來與 MongoDB 連線及操作資料。
  • body-parser:用來解析前端傳送過來的 JSON 格式資料。
  • cors:允許不同來源的網站(前端)請求伺服器 API,解決跨域問題。

2. 建立伺服器

const app = express();
const port = 3000;
app.use(cors());
app.use(bodyParser.json());
  • const app = express();:創建 Express 應用程式的實例。
  • app.use(cors());:允許跨域請求,這樣前端和後端即使來自不同的來源也能通信。
  • app.use(bodyParser.json());:讓伺服器能夠處理 JSON 格式的請求主體(例如前端傳過來的資料)。

3. 連接 MongoDB

mongoose.connect('mongodb://localhost:27017/cyclingRoutes', {
    useNewUrlParser: true,
    useUnifiedTopology: true
}).then(() => console.log('MongoDB 連線成功'))
  .catch(err => console.log(err));
  • mongoose.connect:連接到本地 MongoDB 資料庫 cyclingRoutes
  • useNewUrlParser: trueuseUnifiedTopology: true 是 MongoDB 新版的設置,確保連接穩定。
  • .then(() => ...):如果連接成功,會在控制台輸出 "MongoDB 連線成功"。
  • .catch(err => ...):如果連接失敗,會顯示錯誤訊息。

4. 定義 MongoDB 的 Schema 和 Model

const routeSchema = new mongoose.Schema({
    coordinates: Array,
    distance: Number,
    time: Number,
    speed: Number,
    sharedBy: String,
    dateShared: { type: Date, default: Date.now }
});
const Route = mongoose.model('Route', routeSchema);
  • mongoose.Schema:定義資料的結構。

    • coordinates:一個陣列,儲存路線的經緯度座標。
    • distance:路線的總距離。
    • time:總用時。
    • speed:平均速度。
    • sharedBy:路線的分享者。
    • dateShared:自動記錄路線分享的日期,預設為現在的日期。
  • mongoose.model('Route', routeSchema):創建一個資料模型 Route,這會對應到 MongoDB 中的 routes 集合。

5. API:儲存路線 (POST 請求)

app.post('/api/routes', async (req, res) => {
    try {
        const newRoute = new Route(req.body);
        const savedRoute = await newRoute.save();
        res.status(200).json(savedRoute);
    } catch (error) {
        res.status(400).json({ error: '無法儲存路線' });
    }
});
  • app.post('/api/routes', ...):定義一個 POST 請求的 API 端點。

  • req.body:這包含了從前端傳來的路線數據(coordinates, distance, `time

  • 好的,繼續解釋:

  • new Route(req.body):這段程式碼根據前端傳過來的資料建立一個新的 Route 實例。req.body 包含了前端送來的路線資訊,比如經緯度、距離、時間、速度和分享者。

  • await newRoute.save():將這個新建的路線資料存入 MongoDB 資料庫。save() 是一個非同步操作,因此使用 await 來等待它完成。

  • res.status(200).json(savedRoute):如果資料成功儲存,伺服器會回應狀態碼 200(成功)並將儲存的路線資料以 JSON 格式回傳給前端。

  • catch (error):如果儲存過程中發生錯誤(例如資料庫連線問題),伺服器會返回狀態碼 400,並回應一個錯誤訊息,告訴前端「無法儲存路線」。

6. 啟動伺服器

app.listen(port, () => {
    console.log(`伺服器正在 http://localhost:${port} 上運行`);
});
  • app.listen(port, ...):這行程式碼啟動伺服器,監聽在指定的端口(這裡是 3000),並在伺服器啟動時輸出一條訊息,告訴你伺服器運行在哪個網址。

整體流程總結

  1. 當使用者在前端按下「分享路線」按鈕後,JavaScript 將構建一個包含路線資料的物件,並使用 fetch() 函數發送一個 POST 請求到伺服器(http://localhost:3000/api/routes)。
  2. 後端伺服器接收到請求後,使用 Express 的 POST 路由處理這個請求,並將路線資料存入 MongoDB。
  3. 如果資料成功存入資料庫,伺服器會回應成功訊息;如果發生錯誤,伺服器會回傳錯誤訊息,通知使用者分享失敗。
  4. 最後,伺服器將所有收到的路線儲存到 MongoDB 資料庫的 routes 集合中,並記錄每次分享的日期。

最後真的非常謝謝iT邦幫忙給我這次複習的機會讓我能更精進javascript程式碼,希望我這次有系統性的程式碼能夠得獎,謝謝iT邦幫忙!


上一篇
day 29 javascript結合line分析地價成長空間網頁程式管理系統
系列文
Javascript網頁程式管理系統30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言