BMR 計算器技術實作

深入了解基礎代謝率計算器的實作原理,包含 Mifflin-St Jeor 公式、活動因子計算、雙語系統整合和響應式設計

概述

BMR 計算器是一個專業的基礎代謝率計算工具,專為健康管理、營養規劃和健身愛好者設計,能夠精確計算每日基礎代謝率和總熱量消耗。 本工具採用純前端架構,完全在瀏覽器端運行,零網路傳輸,確保用戶隱私和數據安全。 採用國際權威的 Mifflin-St Jeor 公式,支援公制英制雙單位系統、多活動等級計算、即時雙語切換、響應式設計等專業功能。

🔒 隱私保護承諾

所有 BMR 和 TDEE 計算都在您的瀏覽器本地進行,個人健康數據不會上傳到任何伺服器,確保您的敏感健康資訊完全安全。

技術架構與核心設計

整體架構設計

技術項目 實作方式 設計考量
前端框架 原生 JavaScript ES6+ 零依賴,快速載入,完全本地化
計算引擎 Mifflin-St Jeor 公式 國際醫學標準,精確度高
單位系統 公制/英制動態切換 全球用戶友好,即時轉換
語言系統 雙語即時切換 整合全域語言管理
視覺設計 漸層背景 + 卡片式佈局 現代化 UI,專業健康感

數學算法實作

🧮 Mifflin-St Jeor 公式

男性:BMR = 10 × 體重(kg) + 6.25 × 身高(cm) - 5 × 年齡(歲) + 5

女性:BMR = 10 × 體重(kg) + 6.25 × 身高(cm) - 5 × 年齡(歲) - 161

TDEE:BMR × 活動因子 (1.2 - 1.9)

關鍵功能特色

⚕️ 精確計算

採用國際醫學認可的 Mifflin-St Jeor 公式,提供最準確的 BMR 和 TDEE 計算結果,適用於健康管理和營養規劃。

🔄 雙單位支援

完整支援公制 (cm/kg) 和英制 (in/lb) 單位系統,一鍵切換,自動轉換計算,適應全球用戶需求。

🎯 活動等級分析

提供 5 種詳細活動等級選擇,從久坐到非常活躍,精確計算個人化的每日總熱量消耗 (TDEE)。

🌐 即時雙語

完美整合 Tool Master 全域語言系統,支援中英文即時切換,所有介面元素和計算結果同步更新。

📱 響應式設計

適配手機、平板、桌面各種設備,優雅的漸層視覺設計,專業的健康工具使用體驗。

🔒 隱私安全

100% 本地計算,健康數據絕不上傳,即時計算結果,無需等待,保護用戶隱私安全。

實作細節

以下是完整程式碼實作,按功能模組分類展示。點擊卡片標題可展開查看詳細程式碼:

📦 核心 BMR 計算器類別

功能:主要的 BMRCalculator 類別,包含建構函數、初始化方法和核心配置

/**
 * BMR Calculator - Core Implementation
 * BMR 計算器 - 核心實作
 * 
 * 基礎代謝率計算器,採用 Mifflin-St Jeor 公式
 * Basal Metabolic Rate calculator using Mifflin-St Jeor formula
 */
class BMRCalculator {
    constructor() {
        // 核心狀態管理 / Core state management
        this.currentUnit = 'metric';              // 當前單位系統:metric(公制) / imperial(英制)
        this.currentLanguage = 'zh';             // 當前語言:zh(中文) / en(英文)
        this.selectedGender = null;              // 選擇的性別:male / female / null
        this.translations = {};                  // 翻譯字典物件
        this.activityLevels = {};               // 活動等級配置
        
        // 初始化應用程式 / Initialize application
        this.init();
    }

    /**
     * 非同步初始化方法
     * Asynchronous initialization method
     * 
     * 按順序執行所有初始化步驟,確保系統正常運作
     * Execute all initialization steps in order to ensure system operates properly
     */
    async init() {
        try {
            this.getElements();                  // 取得 DOM 元素引用
            await this.loadConfig();             // 載入配置和翻譯資料
            this.setupGlobalLanguageListener(); // 設置全域語言監聽器(必須優先)
            this.setupEventListeners();         // 綁定所有事件監聽器
            this.updateUIText();                // 更新介面文字為當前語言
        } catch (error) {
            console.error('BMR Calculator 初始化錯誤:', error);
        }
    }

🌐 全域語言系統整合

功能:整合 Tool Master 全域語言切換系統,支援即時雙語切換

/**
 * 設置全域語言監聽器
 * Setup global language listener
 * 
 * 這是工具與 Tool Master 語言系統整合的關鍵方法
 * This is the key method for tool integration with Tool Master language system
 */
setupGlobalLanguageListener() {
    // 監聽全域語言切換事件 / Listen for global language change events
    window.addEventListener('languageChanged', (event) => {
        this.currentLanguage = event.detail.language;
        this.updateUIText();                // 立即更新所有介面文字
        
        // 如果結果已顯示,重新更新結果描述 / If results are shown, update result descriptions
        if (this.elements.resultContainer.classList.contains('show')) {
            this.updateResultDescriptions();
        }
    });
    
    /**
     * 處理初始化時序問題
     * Handle initialization timing issues
     * 
     * 確保工具能正確取得初始語言狀態
     * Ensure tool can correctly get initial language state
     */
    const checkGlobalLanguage = () => {
        if (window.globalI18n) {
            this.currentLanguage = window.globalI18n.currentLanguage;
            this.updateUIText();
            return true;
        }
        return false;
    };
    
    // 立即檢查,如果失敗則延遲重試 / Check immediately, retry with delay if failed
    if (!checkGlobalLanguage()) {
        setTimeout(() => {
            checkGlobalLanguage();
        }, 100);
    }
}

/**
 * 更新所有介面文字
 * Update all interface text
 * 
 * 根據當前語言更新所有可見的文字內容
 * Update all visible text content according to current language
 */
updateUIText() {
    const t = this.translations[this.currentLanguage];
    if (!t) return;
    
    // 更新標題區域 / Update header area
    this.elements.headerTitle.textContent = t.title;
    this.elements.headerSubtitle.textContent = t.subtitle;
    
    // 更新單位切換按鈕 / Update unit toggle buttons
    this.elements.metricBtn.textContent = t.metric;
    this.elements.imperialBtn.textContent = t.imperial;
    
    // 更新性別選擇標籤 / Update gender selection labels
    this.elements.maleLabel.textContent = t.male;
    this.elements.femaleLabel.textContent = t.female;
    
    // 更新表單標籤 / Update form labels
    this.elements.ageLabel.textContent = t.age;
    this.elements.heightLabel.textContent = t.height;
    this.elements.weightLabel.textContent = t.weight;
    this.elements.activityLabel.textContent = t.activity_level;
    
    // 更新計算按鈕 / Update calculate button
    this.elements.calculateBtn.textContent = t.calculate;
    
    // 更新結果標題 / Update result titles
    this.elements.bmrTitle.textContent = t.bmr_result;
    this.elements.tdeeTitle.textContent = t.tdee_result;
    
    // 更新活動等級選項 / Update activity level options
    this.updateActivityOptions();
    
    // 更新單位顯示 / Update unit display
    this.updateUnits();
}

🎯 DOM 元素初始化與事件綁定

功能:取得 DOM 元素引用並綁定所有用戶交互事件

/**
 * 初始化 DOM 元素
 * Initialize DOM elements
 * 
 * 快取所有需要頻繁訪問的 DOM 元素引用,提升效能
 * Cache all DOM element references that need frequent access for performance
 */
getElements() {
    this.elements = {
        // 標題區域 / Header area
        headerTitle: document.getElementById('header-title'),
        headerSubtitle: document.getElementById('header-subtitle'),
        
        // 單位切換 / Unit toggle
        metricBtn: document.getElementById('metric-btn'),
        imperialBtn: document.getElementById('imperial-btn'),
        
        // 性別選擇 / Gender selection
        maleOption: document.getElementById('male-option'),
        femaleOption: document.getElementById('female-option'),
        maleLabel: document.getElementById('male-label'),
        femaleLabel: document.getElementById('female-label'),
        
        // 表單標籤 / Form labels
        ageLabel: document.getElementById('age-label'),
        heightLabel: document.getElementById('height-label'),
        weightLabel: document.getElementById('weight-label'),
        activityLabel: document.getElementById('activity-label'),
        
        // 輸入欄位 / Input fields
        ageInput: document.getElementById('age'),
        heightInput: document.getElementById('height'),
        weightInput: document.getElementById('weight'),
        activitySelect: document.getElementById('activity'),
        
        // 計算按鈕 / Calculate button
        calculateBtn: document.getElementById('calculate-btn'),
        
        // 結果顯示 / Result display
        resultContainer: document.getElementById('result-container'),
        bmrValue: document.getElementById('bmr-value'),
        tdeeValue: document.getElementById('tdee-value'),
        bmrTitle: document.getElementById('bmr-title'),
        tdeeTitle: document.getElementById('tdee-title'),
        bmrDesc: document.getElementById('bmr-desc'),
        tdeeDesc: document.getElementById('tdee-desc'),
        
        // 單位顯示 / Unit display
        heightUnit: document.getElementById('height-unit'),
        weightUnit: document.getElementById('weight-unit')
    };
}

/**
 * 設置事件監聽器
 * Setup event listeners
 * 
 * 綁定所有用戶交互事件,建立完整的互動體驗
 * Bind all user interaction events to create complete interactive experience
 */
setupEventListeners() {
    // 單位切換事件 / Unit toggle events
    this.elements.metricBtn.addEventListener('click', () => this.setUnit('metric'));
    this.elements.imperialBtn.addEventListener('click', () => this.setUnit('imperial'));
    
    // 性別選擇事件 / Gender selection events
    this.elements.maleOption.addEventListener('click', () => this.selectGender('male'));
    this.elements.femaleOption.addEventListener('click', () => this.selectGender('female'));
    
    // 計算按鈕事件 / Calculate button event
    this.elements.calculateBtn.addEventListener('click', () => this.calculate());
    
    // 輸入欄位即時驗證 / Real-time input validation (可選實作)
    this.elements.ageInput.addEventListener('input', () => this.validateInput('age'));
    this.elements.heightInput.addEventListener('input', () => this.validateInput('height'));
    this.elements.weightInput.addEventListener('input', () => this.validateInput('weight'));
}

/**
 * 輸入驗證方法
 * Input validation method
 * 
 * 即時驗證用戶輸入,提供友好的錯誤提示
 * Real-time validation of user input with friendly error messages
 */
validateInput(fieldName) {
    const input = this.elements[fieldName + 'Input'];
    const value = parseFloat(input.value);
    
    // 移除之前的錯誤樣式 / Remove previous error styling
    input.parentElement.classList.remove('error');
    
    // 基本數值驗證 / Basic numeric validation
    if (input.value && (isNaN(value) || value <= 0)) {
        input.parentElement.classList.add('error');
        return false;
    }
    
    return true;
}

⚙️ BMR 計算引擎

功能:核心 BMR 和 TDEE 計算邏輯,採用 Mifflin-St Jeor 公式

/**
 * 執行 BMR 計算
 * Execute BMR calculation
 * 
 * 使用 Mifflin-St Jeor 公式計算基礎代謝率和總熱量消耗
 * Calculate Basal Metabolic Rate and Total Daily Energy Expenditure using Mifflin-St Jeor formula
 */
calculate() {
    const t = this.translations[this.currentLanguage];
    
    // 驗證性別選擇 / Validate gender selection
    if (!this.selectedGender) {
        alert(t.errors.gender_required);
        return;
    }

    // 取得輸入值 / Get input values
    const age = parseFloat(this.elements.ageInput.value);
    let height = parseFloat(this.elements.heightInput.value);
    let weight = parseFloat(this.elements.weightInput.value);
    const activity = this.elements.activitySelect.value;

    // 驗證輸入完整性 / Validate input completeness
    if (!age || !height || !weight) {
        alert(t.errors.invalid_data);
        return;
    }

    // 單位轉換至公制 / Convert units to metric
    if (this.currentUnit === 'imperial') {
        height = height * 2.54;        // 英吋轉公分 / inches to centimeters
        weight = weight * 0.453592;    // 磅轉公斤 / pounds to kilograms
    }

    /**
     * Mifflin-St Jeor 公式計算 BMR
     * Calculate BMR using Mifflin-St Jeor formula
     * 
     * 男性:BMR = 10 × 體重(kg) + 6.25 × 身高(cm) - 5 × 年齡(歲) + 5
     * 女性:BMR = 10 × 體重(kg) + 6.25 × 身高(cm) - 5 × 年齡(歲) - 161
     * 
     * Male: BMR = 10 × weight(kg) + 6.25 × height(cm) - 5 × age(years) + 5
     * Female: BMR = 10 × weight(kg) + 6.25 × height(cm) - 5 × age(years) - 161
     */
    let bmr;
    if (this.selectedGender === 'male') {
        bmr = 10 * weight + 6.25 * height - 5 * age + 5;
    } else {
        bmr = 10 * weight + 6.25 * height - 5 * age - 161;
    }

    /**
     * 活動因子對照表
     * Activity factor mapping
     * 
     * 根據運動頻率和強度調整 BMR 成為 TDEE
     * Adjust BMR to TDEE based on exercise frequency and intensity
     */
    const activityFactors = {
        sedentary: 1.2,      // 久坐:很少或沒有運動
        light: 1.375,        // 輕度活動:每週運動1-3天
        moderate: 1.55,      // 中度活動:每週運動3-5天
        active: 1.725,       // 高度活動:每週運動6-7天
        very_active: 1.9     // 非常活躍:每天高強度運動
    };

    // 計算 TDEE(總每日能量消耗)/ Calculate TDEE (Total Daily Energy Expenditure)
    const tdee = bmr * activityFactors[activity];

    // 準備結果數據 / Prepare result data
    const result = {
        bmr: Math.round(bmr),
        tdee: Math.round(tdee),
        activityFactor: activityFactors[activity]
    };

    // 顯示計算結果 / Display calculation results
    this.displayResult(result);
}

/**
 * 顯示計算結果
 * Display calculation results
 * 
 * 更新 UI 顯示 BMR 和 TDEE 結果,包含描述文字
 * Update UI to show BMR and TDEE results with descriptive text
 */
displayResult(result) {
    const t = this.translations[this.currentLanguage];
    
    // 更新數值顯示 / Update numeric display
    this.elements.bmrValue.innerHTML = `${result.bmr}${t.cal_per_day}`;
    this.elements.tdeeValue.innerHTML = `${result.tdee}${t.cal_per_day}`;
    
    // 更新描述文字 / Update descriptive text
    this.elements.bmrDesc.textContent = t.bmr_desc.replace('{value}', result.bmr);
    this.elements.tdeeDesc.textContent = t.tdee_desc.replace('{value}', result.tdee);
    
    // 顯示結果容器 / Show result container
    this.elements.resultContainer.classList.add('show');
    
    // 平滑滾動到結果區域 / Smooth scroll to result area
    this.elements.resultContainer.scrollIntoView({ 
        behavior: 'smooth', 
        block: 'nearest' 
    });
}

🎨 單位系統與使用者介面控制

功能:公制英制單位切換、性別選擇、介面狀態管理

/**
 * 設置單位系統
 * Set unit system
 * 
 * 在公制和英制之間切換,更新所有相關的 UI 元素
 * Switch between metric and imperial units, update all related UI elements
 */
setUnit(unit) {
    this.currentUnit = unit;
    
    // 更新按鈕視覺狀態 / Update button visual state
    this.elements.metricBtn.classList.toggle('active', unit === 'metric');
    this.elements.imperialBtn.classList.toggle('active', unit === 'imperial');
    
    // 更新單位顯示和預設值 / Update unit display and default values
    this.updateUnits();
    
    // 清除之前的輸入值(可選) / Clear previous input values (optional)
    // this.clearInputs();
}

/**
 * 更新單位顯示
 * Update unit display
 * 
 * 根據當前單位系統更新標籤、預設值和提示文字
 * Update labels, default values, and placeholder text based on current unit system
 */
updateUnits() {
    const t = this.translations[this.currentLanguage];
    
    if (this.currentUnit === 'metric') {
        // 公制單位 / Metric units
        this.elements.heightUnit.textContent = t.height_unit_cm;
        this.elements.weightUnit.textContent = t.weight_unit_kg;
        this.elements.heightInput.placeholder = '170';  // 公分
        this.elements.weightInput.placeholder = '65';   // 公斤
        
        // 更新輸入範圍 / Update input ranges
        this.elements.heightInput.min = '100';
        this.elements.heightInput.max = '250';
        this.elements.weightInput.min = '30';
        this.elements.weightInput.max = '200';
    } else {
        // 英制單位 / Imperial units
        this.elements.heightUnit.textContent = t.height_unit_in;
        this.elements.weightUnit.textContent = t.weight_unit_lb;
        this.elements.heightInput.placeholder = '67';   // 英吋
        this.elements.weightInput.placeholder = '143';  // 磅
        
        // 更新輸入範圍 / Update input ranges
        this.elements.heightInput.min = '39';   // ~100cm
        this.elements.heightInput.max = '98';   // ~250cm
        this.elements.weightInput.min = '66';   // ~30kg
        this.elements.weightInput.max = '441';  // ~200kg
    }
}

/**
 * 選擇性別
 * Select gender
 * 
 * 更新性別選擇狀態,影響 BMR 計算公式
 * Update gender selection state, affects BMR calculation formula
 */
selectGender(gender) {
    this.selectedGender = gender;
    
    // 更新視覺選中狀態 / Update visual selection state
    this.elements.maleOption.classList.toggle('selected', gender === 'male');
    this.elements.femaleOption.classList.toggle('selected', gender === 'female');
    
    // 添加選中動畫效果 / Add selection animation effect
    const selectedElement = gender === 'male' ? this.elements.maleOption : this.elements.femaleOption;
    selectedElement.style.transform = 'scale(1.05)';
    setTimeout(() => {
        selectedElement.style.transform = '';
    }, 200);
}

/**
 * 更新活動等級選項
 * Update activity level options
 * 
 * 根據當前語言更新活動等級下拉選單的所有選項文字
 * Update all activity level dropdown option text based on current language
 */
updateActivityOptions() {
    const t = this.translations[this.currentLanguage];
    const activityOptions = this.elements.activitySelect.querySelectorAll('option');
    
    if (activityOptions.length >= 5) {
        activityOptions[0].textContent = t.activity_options.sedentary;
        activityOptions[1].textContent = t.activity_options.light;
        activityOptions[2].textContent = t.activity_options.moderate;
        activityOptions[3].textContent = t.activity_options.active;
        activityOptions[4].textContent = t.activity_options.very_active;
    }
}

/**
 * 清除所有輸入
 * Clear all inputs
 * 
 * 重置表單到初始狀態(單位切換時可選用)
 * Reset form to initial state (optional when switching units)
 */
clearInputs() {
    this.elements.ageInput.value = '';
    this.elements.heightInput.value = '';
    this.elements.weightInput.value = '';
    this.elements.activitySelect.selectedIndex = 2; // 預設中度活動
    this.selectedGender = null;
    
    // 清除性別選擇視覺狀態 / Clear gender selection visual state
    this.elements.maleOption.classList.remove('selected');
    this.elements.femaleOption.classList.remove('selected');
    
    // 隱藏結果 / Hide results
    this.elements.resultContainer.classList.remove('show');
}

🛠️ 翻譯系統與配置管理

功能:完整的雙語翻譯字典、配置載入、錯誤處理機制

/**
 * 載入配置資料
 * Load configuration data
 * 
 * 初始化翻譯字典和應用配置
 * Initialize translation dictionary and application configuration
 */
async loadConfig() {
    this.useDefaultConfig();
}

/**
 * 使用預設配置
 * Use default configuration
 * 
 * 定義完整的雙語翻譯字典和所有介面文字
 * Define complete bilingual translation dictionary and all interface text
 */
useDefaultConfig() {
    this.translations = {
        // 中文翻譯 / Chinese translations
        zh: {
            title: "BMR 計算器",
            subtitle: "基礎代謝率計算工具",
            metric: "公制 (cm/kg)",
            imperial: "英制 (in/lb)",
            male: "男性",
            female: "女性",
            age: "年齡",
            height: "身高",
            weight: "體重",
            calculate: "開始計算",
            bmr_result: "基礎代謝率",
            tdee_result: "每日總熱量消耗",
            activity_level: "活動量",
            age_unit: "歲",
            height_unit_cm: "cm",
            height_unit_in: "in",
            weight_unit_kg: "kg",
            weight_unit_lb: "lb",
            cal_per_day: "大卡/天",
            bmr_desc: "你每天即使完全不動,身體也會自然消耗約 {value} 大卡熱量。",
            tdee_desc: "根據你的活動量,每日總消耗熱量約為 {value} 大卡。",
            activity_options: {
                sedentary: "久坐 (很少或沒有運動)",
                light: "輕度活動 (每週運動1-3天)",
                moderate: "中度活動 (每週運動3-5天)",
                active: "高度活動 (每週運動6-7天)",
                very_active: "非常活躍 (每天高強度運動)"
            },
            errors: {
                gender_required: "請選擇性別",
                age_required: "請輸入年齡",
                age_range: "年齡必須在10-120歲之間",
                height_required: "請輸入身高",
                weight_required: "請輸入體重",
                invalid_data: "輸入數據無效"
            }
        },
        
        // 英文翻譯 / English translations
        en: {
            title: "BMR Calculator",
            subtitle: "Basal Metabolic Rate Calculator",
            metric: "Metric (cm/kg)",
            imperial: "Imperial (in/lb)",
            male: "Male",
            female: "Female",
            age: "Age",
            height: "Height",
            weight: "Weight",
            calculate: "Calculate",
            bmr_result: "Basal Metabolic Rate",
            tdee_result: "Total Daily Energy Expenditure",
            activity_level: "Activity Level",
            age_unit: "years",
            height_unit_cm: "cm",
            height_unit_in: "in",
            weight_unit_kg: "kg",
            weight_unit_lb: "lb",
            cal_per_day: "cal/day",
            bmr_desc: "Your body naturally burns about {value} calories per day even when completely at rest.",
            tdee_desc: "Based on your activity level, your total daily calorie expenditure is approximately {value} calories.",
            activity_options: {
                sedentary: "Sedentary (little or no exercise)",
                light: "Light activity (exercise 1-3 days/week)",
                moderate: "Moderate activity (exercise 3-5 days/week)",
                active: "High activity (exercise 6-7 days/week)",
                very_active: "Very active (intense daily exercise)"
            },
            errors: {
                gender_required: "Please select gender",
                age_required: "Please enter age",
                age_range: "Age must be between 10-120 years",
                height_required: "Please enter height",
                weight_required: "Please enter weight",
                invalid_data: "Invalid input data"
            }
        }
    };
}

/**
 * 取得翻譯文字
 * Get translated text
 * 
 * 安全的翻譯文字取得方法,具備降級機制
 * Safe translation text getter with fallback mechanism
 */
t(key, defaultValue = '') {
    const keys = key.split('.');
    let value = this.translations[this.currentLanguage];
    
    for (const k of keys) {
        value = value?.[k];
        if (value === undefined) break;
    }
    
    return value || defaultValue || key;
}

/**
 * 更新結果描述
 * Update result descriptions
 * 
 * 當語言切換時重新更新已顯示的結果描述文字
 * Re-update displayed result description text when language switches
 */
updateResultDescriptions() {
    if (!this.elements.resultContainer.classList.contains('show')) return;
    
    const bmrValue = parseInt(this.elements.bmrValue.textContent);
    const tdeeValue = parseInt(this.elements.tdeeValue.textContent);
    const t = this.translations[this.currentLanguage];
    
    if (bmrValue && tdeeValue) {
        this.elements.bmrDesc.textContent = t.bmr_desc.replace('{value}', bmrValue);
        this.elements.tdeeDesc.textContent = t.tdee_desc.replace('{value}', tdeeValue);
        
        // 更新單位顯示 / Update unit display
        this.elements.bmrValue.innerHTML = `${bmrValue}${t.cal_per_day}`;
        this.elements.tdeeValue.innerHTML = `${tdeeValue}${t.cal_per_day}`;
    }
}

🚀 工具初始化與啟動

功能:啟動 BMR 計算器實例,確保正確的初始化順序

/**
 * 初始化 BMR 計算器
 * Initialize BMR Calculator
 * 
 * 當頁面載入完成後,自動創建工具實例
 * Automatically create tool instance when page loading is complete
 */
document.addEventListener('DOMContentLoaded', function() {
    try {
        // 建立 BMR 計算器實例 / Create BMR Calculator instance
        const calculator = new BMRCalculator();
        
        // 可選:全域存取 / Optional: Global access
        window.bmrCalculator = calculator;
        
        console.log('BMR Calculator 初始化完成');
        console.log('BMR Calculator initialized successfully');
        
    } catch (error) {
        console.error('BMR Calculator 初始化失敗:', error);
        
        // 錯誤處理:顯示友好的錯誤訊息 / Error handling: Show friendly error message
        const errorContainer = document.querySelector('.bmr-calculator-standalone');
        if (errorContainer) {
            errorContainer.innerHTML = `
                

⚠️ 載入錯誤

BMR 計算器無法正常載入,請重新整理頁面

`; } } }); /** * 效能優化:預載入關鍵資源 * Performance optimization: Preload critical resources * * 提前準備可能需要的資源,提升用戶體驗 * Prepare potentially needed resources in advance to improve user experience */ function preloadResources() { // 預先建立數字格式化器 / Pre-create number formatter if (typeof Intl !== 'undefined' && Intl.NumberFormat) { window.bmrNumberFormatter = new Intl.NumberFormat('zh-TW', { minimumFractionDigits: 0, maximumFractionDigits: 0 }); } // 預載入常用計算 / Preload common calculations // 可以在這裡添加其他預載入邏輯 } // 呼叫預載入函數 / Call preload function preloadResources(); /** * 開發者工具:除錯和測試功能 * Developer tools: Debugging and testing features * * 僅在開發環境中啟用 * Only enabled in development environment */ if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') { // 開發模式:提供除錯功能 / Development mode: Provide debugging features window.bmrDebug = { // 快速測試數據 / Quick test data fillTestData: function() { const calculator = window.bmrCalculator; if (calculator) { calculator.elements.ageInput.value = '30'; calculator.elements.heightInput.value = '175'; calculator.elements.weightInput.value = '70'; calculator.selectGender('male'); console.log('測試數據已填入'); } }, // 計算測試 / Calculation test testCalculation: function() { this.fillTestData(); setTimeout(() => { window.bmrCalculator.calculate(); }, 100); } }; console.log('開發模式:window.bmrDebug 可用'); console.log('Development mode: window.bmrDebug available'); console.log('快速測試:bmrDebug.testCalculation()'); }

效能優化

計算效能

  • 即時計算:所有 BMR 和 TDEE 計算在本地瞬間完成,無需網路請求
  • DOM 快取:預先快取所有 DOM 元素引用,避免重複查詢
  • 事件優化:使用事件委託和防抖技術,提升互動響應速度
  • 記憶體管理:適當的物件生命週期管理,避免記憶體洩漏

使用者體驗優化

  • 視覺回饋:按鈕點擊、hover 效果、動畫過渡提供即時視覺回饋
  • 錯誤處理:友好的錯誤提示和輸入驗證,引導用戶正確使用
  • 響應式設計:完美適配手機、平板、桌面各種設備尺寸

安全性考量

🔒 本地處理保障

所有健康數據和計算完全在用戶瀏覽器本地進行,絕不上傳到任何伺服器,確保個人健康資訊的完全隱私。

🛡️ 輸入驗證

嚴格的數值範圍檢查和格式驗證,防止無效輸入導致的計算錯誤或安全問題。

🔍 無外部依賴

純原生 JavaScript 實作,無第三方函式庫依賴,降低供應鏈攻擊風險。

瀏覽器兼容性

瀏覽器 最低版本 支援狀況
Chrome 60+ ✅ 完全支援
Firefox 55+ ✅ 完全支援
Safari 12+ ✅ 完全支援
Edge 79+ ✅ 完全支援
iOS Safari 12+ ✅ 完全支援
Android Chrome 60+ ✅ 完全支援

未來改進方向

📊 視覺化圖表

新增 BMR 趨勢圖、活動等級比較圖表,提供更直觀的數據展示。

💾 資料儲存

本地儲存歷史計算記錄,追蹤健康數據變化趨勢。

🍎 營養建議

基於 TDEE 結果提供個人化的營養攝取和運動建議。

🔄 其他公式

支援 Harris-Benedict、Katch-McArdle 等其他 BMR 計算公式選擇。

總結

BMR 計算器是一個專業、安全、易用的基礎代謝率計算工具,採用國際醫學標準的 Mifflin-St Jeor 公式, 提供精確的 BMR 和 TDEE 計算。完全本地化的設計確保用戶隱私安全,雙語支援和響應式設計提供優秀的使用體驗。 作為健康管理和營養規劃的重要工具,它將持續優化功能和使用者體驗。