科学计算工具

科学计算工具

    <div class="cards-container" id="cards-container">
        <!-- 卡片将通过JavaScript动态生成 -->
    </div>
</div>

<!-- 模态框将通过JavaScript动态生成 -->
<div id="modals-container"></div>

<script>
    // 公式配置数据
    const formulasConfig = {
        "kinetic-energy": {
            title: "动能计算",
            description: "计算物体的动能,基于质量和速度",
            formula: "E_k = \\frac{1}{2}mv^2",
            variables: [
                { name: "E_k", description: "动能 (J)", isResult: true },
                { name: "m", description: "质量 (kg)", className: "mass", placeholder: "输入质量" },
                { name: "v", description: "速度 (m/s)", className: "velocity", placeholder: "输入速度" }
            ],
            calculation: function (row) {
                const mass = parseFloat(row.querySelector('.mass').value) || 0;
                const velocity = parseFloat(row.querySelector('.velocity').value) || 0;
                return 0.5 * mass * Math.pow(velocity, 2);
            }
        },
        "gravitational-force": {
            title: "万有引力",
            description: "计算两个物体之间的万有引力",
            formula: "F = G\\frac{m_1m_2}{r^2}",
            constants: [
                { name: "G", value: "6.674 \\times 10^{-11} N \\cdot m^2/kg^2", description: "万有引力常数" }
            ],
            variables: [
                { name: "F", description: "引力 (N)", isResult: true },
                { name: "m_1", description: "质量1 (kg)", className: "mass1", placeholder: "输入质量1" },
                { name: "m_2", description: "质量2 (kg)", className: "mass2", placeholder: "输入质量2" },
                { name: "r", description: "距离 (m)", className: "distance", placeholder: "输入距离" }
            ],
            calculation: function (row) {
                const mass1 = parseFloat(row.querySelector('.mass1').value) || 0;
                const mass2 = parseFloat(row.querySelector('.mass2').value) || 0;
                const distance = parseFloat(row.querySelector('.distance').value) || 0;

                const G = 6.67430e-11; // 万有引力常数
                let force = 0;

                if (distance !== 0) {
                    force = G * mass1 * mass2 / Math.pow(distance, 2);
                }

                return force;
            },
            formatResult: function (result) {
                return result.toExponential(4);
            }
        },
        "ohms-law": {
            title: "欧姆定律",
            description: "计算电压、电流或电阻",
            formula: "V = IR",
            variables: [
                { name: "V", description: "电压 (V)", className: "voltage", placeholder: "输入电压" },
                { name: "I", description: "电流 (A)", className: "current", placeholder: "输入电流" },
                { name: "R", description: "电阻 (Ω)", className: "resistance", placeholder: "输入电阻" }
            ],
            calculation: function (row, changedField) {
                const voltage = parseFloat(row.querySelector('.voltage').value);
                const current = parseFloat(row.querySelector('.current').value);
                const resistance = parseFloat(row.querySelector('.resistance').value);

                let results = {};

                // 根据已知的两个值计算第三个值
                if (changedField === 'voltage') {
                    if (current !== 0 && !isNaN(current)) {
                        results.resistance = voltage / current;
                    }
                    if (resistance !== 0 && !isNaN(resistance)) {
                        results.current = voltage / resistance;
                    }
                } else if (changedField === 'current') {
                    if (voltage !== 0 && !isNaN(voltage)) {
                        results.resistance = voltage / current;
                    }
                    if (resistance !== 0 && !isNaN(resistance)) {
                        results.voltage = current * resistance;
                    }
                } else if (changedField === 'resistance') {
                    if (voltage !== 0 && !isNaN(voltage)) {
                        results.current = voltage / resistance;
                    }
                    if (current !== 0 && !isNaN(current)) {
                        results.voltage = current * resistance;
                    }
                }

                return results;
            },
            formatResult: function (result) {
                return result.toFixed(4);
            },
            isInteractive: true
        },
        "pythagorean-theorem": {
            title: "勾股定理",
            description: "计算直角三角形的边长",
            formula: "c = \\sqrt{a^2 + b^2}",
            variables: [
                { name: "a", description: "直角边a", className: "side-a", placeholder: "输入边a" },
                { name: "b", description: "直角边b", className: "side-b", placeholder: "输入边b" },
                { name: "c", description: "斜边c", className: "side-c", placeholder: "输入边c" }
            ],
            calculation: function (row, changedSide) {
                const sideA = parseFloat(row.querySelector('.side-a').value);
                const sideB = parseFloat(row.querySelector('.side-b').value);
                const sideC = parseFloat(row.querySelector('.side-c').value);

                let results = {};

                // 根据已知的两个边计算第三个边
                if (changedSide === 'a') {
                    if (!isNaN(sideB) && !isNaN(sideC)) {
                        results.a = Math.sqrt(Math.pow(sideC, 2) - Math.pow(sideB, 2));
                    } else if (!isNaN(sideA) && !isNaN(sideB)) {
                        results.c = Math.sqrt(Math.pow(sideA, 2) + Math.pow(sideB, 2));
                    } else if (!isNaN(sideA) && !isNaN(sideC)) {
                        results.b = Math.sqrt(Math.pow(sideC, 2) - Math.pow(sideA, 2));
                    }
                } else if (changedSide === 'b') {
                    if (!isNaN(sideA) && !isNaN(sideC)) {
                        results.b = Math.sqrt(Math.pow(sideC, 2) - Math.pow(sideA, 2));
                    } else if (!isNaN(sideA) && !isNaN(sideB)) {
                        results.c = Math.sqrt(Math.pow(sideA, 2) + Math.pow(sideB, 2));
                    } else if (!isNaN(sideB) && !isNaN(sideC)) {
                        results.a = Math.sqrt(Math.pow(sideC, 2) - Math.pow(sideB, 2));
                    }
                } else if (changedSide === 'c') {
                    if (!isNaN(sideA) && !isNaN(sideB)) {
                        results.c = Math.sqrt(Math.pow(sideA, 2) + Math.pow(sideB, 2));
                    } else if (!isNaN(sideA) && !isNaN(sideC)) {
                        results.b = Math.sqrt(Math.pow(sideC, 2) - Math.pow(sideA, 2));
                    } else if (!isNaN(sideB) && !isNaN(sideC)) {
                        results.a = Math.sqrt(Math.pow(sideC, 2) - Math.pow(sideB, 2));
                    }
                }

                return results;
            },
            formatResult: function (result) {
                return result.toFixed(4);
            },
            isInteractive: true
        },
        "ratio-calculation": {
            title: "扭度计算公式",
            description: "计算扭度",
            formula: "X = \\frac{2(AC-BD)}{(AC+BD)} \\times 100\\%",
            variables: [
                { name: "X", description: "百分比比率 (%)", isResult: true },
                { name: "AC", description: "AC值", className: "ac-value", placeholder: "输入AC值" },
                { name: "BD", description: "BD值", className: "bd-value", placeholder: "输入BD值" }
            ],
            calculation: function (row) {
                const ac = parseFloat(row.querySelector('.ac-value').value) || 0;
                const bd = parseFloat(row.querySelector('.bd-value').value) || 0;

                let ratio = 0;

                if ((ac + bd) !== 0) {
                    ratio = (2 * (ac - bd)) / (ac + bd) * 100;
                }

                return ratio;
            },
            formatResult: function (result) {
                return result.toFixed(2) + "%";
            }
        }
    };

    // 初始化应用
    document.addEventListener('DOMContentLoaded', function () {
        // 生成卡片
        const cardsContainer = document.getElementById('cards-container');
        const modalsContainer = document.getElementById('modals-container');

        for (const [id, config] of Object.entries(formulasConfig)) {
            // 创建卡片
            const card = document.createElement('div');
            card.className = 'card';
            card.setAttribute('onclick', `openModal('${id}-modal')`);

            const title = document.createElement('h3');
            title.textContent = config.title;

            const description = document.createElement('p');
            description.textContent = config.description;

            card.appendChild(title);
            card.appendChild(description);
            cardsContainer.appendChild(card);

            // 创建模态框
            const modal = document.createElement('div');
            modal.id = `${id}-modal`;
            modal.className = 'modal';

            const modalContent = document.createElement('div');
            modalContent.className = 'modal-content';

            // 模态框头部
            const modalHeader = document.createElement('div');
            modalHeader.className = 'modal-header';

            const modalTitle = document.createElement('h2');
            modalTitle.textContent = config.title;

            const closeBtn = document.createElement('button');
            closeBtn.className = 'close-btn';
            closeBtn.innerHTML = '&times;';
            closeBtn.setAttribute('onclick', `closeModal('${id}-modal')`);

            modalHeader.appendChild(modalTitle);
            modalHeader.appendChild(closeBtn);

            // 模态框主体
            const modalBody = document.createElement('div');
            modalBody.className = 'modal-body';

            // 公式容器
            const formulaContainer = document.createElement('div');
            formulaContainer.className = 'formula-container';

            const formulaTitle = document.createElement('p');
            formulaTitle.textContent = `${config.title}公式:`;

            const formula = document.createElement('p');
            formula.innerHTML = `\\[ ${config.formula} \\]`;

            const variablesTitle = document.createElement('p');
            variablesTitle.textContent = "其中:";

            formulaContainer.appendChild(formulaTitle);
            formulaContainer.appendChild(formula);
            formulaContainer.appendChild(variablesTitle);

            // 添加常量说明
            if (config.constants) {
                config.constants.forEach(constant => {
                    const constantP = document.createElement('p');
                    constantP.innerHTML = `\\( ${constant.name} \\) = ${constant.value} (${constant.description})`;
                    formulaContainer.appendChild(constantP);
                });
            }

            // 添加变量说明
            config.variables.forEach(variable => {
                if (!variable.isResult) {
                    const variableP = document.createElement('p');
                    variableP.innerHTML = `\\( ${variable.name} \\) = ${variable.description}`;
                    formulaContainer.appendChild(variableP);
                }
            });

            // 变量输入容器
            const variablesContainer = document.createElement('div');
            variablesContainer.className = 'variables-container';

            const inputTitle = document.createElement('h3');
            inputTitle.textContent = '输入数据';

            variablesContainer.appendChild(inputTitle);

            // 创建输入表格
            const table = document.createElement('table');
            table.className = 'input-table';
            table.id = `${id}-table`;

            const thead = document.createElement('thead');
            const headerRow = document.createElement('tr');

            // 添加表头
            config.variables.forEach(variable => {
                const th = document.createElement('th');
                th.textContent = variable.description.split(')')[0] + ')';
                headerRow.appendChild(th);
            });

            thead.appendChild(headerRow);
            table.appendChild(thead);

            const tbody = document.createElement('tbody');

            // 添加输入行
            const inputRow = document.createElement('tr');

            config.variables.forEach(variable => {
                const td = document.createElement('td');

                if (variable.isResult) {
                    td.className = 'result-cell';
                    td.textContent = '0';
                } else {
                    const input = document.createElement('input');
                    input.type = 'number';
                    input.className = variable.className;
                    input.placeholder = variable.placeholder;

                    if (config.isInteractive) {
                        // 交互式公式(如欧姆定律、勾股定理)
                        input.oninput = function () {
                            const changedField = variable.className.split('-')[config.id === 'pythagorean-theorem' ? 1 : 0];
                            const results = config.calculation(this.closest('tr'), changedField);

                            for (const [field, value] of Object.entries(results)) {
                                const inputField = this.closest('tr').querySelector(`.${config.id === 'pythagorean-theorem' ? 'side-' + field : field}`);
                                if (inputField && !inputField.isSameNode(this)) {
                                    inputField.value = config.formatResult(value);
                                }
                            }
                        };
                    } else {
                        // 普通公式
                        input.oninput = function () {
                            const result = config.calculation(this.closest('tr'));
                            const resultCell = this.closest('tr').querySelector('.result-cell');
                            if (resultCell) {
                                resultCell.textContent = config.formatResult
                                    ? config.formatResult(result)
                                    : result.toFixed(4);
                            }
                        };
                    }

                    td.appendChild(input);
                }

                inputRow.appendChild(td);
            });

            tbody.appendChild(inputRow);
            table.appendChild(tbody);

            variablesContainer.appendChild(table);

            // 添加行按钮(非交互式公式才有)
            if (!config.isInteractive) {
                const addRowBtn = document.createElement('button');
                addRowBtn.className = 'btn add-row-btn';
                addRowBtn.textContent = '添加行';
                addRowBtn.onclick = function () {
                    addRow(id, `${id}-table`, config);
                };
                variablesContainer.appendChild(addRowBtn);
            } else {
                // 添加提示文本
                const hint = document.createElement('p');
                hint.style.marginTop = '10px';
                hint.style.color = '#666';
                hint.style.fontSize = '14px';
                hint.textContent = '提示: 输入任意两个值计算第三个值';
                variablesContainer.appendChild(hint);
            }

            // 操作按钮
            const actionButtons = document.createElement('div');
            actionButtons.className = 'action-buttons';

            const clearBtn = document.createElement('button');
            clearBtn.className = 'btn';
            clearBtn.textContent = '清空';
            clearBtn.onclick = function () {
                clearTable(`${id}-table`);
            };

            const closeModalBtn = document.createElement('button');
            closeModalBtn.className = 'btn';
            closeModalBtn.textContent = '关闭';
            closeModalBtn.onclick = function () {
                closeModal(`${id}-modal`);
            };

            actionButtons.appendChild(clearBtn);
            actionButtons.appendChild(closeModalBtn);
            variablesContainer.appendChild(actionButtons);

            // 组装模态框
            modalBody.appendChild(formulaContainer);
            modalBody.appendChild(variablesContainer);

            modalContent.appendChild(modalHeader);
            modalContent.appendChild(modalBody);

            modal.appendChild(modalContent);
            modalsContainer.appendChild(modal);
        }

        // 重新渲染MathJax公式
        if (MathJax.typeset) {
            MathJax.typeset();
        }
    });

    // 打开模态框
    function openModal(modalId) {
        document.getElementById(modalId).style.display = 'flex';
        // 重新渲染MathJax公式,确保显示正确
        if (MathJax.typeset) {
            MathJax.typeset();
        }
    }

    // 关闭模态框
    function closeModal(modalId) {
        document.getElementById(modalId).style.display = 'none';
    }

    // 添加行
    function addRow(formulaId, tableId, config) {
        const table = document.getElementById(tableId);
        const tbody = table.querySelector('tbody');
        const newRow = tbody.insertRow();

        config.variables.forEach(variable => {
            const td = document.createElement('td');

            if (variable.isResult) {
                td.className = 'result-cell';
                td.textContent = '0';
            } else {
                const input = document.createElement('input');
                input.type = 'number';
                input.className = variable.className;
                input.placeholder = variable.placeholder;

                if (config.isInteractive) {
                    const changedField = variable.className.split('-')[formulaId === 'pythagorean-theorem' ? 1 : 0];
                    input.oninput = function () {
                        const results = config.calculation(this.closest('tr'), changedField);

                        for (const [field, value] of Object.entries(results)) {
                            const inputField = this.closest('tr').querySelector(`.${formulaId === 'pythagorean-theorem' ? 'side-' + field : field}`);
                            if (inputField && !inputField.isSameNode(this)) {
                                inputField.value = config.formatResult(value);
                            }
                        }
                    };
                } else {
                    input.oninput = function () {
                        const result = config.calculation(this.closest('tr'));
                        const resultCell = this.closest('tr').querySelector('.result-cell');
                        if (resultCell) {
                            resultCell.textContent = config.formatResult
                                ? config.formatResult(result)
                                : result.toFixed(4);
                        }
                    };
                }

                td.appendChild(input);
            }

            newRow.appendChild(td);
        });
    }

    // 清空表格
    function clearTable(tableId) {
        const table = document.getElementById(tableId);
        const tbody = table.querySelector('tbody');
        
        // 保留第一行,清空其输入
        const firstRow = tbody.rows[0];
        for (let i = 0; i < firstRow.cells.length; i++) {
            const input = firstRow.cells[i].querySelector('input');
            if (input) {
                input.value = '';
            } else {
                firstRow.cells[i].textContent = '0';
            }
        }

        // 删除其他行
        while (tbody.rows.length > 1) {
            tbody.deleteRow(1);
        }
    }
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值