4.4 progress, meter 与 output 元素

4.4 progress, meter与output元素

progress元素:进度指示器

<progress>元素用于显示任务完成进度,适合表示需要较长时间操作的完成情况。

基础用法

<label for="file-upload">文件上传进度:</label>
<progress id="file-upload" value="35" max="100">35%</progress>

核心属性

  • value:当前进度值(必须≥0且≤max)
  • max:总进度值(默认为1)
  • value时表示不确定进度(如<progress></progress>

动态控制示例

// 模拟文件上传
const progressBar = document.getElementById('upload-progress');
let progress = 0;

const uploadInterval = setInterval(() => {
  progress += Math.random() * 10;
  progressBar.value = Math.min(progress, 100);
  
  if(progress >= 100) {
    clearInterval(uploadInterval);
    progressBar.textContent = '上传完成!';
  }
}, 500);

样式定制技巧

/* 整体样式 */
progress {
  width: 100%;
  height: 20px;
  border-radius: 10px;
}

/* WebKit浏览器样式 */
progress::-webkit-progress-bar {
  background-color: #f0f0f0;
  border-radius: 10px;
}

progress::-webkit-progress-value {
  background: linear-gradient(to right, #4CAF50, #8BC34A);
  border-radius: 10px;
}

/* Firefox样式 */
progress::-moz-progress-bar {
  background: linear-gradient(to right, #4CAF50, #8BC34A);
}

meter元素:度量衡指示器

<meter>元素表示已知范围内的标量测量值或分数值(如磁盘用量、投票结果等)。

基础用法

<label for="disk-usage">磁盘使用量:</label>
<meter id="disk-usage" 
       value="75" 
       min="0" 
       max="100"
       low="20" 
       high="80" 
       optimum="50">
  75GB/100GB
</meter>

属性详解

属性 描述 默认值
value 当前值(必需) -
min 最小值 0
max 最大值 1
low 界定"低"范围的阈值 min值
high 界定"高"范围的阈值 max值
optimum 最佳值(影响颜色指示) (min+max)/2

状态可视化

  • 最佳区间(绿色):value接近optimum
  • 可接受区间(黄色):valuelowhigh之间
  • 警告区间(红色):value超出low/high

动态数据绑定

<div class="poll-results">
  <p>投票结果:</p>
  <meter id="poll-meter" 
         min="0" 
         max="1000"
         value="650"></meter>
  <output id="poll-output" for="poll-meter">650</output>/1000
</div>

<script>
  // 实时更新投票数据
  const pollMeter = document.getElementById('poll-meter');
  const pollOutput = document.getElementById('poll-output');
  
  setInterval(() => {
    fetch('/api/poll-results')
      .then(res => res.json())
      .then(data => {
        pollMeter.value = data.votes;
        pollOutput.value = data.votes;
      });
  }, 5000);
</script>

output元素:计算结果输出

<output>元素表示计算或用户操作的结果,常与表单元素联动。

基础用法

<form oninput="result.value = parseInt(a.value) + parseInt(b.value)">
  <input type="range" id="a" value="50" min="0" max="100"> +
  <input type="number" id="b" value="25"> =
  <output name="result" for="a b">75</output>
</form>

关键特性

  • for属性关联输入元素的id(空格分隔多个id)
  • 支持name属性,可随表单一起提交
  • 默认display: inline

高级应用示例

<div class="price-calculator">
  <label for="quantity">数量:</label>
  <input type="number" id="quantity" min="1" value="1">
  
  <label for="price">单价:</label>
  <input type="number" id="price" min="0" step="0.01" value="99.99">
  
  <label>总价:</label>
  <output id="total" for="quantity price"></output>
  
  <label for="discount">折扣码:</label>
  <input type="text" id="discount">
</div>

<script>
  const inputs = document.querySelectorAll('#quantity, #price, #discount');
  const output = document.getElementById('total');
  
  function calculateTotal() {
    const quantity = parseInt(document.getElementById('quantity').value) || 0;
    const price = parseFloat(document.getElementById('price').value) || 0;
    const discount = getDiscount(); // 自定义折扣计算
    
    output.value = (quantity * price * discount).toFixed(2);
  }
  
  inputs.forEach(input => input.addEventListener('input', calculateTotal));
</script>

三元素对比指南

特性 <progress> <meter> <output>
用途 任务完成进度 已知范围内的测量值 计算结果显示
值范围 0-max min-max 无限制
动态更新 常见 常见 必需
交互性 只读 只读 只读
视觉状态 单一颜色进度条 颜色反映value与optimum关系 纯文本
关联元素 通常独立使用 通常独立使用 常与表单元素关联

无障碍访问实践

1. 屏幕阅读器优化

<label for="loading-progress">正在加载:</label>
<progress id="loading-progress" 
          value="45" 
          max="100"
          aria-valuetext="45 percent">
  45%
</progress>

<div role="status" aria-live="polite">
  当前进度:<span id="progress-announce">45</span>%
</div>

<script>
  // 动态更新进度播报
  const progress = document.getElementById('loading-progress');
  const announce = document.getElementById('progress-announce');
  
  progress.addEventListener('input', () => {
    announce.textContent = progress.value;
  });
</script>

2. 高对比度模式支持

@media (forced-colors: active) {
  progress, meter {
    border: 1px solid CanvasText;
  }
  
  progress::-webkit-progress-value,
  meter::-webkit-meter-optimum-value {
    forced-color-adjust: none;
    background: Highlight;
  }
}

实际应用案例

1. 文件上传面板

<div class="upload-panel">
  <h3>上传文件</h3>
  <input type="file" id="file-input">
  
  <div class="upload-status" hidden>
    <label>进度:</label>
    <progress id="upload-progress" max="100"></progress>
    <output id="upload-speed"></output>
  </div>
</div>

<script>
  document.getElementById('file-input').addEventListener('change', (e) => {
    const file = e.target.files[0];
    if(!file) return;
    
    const statusPanel = document.querySelector('.upload-status');
    const progressBar = document.getElementById('upload-progress');
    const speedOutput = document.getElementById('upload-speed');
    
    statusPanel.hidden = false;
    
    // 模拟上传过程
    let uploaded = 0;
    const totalSize = file.size;
    const startTime = Date.now();
    
    const uploadInterval = setInterval(() => {
      uploaded += Math.min(1024 * 1024, totalSize - uploaded);
      const percent = (uploaded / totalSize * 100).toFixed(1);
      
      // 更新进度
      progressBar.value = percent;
      
      // 计算并显示速度
      const timeElapsed = (Date.now() - startTime) / 1000;
      const speed = (uploaded / timeElapsed / 1024).toFixed(1);
      speedOutput.value = `${speed} KB/s`;
      
      if(uploaded >= totalSize) {
        clearInterval(uploadInterval);
        speedOutput.value += ' - 上传完成';
      }
    }, 100);
  });
</script>

2. 系统监控仪表盘

<div class="system-monitor">
  <h3>系统资源监控</h3>
  
  <div class="metric">
    <label>CPU使用率:</label>
    <meter id="cpu-usage" 
           high="80" 
           optimum="30"
           min="0" 
           max="100"></meter>
    <output id="cpu-value" for="cpu-usage"></output>
  </div>
  
  <div class="metric">
    <label>内存占用:</label>
    <meter id="memory-usage" 
           high="85" 
           optimum="40"
           min="0" 
           max="100"></meter>
    <output id="memory-value" for="memory-usage"></output>
  </div>
</div>

<script>
  // 实时获取系统数据
  function updateSystemMetrics() {
    fetch('/api/system-metrics')
      .then(res => res.json())
      .then(data => {
        document.getElementById('cpu-usage').value = data.cpu;
        document.getElementById('cpu-value').value = `${data.cpu}%`;
        
        document.getElementById('memory-usage').value = data.memory;
        document.getElementById('memory-value').value = `${data.memory}%`;
      });
  }
  
  setInterval(updateSystemMetrics, 2000);
</script>

兼容性处理方案

1. 特性检测与Polyfill

// 检测progress/meter支持
if(!('value' in document.createElement('progress')) || 
   !('value' in document.createElement('meter'))) {
   
  // 加载polyfill
  const script = document.createElement('script');
  script.src = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/meter-polyfill.min.js';
  document.head.appendChild(script);
}

2. 优雅降级方案

<progress id="js-progress" value="35" max="100">35%</progress>
<noscript>
  <div class="progress-fallback">
    <div class="progress-bar" style="width:35%"></div>
  </div>
  <span>35%</span>
</noscript>

<style>
  .progress-fallback {
    display: inline-block;
    width: 200px;
    background: #eee;
  }
  
  .progress-bar {
    height: 20px;
    background: #4CAF50;
  }
</style>

<script>
  // 隐藏原生元素如果不支持
  if(!('value' in document.createElement('progress'))) {
    document.getElementById('js-progress').style.display = 'none';
  }
</script>

通过合理运用progressmeteroutput元素,开发者可以创建直观的数据可视化界面,这些语义化元素不仅能提升用户体验,还能为辅助技术提供明确的结构信息。结合现代CSS和JavaScript,这些元素能够适应各种复杂的应用场景。

#前端开发 分享于 2025-04-01

【 内容由 AI 共享,不代表本站观点,请谨慎参考 】