【问题标题】:calculate percentage in progress circle计算进度圈百分比
【发布时间】:2021-05-18 04:48:04
【问题描述】:

我想在不点击按钮渲染的情况下动态(实时)生成进度圈

例子:

  • 成分1的输入加10,成分2的输入加10,成分3的输入加10。总共30个圆圈应该在不点击渲染按钮的情况下渲染

  • 取消选中任何成分复选框总计会计算所有输入值。整个圆圈应该在不点击渲染按钮的情况下渲染

演示:https://jsfiddle.net/worldwildweb/mcjs9275/

jQuery(function($) {
 
 
  $(function() {
  $(".tags").on('input', function() {

    var calculated_total_sum = $(this).find(".ingredient").map(function() {
      const chck = $(this).is(":checked")
      const val = $(this).closest("div").find(".txtCal").val()
      return chck ? +val : 0;
    }).get().reduce((a, b) => a + b)
    $("#percent").val(calculated_total_sum);
    if ($("#percent").text() > 1000) {
    $("#percent").css('color', 'red');
  }    
  else{
    $("#percent").css('color', 'green');
  }
  });
});
// ingrédients allergènes
$('div.tags').delegate('input:checkbox', 'change', function() {
  $(this).parent().nextAll().slice(0, 2).hide().val('0');
  
  
  var list = $('.results > li').hide();
  //For each one checked
  $('input:checked').each(function() {
    list.filter('.' + $(this).attr('rel')).show();
    $(this).parent().nextAll().slice(0, 2).show();
  });
}).find('input:checkbox').change();  

$(".tags").on('input', '.txtCal', function () {
     var calculated_total_sum = 0;
   
     $(".tags .txtCal").each(function () {
         var get_textbox_value = $(this).val();
         if ($.isNumeric(get_textbox_value)) {
            calculated_total_sum += parseFloat(get_textbox_value);
            }                  
          });
            $("#percent").val(calculated_total_sum);



            
     });

     var svg ;

function drawProgress(end){ 
d3.select("svg").remove() 
  if(svg){
  svg.selectAll("*").remove();
  
}
var wrapper = document.getElementById('radialprogress');
var start = 0;
 
var colours = {
  fill: '#FF0000',
  track: '#555555',
  text: '#00C0FF',
  stroke: '#FFFFFF',
}

var radius = 80;
var border = 12;
var strokeSpacing = 4;
var endAngle = Math.PI * 2;
var formatText = d3.format('.0%');
var boxSize = radius * 2;
var count = end;
var progress = start;
var step = end < start ? -0.01 : 0.01;

//Define the circle
var circle = d3.svg.arc()
  .startAngle(0)
  .innerRadius(radius)
  .outerRadius(radius - border);

//setup SVG wrapper
svg = d3.select(wrapper)
  .append('svg')
  .attr('width', boxSize)
  .attr('height', boxSize);

  
// ADD Group container
var g = svg.append('g')
  .attr('transform', 'translate(' + boxSize / 2 + ',' + boxSize / 2 + ')');

//Setup track
var track = g.append('g').attr('class', 'radial-progress');
track.append('path')
  .attr('fill', colours.track)
  .attr('stroke', colours.stroke)
  .attr('stroke-width', strokeSpacing + 'px')
  .attr('d', circle.endAngle(endAngle));

//Add colour fill
var value = track.append('path')
  .attr('fill', colours.fill)
  .attr('stroke', colours.stroke)
  .attr('stroke-width', strokeSpacing + 'px');

//Add text value
var numberText = track.append('text')
  .attr('fill', colours.text)
  .attr('text-anchor', 'middle')
  .attr('dy', '.5rem'); 

  //update position of endAngle
  value.attr('d', circle.endAngle(endAngle * end));
  //update text value
  numberText.text(formatText(end));
  
}

$('#submitClick').click(function(){
  var val = parseInt($('#percent').val());
   drawProgress(val/100)
})
 
drawProgress(10/100)

});
    <div class="tags">
      <div>
        <label><input type="checkbox" checked rel="ingredient-1" class="ingredient"> ingredient 1 </label><br><input type="text" class='txtCal'  /><br>
      </div>
      <div>
        <label><input type="checkbox" checked rel="ingredient-2" class="ingredient"> ingredient 2 </label><br><input type="text" class='txtCal' /><br>
      </div>
      <div>
        <label><input type="checkbox" checked rel="ingredient-3" class="ingredient"> ingredient 3 </label><br><input type="text" class='txtCal' /><br>
      </div>
      <span><b>TOTAL  :</b></span><b><span id="total_sum_value"></span></b>
      <!-- https://stackoverflow.com/questions/49345858/html-how-do-i-generate-a-progress-bar-circle-with-a-percentage-in-and-set-the -->
      <label for="percent">Type a percent!</label>
<input id="percent" name="percent" value=10>
<button id='submitClick' name='submitButton' >Render</button>


<div id="radialprogress"></div>
    </div>


        <ul class="results">
             <li class="ingredient-1 ingredient-3">Alpha isomethylionone</li>
             <li class="ingredient-1">Amyl cinnamal (Jasmonal A)</li>
             <li class="ingredient-1">Amylcinnamyl alcohol</li>
             <li class="ingredient-1">Anisyl alcohol</li>
             <li class="ingredient-1 ingredient-2">Benzyl alcohol</li>
             <li class="ingredient-1 ingredient-2 ingredient-3">Benzyl benzoate</li>
             <li class="ingredient-2">Benzyl cinnamate</li>
             <li class="ingredient-2">Benzyl salicylate</li>
             <li class="ingredient-2">Butylphenyl methylpropional (Lilial)</li>
             <li class="ingredient-2 ingredient-3">Cinnamal</li>
             <li class="ingredient-3">Cinnamyl alcohol</li>
             <li class="ingredient-3">Citral</li>
             <li class="ingredient-3">Citronellol</li>
             <li class="ingredient-3">Coumarin</li>
        </ul>

        <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

【问题讨论】:

    标签: html jquery svg


    【解决方案1】:

    要在值更改时重绘进度圈,只需调用input 事件处理程序中的drawProgress() 函数即可。

    另请注意,您可以对代码进行其他一些改进:

    • 删除嵌套文档。准备就绪
    • delegate 已弃用,请改用 on
    • $('#percent').text() 应该是 $('#percent').val(),我假设该行的条件中的 1000 应该是 100。

    jQuery($ => {
      $('#submitClick').click(function() {
        var val = parseInt($('#percent').val());
        drawProgress(val / 100);
      }).trigger('click');
      
      $(".tags").on('input', function() {
        // needlessly using 2 loops here, amended
        //var calculated_total_sum = $(this).find(".ingredient:checked").map((i, el) => parseFloat($(el).closest("div").find(".txtCal").val())).get().reduce((a, b) => a + b) || 0;   
        var calculated_total_sum = 0;
        $(this).find('div:has(.ingredient:checked) .txtCal').each((i, el) => calculated_total_sum += parseFloat(el.value));   
        
        $("#percent")
          .val(calculated_total_sum)
          .css('color', parseFloat($("#percent").val()) > 1000 ? 'red' : 'green');
          
        drawProgress(calculated_total_sum / 100);
      });
    
      // ingrédients allergènes
      $('div.tags').on('change', 'input:checkbox', function() {
        $(this).parent().nextAll().slice(0, 2).hide().val('0');
        var list = $('.results > li').hide();
        
        $('input:checked').each(function() {
          list.filter('.' + $(this).attr('rel')).show();
          $(this).parent().nextAll().slice(0, 2).show();
        });
      }).find('input:checkbox').change();
    
      $(".tags").on('input', '.txtCal', function() {
        var calculated_total_sum = 0;
        $(".tags .txtCal").each(function() {
          var get_textbox_value = $(this).val();
          if ($.isNumeric(get_textbox_value)) {
            calculated_total_sum += parseFloat(get_textbox_value);
          }
        });
        $("#percent").val(calculated_total_sum);
      });
    
      var svg;
    
      function drawProgress(end) {
        d3.select("svg").remove()
        if (svg) {
          svg.selectAll("*").remove();
        }
        var wrapper = document.getElementById('radialprogress');
        var start = 0;
    
        var colours = {
          fill: '#FF0000',
          track: '#555555',
          text: '#00C0FF',
          stroke: '#FFFFFF',
        }
    
        var radius = 80;
        var border = 12;
        var strokeSpacing = 4;
        var endAngle = Math.PI * 2;
        var formatText = d3.format('.0%');
        var boxSize = radius * 2;
        var count = end;
        var progress = start;
        var step = end < start ? -0.01 : 0.01;
    
        //Define the circle
        var circle = d3.svg.arc()
          .startAngle(0)
          .innerRadius(radius)
          .outerRadius(radius - border);
    
        //setup SVG wrapper
        svg = d3.select(wrapper)
          .append('svg')
          .attr('width', boxSize)
          .attr('height', boxSize);
    
    
        // ADD Group container
        var g = svg.append('g')
          .attr('transform', 'translate(' + boxSize / 2 + ',' + boxSize / 2 + ')');
    
        //Setup track
        var track = g.append('g').attr('class', 'radial-progress');
        track.append('path')
          .attr('fill', colours.track)
          .attr('stroke', colours.stroke)
          .attr('stroke-width', strokeSpacing + 'px')
          .attr('d', circle.endAngle(endAngle));
    
        //Add colour fill
        var value = track.append('path')
          .attr('fill', colours.fill)
          .attr('stroke', colours.stroke)
          .attr('stroke-width', strokeSpacing + 'px');
    
        //Add text value
        var numberText = track.append('text')
          .attr('fill', colours.text)
          .attr('text-anchor', 'middle')
          .attr('dy', '.5rem');
    
        //update position of endAngle
        value.attr('d', circle.endAngle(endAngle * end));
        //update text value
        numberText.text(formatText(end));
      }
    });
    <div class="tags">
      <div>
        <label><input type="checkbox" checked rel="ingredient-1" class="ingredient"> ingredient 1 </label><br><input type="text" class='txtCal' /><br>
      </div>
      <div>
        <label><input type="checkbox" checked rel="ingredient-2" class="ingredient"> ingredient 2 </label><br><input type="text" class='txtCal' /><br>
      </div>
      <div>
        <label><input type="checkbox" checked rel="ingredient-3" class="ingredient"> ingredient 3 </label><br><input type="text" class='txtCal' /><br>
      </div>
      <span><b>TOTAL  :</b></span><b><span id="total_sum_value"></span></b>
      <label for="percent">Type a percent!</label>
      <input id="percent" name="percent" value="0">
      <button id='submitClick' name='submitButton'>Render</button>
      <div id="radialprogress"></div>
    </div>
    <ul class="results">
      <li class="ingredient-1 ingredient-3">Alpha isomethylionone</li>
      <li class="ingredient-1">Amyl cinnamal (Jasmonal A)</li>
      <li class="ingredient-1">Amylcinnamyl alcohol</li>
      <li class="ingredient-1">Anisyl alcohol</li>
      <li class="ingredient-1 ingredient-2">Benzyl alcohol</li>
      <li class="ingredient-1 ingredient-2 ingredient-3">Benzyl benzoate</li>
      <li class="ingredient-2">Benzyl cinnamate</li>
      <li class="ingredient-2">Benzyl salicylate</li>
      <li class="ingredient-2">Butylphenyl methylpropional (Lilial)</li>
      <li class="ingredient-2 ingredient-3">Cinnamal</li>
      <li class="ingredient-3">Cinnamyl alcohol</li>
      <li class="ingredient-3">Citral</li>
      <li class="ingredient-3">Citronellol</li>
      <li class="ingredient-3">Coumarin</li>
    </ul>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    【讨论】:

    • 对于您的第三点:$('#percent').text() 应该是 $('#percent').val(),我假设该行的条件为 1000改为 100。这个想法是,当 % > 100 时,圆圈变为红色,否则 =
    • 这是我的假设,这就是我做出我描述的改变的原因。
    【解决方案2】:

    使用&lt;path&gt; 可能更容易创建该圈子,
    然后使用pathLength="100" 和stroke-dasharray="30 70" 设置30% 的进度。

    不需要 jQuery 或 D3 库

    现代的自定义元素(所有现代浏览器都支持)使得 HTML 元素可重用

     <svg-progress-circle percent="30"></svg-progress-circle>
     <svg-progress-circle percent="20" color="blue"></svg-progress-circle>
     <svg-progress-circle percent="80" color="gold"></svg-progress-circle>
    

    查看滑块oninput,设置值:

        document.getElementById("Slider1").percent = <PERCENTAGE>;
    

    <style>
      svg { width: 150px; background: teal; }
      svg-progress-circle[percent="100"] path { stroke: green; }
    </style>
    
    <svg-progress-circle percent="30"></svg-progress-circle>
    <svg-progress-circle percent="20" color="blue"></svg-progress-circle>
    <svg-progress-circle percent="80" color="gold"></svg-progress-circle>
    
    <script>
      customElements.define("svg-progress-circle", class extends HTMLElement {
        connectedCallback() {
          let d = 'M5,30a25,25 0 1,1 50,0a25,25 0 1,1 -50,0'; // circle
          this.innerHTML = `<input min="0" max="100" step="10" value="30" oninput="this.parentNode.percent=this.value" type="range"/><br>
          <svg viewBox="0 0 60 60">
      <path stroke-dasharray="10 2"   stroke-dashoffset="-19" 
            pathlength="120" d="${d}" fill="grey" stroke="lightgrey" stroke-width="5"/>
      <path stroke-dasharray="30 70" stroke-dashoffset="-25" 
            pathlength="100" d="${d}" fill="none" 
            stroke="${this.getAttribute("color")||"red"}" stroke-width="5"/>
      <text x="50%" y="57%" text-anchor="middle">30%</text></svg></span>`;
          this.style.display='inline-block';
          this.percent = this.getAttribute("percent");
        }
        set percent(val = 0) {
          this.setAttribute("percent", val);
          let dash = val + " " + (100 - val);
          this.querySelector("path+path").setAttribute('stroke-dasharray', dash);
          this.querySelector("text").innerHTML = val + "%";
          this.querySelector("input").value = val;
        }
      })
    </script>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-22
      • 2021-08-06
      • 2015-01-03
      • 1970-01-01
      • 2023-02-08
      • 2021-03-24
      相关资源
      最近更新 更多