You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:如何实现JavaScript基础补水计算器的函数图表展示?

解决补水计算器图表无法正常展示的问题

问题诊断

当前代码存在以下核心问题导致图表无法正常渲染:

  • 未实现calcularFuncion函数:代码中调用了该函数但未定义,导致图表无数据来源
  • 图表数据维度不匹配:仅使用固定的4个x轴标签,无法完整展示分段函数的趋势(尤其是30kg以上趋近333.33cc/hr的部分)
  • 重复创建Chart实例:每次点击按钮都会生成新的Chart实例,导致画布冲突
  • 按钮无操作文本:HTML按钮缺少显示文本,影响用户操作体验

修正后的完整代码

HTML部分

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Calculadora de hidratación</title>
    <link rel="stylesheet" href="./style.css" />
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <!-- 引入注释插件支持渐近线标注 -->
    <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation@2.2.0/dist/chartjs-plugin-annotation.min.js"></script>
  </head>
  <body>
    <div>
      <div id="calculadora">
        <h2>Hidratación Basal</h2>
        <input type="number" id="peso" placeholder="Indicar peso en kilogramos" />
        <button onclick="handleSubmit()">Calcular y Mostrar Gráfica</button>
      </div>
      <div>
        <p>
          <output id="Resultado"></output>
        </p>
      </div>
      <div id="descripcion">
        <h3>¿Cómo se calcula?</h3>
        <ul>
          <li>De 0kg a 10kg, se calcula 100cc por cada kilo.</li>
          <li>Se suman 50cc por cada kilo de peso por arriba de 10kg, hasta 20kg</li>
          <li>De 20kg y hasta 30kg, se suman 20cc por cada kilo adicional</li>
          <li>De 30kg para arriba, se determina mediante la superficie corporal del paciente </li>
        </ul>
      </div>
    </div>
    <div>
      <canvas id="grafica" width="400" height="200"></canvas>
    </div>
    <script src="./index-calculadoralucas.js"></script>
  </body>
</html>

JavaScript部分

// 全局存储Chart实例,用于销毁旧实例避免冲突
let myChart = null;

// 核心计算函数,提取为独立方法复用
function calcularPeso(peso) {
    if (isNaN(peso) || peso < 0) {
        return "Ingrese un número válido";
    }
    let ccPorHora;
    if (peso <= 10) {
        ccPorHora = (peso * 100) / 16;
    } else if (peso <= 20) {
        ccPorHora = (((peso - 10) * 50) + 1500) / 16;
    } else if (peso <= 30) {
        ccPorHora = (((peso - 20) * 20) + 1500) / 16;
    } else {
        ccPorHora = ((((peso * 4 + 7) / (peso + 90)) * 2000) / 24).toFixed(2);
    }
    return `La cantidad necesaria es: ${ccPorHora}cc/hr`;
}

// 实现缺失的calcularFuncion,生成连续数据点
function calcularFuncion(maxPeso) {
    const data = [];
    const step = 1; // 步长设为1保证曲线平滑
    // 生成0到输入体重的连续数据
    for (let x = 0; x <= maxPeso; x += step) {
        let y;
        if (x <= 10) {
            y = (x * 100) / 16;
        } else if (x <= 20) {
            y = (((x - 10) * 50) + 1500) / 16;
        } else if (x <= 30) {
            y = (((x - 20) * 20) + 1500) / 16;
        } else {
            y = ((((x * 4 + 7) / (x + 90)) * 2000) / 24);
        }
        data.push(y);
    }
    // 体重超过30kg时,额外添加更远的点展示渐近趋势
    if (maxPeso > 30) {
        const x = maxPeso + 50;
        const y = ((((x * 4 + 7) / (x + 90)) * 2000) / 24);
        data.push(y);
    }
    return data;
}

// 图表渲染函数
function mostrarGrafica(peso) {
    const ctx = document.getElementById('grafica').getContext('2d');
    
    // 销毁旧实例避免画布冲突
    if (myChart) {
        myChart.destroy();
    }

    // 生成对应x轴标签数组
    const labels = [];
    const step = 1;
    for (let x = 0; x <= peso; x += step) {
        labels.push(x);
    }
    if (peso > 30) {
        labels.push(peso + 50);
    }

    myChart = new Chart(ctx, {
        type: 'line',
        data: {
            labels: labels,
            datasets: [{
                label: 'Función de cálculo de hidratación',
                data: calcularFuncion(peso),
                borderColor: '#e50914',
                borderWidth: 2,
                fill: false,
                tension: 0.1 // 让折线更平滑
            }]
        },
        options: {
            scales: {
                x: {
                    title: {
                        display: true,
                        text: 'Peso (kg)'
                    }
                },
                y: {
                    min: 0,
                    title: {
                        display: true,
                        text: 'CC/Hora'
                    }
                }
            },
            plugins: {
                annotation: {
                    annotations: {
                        asymptoticLine: {
                            type: 'line',
                            yMin: 333.33,
                            yMax: 333.33,
                            borderColor: 'rgba(0,0,0,0.3)',
                            borderWidth: 2,
                            borderDash: [5,5],
                            label: {
                                content: 'Límite asintótico (333.33cc/hr)',
                                enabled: true,
                                position: 'end'
                            }
                        }
                    }
                }
            }
        }
    });
}

// 统一处理提交事件
function handleSubmit() {
    const peso = parseInt(document.getElementById("peso").value);
    const resultado = document.getElementById("Resultado");
    resultado.innerHTML = calcularPeso(peso);
    
    // 仅当输入有效时渲染图表
    if (!isNaN(peso) && peso >= 0) {
        mostrarGrafica(peso);
    }
}

关键优化说明

  1. 实现calcularFuncion函数:生成从0到输入体重的连续数据点,30kg以上额外添加更远的点,直观展示趋近333.33cc/hr的渐近趋势
  2. 管理Chart实例:全局存储实例对象,每次渲染前销毁旧实例,避免画布冲突
  3. 统一事件处理:将计算和渲染逻辑合并到handleSubmit,增加输入合法性校验
  4. 增强图表可读性:添加坐标轴标题、333.33cc/hr的虚线参考线及标注,清晰展示函数趋势
  5. 修复UI细节:给按钮添加明确操作文本,提升用户体验

内容的提问来源于stack exchange,提问作者Lucas Sitzmann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 20:57:01