【问题标题】:Update SVG progress circle by clicking checkboxes通过单击复选框更新 SVG 进度圈
【发布时间】:2022-02-11 15:35:39
【问题描述】:

我有 5 个复选框代表一个待办事项列表,对于我单击的每个复选框,圆的直径应该完成 1/5、2/5、3/5、4/5、5/ 5 直到完成 5 个复选框,复选框的创建顺序无关紧要。如果我单击“第一个 ToDo”和“第三个 ToDo”而不选择“第二个 ToDo”,则圆圈仍应显示 2/5。

到目前为止,我已经能够使圆圈与复选框的输入进行交互,但是当我单击其中一个待办事项时,我正在努力使视觉进度发生,它被标记但不在正确的顺序和部分,这个想法是视觉进度应该向右移动直到完成圆圈。

在网上找资料,我看到有人用<circle path>但是我真的很困惑,因为有些配置是通过CSS进行的,而其他人是在JS中进行的,据我所知最好用JS来显示进度,因为它应该在复选框的基础上运行。

function update() {

  var myBar = document.getElementById("myCircle");
  //Reference the Form.
  var toDo = document.getElementById("toDo");

  //Reference all the CheckBoxes in Table.
  boxes = toDo.querySelectorAll("input[type='checkbox']:checked");
  checked = boxes.length


  myBar.style.strokeDasharray = ((checked) * 100) + "%";
  if (checked === 0) {
    alert("Please select CheckBox(s).");
  }
  return true;
}

checks = document.querySelectorAll("input[type='checkbox']");
checks.forEach(function(box) {
  box.addEventListener("change", function() {
    update()
  });
});
#myCircle {
  width: 0;
  height: 30px;
  stroke: #A3BBAD;
  stroke-width: 3px;
}

#myProgress {
  margin: auto;
  width: 50%;
  stroke: #357266;
  stroke-width: 3px;
}
<svg height="100" width="100">
  <circle id="myProgress" cx="50" cy="50" r="40" fill="transparent"/>
  <circle id="myCircle" cx="50" cy="50" r="40" fill="transparent"/>
</svg>
<br>

<form id="toDo">
  <input id="FirstToDo" type="checkbox" value="1" /><label for="FirstToDo">First</label>
  <input id="SecondToDo" type="checkbox" value="2" /><label for="SecondToDo">Second</label>
  <input id="ThirdToDo" type="checkbox" value="3" /><label for="ThirdToDo">Third</label>
  <input id="FourthToDo" type="checkbox" value="4" /><label for="FourthToDo">Fourth</label>
  <input id="FifthToDo" type="checkbox" value="5" /><label for="FifthToDo">Fifth</label>
</form>
<script src="Circle.js"></script>

【问题讨论】:

  • 我为您创建了一个Stack Snippet,如果有任何问题,请随时编辑
  • 您将 strokeDasharray 从 100% 设置为 500%。
  • 我没有完全得到你的建议,你能更具体点吗?据我说,我将其设置为 100%,因此百分比可以代表整个圆圈。但是我对使用 SVG circle 很陌生,所以我不确定我是否使用了正确的方法。

标签: javascript html css svg checkbox


【解决方案1】:

首先,您需要了解百分比单位不是圆圈路径的一部分。在这种情况下:

如果使用百分比,则该值表示当前视口的百分比。
[source w3.org强调我的]

要设置圆圈路径的总长度,您可以使用pathLength="100" (see MDN for more information on the pathLength)。
然后,您可以调整您的 JS 以将 strokeDasharray 值设置为以 100 为底的圆的路径 lentgh。
这是一种可能的方法:

function update() {

  var myBar = document.getElementById("myCircle");
  //Reference the Form.
  var toDo = document.getElementById("toDo");

  //Reference all the CheckBoxes in Table.
  boxes = toDo.querySelectorAll("input[type='checkbox']:checked");
  checked = boxes.length


  myBar.style.strokeDasharray = (100 - (checked) * 20) + ', 100';
  if (checked === 0) {
    alert("Please select CheckBox(s).");
  }
  return true;
}

checks = document.querySelectorAll("input[type='checkbox']");
checks.forEach(function(box) {
  box.addEventListener("change", function() {
    update()
  });
});
svg {
  transform: rotate(-90deg);
}
#myCircle {
  width: 0;
  height: 30px;
  stroke: #A3BBAD;
  stroke-width: 3px;
}

#myProgress {
  margin: auto;
  width: 50%;
  stroke: #357266;
  stroke-width: 3px;
}
<svg height="100" width="100">
  <circle id="myProgress" cx="50" cy="50" r="40" fill="transparent"/>
  <circle id="myCircle" cx="50" cy="50" r="40" fill="transparent" pathLength="100"/>
</svg>
<br>

<form id="toDo">
  <input id="FirstToDo" type="checkbox" value="1" /><label for="FirstToDo">First</label>
  <input id="SecondToDo" type="checkbox" value="2" /><label for="SecondToDo">Second</label>
  <input id="ThirdToDo" type="checkbox" value="3" /><label for="ThirdToDo">Third</label>
  <input id="FourthToDo" type="checkbox" value="4" /><label for="FourthToDo">Fourth</label>
  <input id="FifthToDo" type="checkbox" value="5" /><label for="FifthToDo">Fifth</label>
</form>

附带说明,由于默认情况下圆形笔划从 cricle 的右侧开始,我在 svg 中添加了一个旋转 (-90deg) 以使进度条从圆形顶部开始。

【讨论】:

    【解决方案2】:

    这是一个纯 CSS 的解决方案。为此,输入框必须位于标记中的圆圈上方,我添加了一些布局技巧,但您可以使用 JS 对其进行调整并保留原始标记。

    代码使用基于 5 个 CSS 变量之和的圆锥梯度,这些值由复选框控制。如果需要更大的灵活性,这也可以通过 JS 完成。关键是对角度基于总和的区域进行着色,而不是对 5 个预定义区域进行着色。

    #myProgress {
      --task1: 0;
      --task2: 0;
      --task3: 0;
      --task4: 0;
      --task5: 0;
    }
    
    #FirstToDo:checked ~ #myProgress {
      --task1: 1;
    }
    
    #SecondToDo:checked ~ #myProgress {
      --task2: 1;
    }
    
    #ThirdToDo:checked ~ #myProgress {
      --task3: 1;
    }
    
    #FourthToDo:checked ~ #myProgress {
      --task4: 1;
    }
    
    #FifthToDo:checked ~ #myProgress {
      --task5: 1;
    }
    
    .flex {
      display: flex;
      flex-direction: row;
    }
    
    .circle {
      order: -1;
      width: 100px;
      height: 100px;
      background: blue;
      border-radius: 50%;
      mask: radial-gradient(farthest-side, transparent 0 70%, #fff 70% 100%);
      -webkit-mask: radial-gradient(farthest-side, transparent 0 70%, #fff 70% 100%);
    }   
    
    #myProgress {
      background-image: conic-gradient(
        green 0 calc((var(--task1) + var(--task2) + var(--task3) + var(--task4) + var(--task5))* 20%),
        transparent 0 100%);
    }
    <div class="flex">
        <input id="FirstToDo" type="checkbox" value="1" /><label for="FirstToDo">First</label>
        <input id="SecondToDo" type="checkbox" value="2" /><label for="SecondToDo">Second</label>
        <input id="ThirdToDo" type="checkbox" value="3" /><label for="ThirdToDo">Third</label>
        <input id="FourthToDo" type="checkbox" value="4" /><label for="FourthToDo">Fourth</label>
        <input id="FifthToDo" type="checkbox" value="5" /><label for="FifthToDo">Fifth</label>
    
      <div id="myProgress" class="circle"></div>
    </div>

    【讨论】:

      【解决方案3】:

      你可以:

      • 在圆形标签上设置pathLength="100" 表示百分比圆形占圆形路径的100%

      • % 计算将是 100 - percent

      • css 属性 strokeDashoffset 是您可以影响百分比的属性

         myBar.style.strokeDashoffset = 100 - percent;
        

          function update() {
      
            var myBar = document.getElementById("myProgress");
            //Reference the Form.
            var toDo = document.getElementById("toDo");
      
            //Reference all the CheckBoxes in Table.
            boxes = toDo.querySelectorAll("input[type='checkbox']:checked");
            checked = boxes.length
      
            var percent = (checked) * 20;
            
            myBar.style.strokeDashoffset = 100 - percent;
            if (checked === 0) {
              alert("Please select CheckBox(s).");
            }
            return true;
          }
      
          checks = document.querySelectorAll("input[type='checkbox']");
          checks.forEach(function(box) {
            box.addEventListener("change", function() {
              update()
            });
          });
         #mySvg {
            transform: rotate(-90deg);
         }
         
         #myCircle {
            width: 0;
            height: 30px;
            stroke: #A3BBAD;
            stroke-width: 3px;
          }
      
          #myProgress {
            margin: auto;
            width: 50%;
            stroke: #357266;
            stroke-width: 3px;
            stroke-dasharray: 100;
            stroke-dashoffset: 100;
          }
          <!DOCTYPE html>
          <html lang="en">
      
          <head>
            <meta charset="UTF-8">
            <title>Circle</title>
            <link rel="stylesheet" href="style.css">
          </head>
      
          <body>
      
            <svg id="mySvg" height="100" width="100">
              <circle id="myCircle" cx="50" cy="50" r="40" fill="transparent"/>
              <circle id="myProgress" cx="50" cy="50" r="40" fill="transparent" pathLength="100"/>
            </svg>
            <br>
      
            <form id="toDo">
              <input id="FirstToDo" type="checkbox" value="1" /><label for="FirstToDo">First</label>
              <input id="SecondToDo" type="checkbox" value="2" /><label for="SecondToDo">Second</label>
              <input id="ThirdToDo" type="checkbox" value="3" /><label for="ThirdToDo">Third</label>
              <input id="FourthToDo" type="checkbox" value="4" /><label for="FourthToDo">Fourth</label>
              <input id="FifthToDo" type="checkbox" value="5" /><label for="FifthToDo">Fifth</label>
            </form>
            <script src="Circle.js"></script>
          </body>
      
          </html>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-31
        • 2023-04-02
        • 2018-06-16
        • 1970-01-01
        • 1970-01-01
        • 2014-02-12
        • 1970-01-01
        • 2015-05-12
        相关资源
        最近更新 更多