不常见但有用且高效的 html5 标签<Progress>进度条标签 制作一个球体水波纹进度条

54 阅读2分钟

Progress

从其名字上就知道<progress>元素就是作为进度条展示。在不指定 value 的情况下,它将来回播放展示:

<progress></progress>

同样的,也可以为其指定 value 和最大值(max)

<progress value="70" max="100"></progress>

通过伪元素给<progress>添加一个进度条滑块

  progress::after {
    width: 10px;
    height: 20px;
    border-radius: 5px;
    content: '';
    background-color: #61c554;
    position: absolute;
    top: 50%;
    translate: -50% -50%;
    left: calc(var(--progress) * 1%);
  }

监听<progress>标签的鼠标事件

const progressBox = document.querySelector('#progress')
progressBox.addEventListener('mousemove', handleMouseMove)
progressBox.addEventListener('mouseup', handleMouseUp)
progressBox.addEventListener('mousedown', handleMouseDown)
progressBox.addEventListener('mouseout', handleMouseseout)

之后设置css变量去控制伪元素滑块的left值达到滑动效果, 同理球体盒子添加伪元素让它旋转,变量去控制伪元素的top值达到上移动效果 js代码

      const progressBox = document.querySelector('#progress')
      const textBox = document.querySelector('#text')
      const progress = document.getElementById('progress')
      const text = document.getElementById('text')
      const borderBox = document.querySelector('.border')
      function setProgressValue(v) {
        progress.value = v
        text.innerText = v
        borderBox.style.setProperty(
          '--boder',
          120 - Math.floor(120 * (v / 100))
        )
        progress.style.setProperty('--progress', v)
      }

      let dragging = false
      function handleMouseDown() {
        dragging = true
      }
      function handleMouseUp() {
        dragging = false
      }
      function handleMouseMove(e) {
        if (dragging) {
          const { width, left } = progress.getBoundingClientRect()
          const mouseX = e.clientX
          const percent = (mouseX - left) / width
          let value = Math.round(percent * 100)
          if (value > 100) value = 100
          if (value < 0) value = 0
          setProgressValue(value)
        }
      }
      function handleMouseseout(e) {
        dragging = false
      }
      progressBox.addEventListener('mousemove', handleMouseMove)
      progressBox.addEventListener('mouseup', handleMouseUp)
      progressBox.addEventListener('mousedown', handleMouseDown)
      progressBox.addEventListener('mouseout', handleMouseseout)

css代码

:root {
        --progress: 0;
        --boder: 120;
      }
      progress {
        cursor: grabbing;
        width: 200px;
        position: relative;
      }
      progress::after {
        width: 10px;
        height: 20px;
        border-radius: 5px;
        content: '';
        background-color: #61c554;
        position: absolute;
        top: 50%;
        translate: -50% -50%;
        left: calc(var(--progress) * 1%);
      }
      @keyframes move {
        0% {
          transform: rotate(0deg);
        }
        100% {
          transform: rotate(360deg);
        }
      }
      .border {
        width: 100px;
        height: 100px;
        margin-left: 50px;
        border: 2px solid #000;
        border-radius: 50%;
        position: relative;
        overflow: hidden;
      }
      .border::after {
        z-index: -1;
        content: '';
        width: 250px;
        height: 250px;
        position: absolute;
        top: calc(var(--boder) * 1%);
        left: -80%;
        border-radius: 30%;
        background-image: linear-gradient(to top, #0ff7eb 0%, #fa145d 100%);
        transform: rotate(45deg);
        animation: move 5s linear infinite;
      }

html标签

    <div style="user-select: none; width: 300px; height: 300px; margin: 0 auto">
   <div class="border"></div>
   <progress id="progress" value="0" max="100"></progress>
   <span id="text" style="user-select: none">0</span>
 </div>