Search code examples
javascripthtmlcssformsdonut-chart

Why will this HTML form let me increase numbers in a form, but not decrease them?


I have written an HTML page where the header features a form where you can enter in three numbers. Each number draws a ring in a donut chart. If you enter a zero, no ring is drawn. If you enter 50, half a ring is drawn. If you enter 100, a complete ring is drawn. There is a green outer ring, a orange middle ring, and a blue inner ring.

When I increase the numbers in the form from 0, either by typing or by clicking on the buttons which increase the number in the input field, and then click "Update rings", everything works just fine. However, when I attempt to make any of the rings shorter by lowering the numbers in the input fields, clicking on "Update rings" does not make the rings shorter. In short, I can increase percentage values, but I cannot decrease them.

Here's the code:

<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
body{
    margin: 0px;
    padding: 0px;
}
</style>
<form id="frm1" action="/action_page.php">
  Outer Ring Completion %: <input type="number" name="apercent" value="0" min="0" max="100">
  Middle Ring Completion %: <input type="number" name="bpercent" value="0" min="0" max="100">
  Inner Ring Completion %: <input type="number" name="cpercent" value="0" min="0" max="100">
</form>
<br>
<button onclick="ChangeNums()">Update rings</button>
<br>
</head>
<body onload="ChangeNums()">
<canvas id="myCanvas" width="600" height="600"></canvas>
<script>
var outerval;
var middleval;
var innerval;

function ChangeNums() {
    var x = document.getElementById("frm1");
    outerval = x.apercent.value;
    middleval = x.bpercent.value;
    innerval = x.cpercent.value;
    RenderChart()
};

function RenderChart() {

      //Outermost line
      var canvas = document.getElementById('myCanvas');
      var outerline = canvas.getContext('2d');
      var x = canvas.width / 2;
      var y = canvas.height / 2;
      var radius = 270;
      var startAngle = 1.5 * Math.PI;
      var endAngle = ((outerval - 25) / 50) * Math.PI;
      //var endAngle = 0.25 * Math.PI;
      var counterClockwise = false;

      outerline.beginPath();
      outerline.arc(x, y, radius, startAngle, endAngle, counterClockwise);
      outerline.lineWidth = 30;

      // line color
      outerline.strokeStyle = 'green';
      if(outerval != 0){
      outerline.stroke();
      }

      //Middle line
      var middleline = canvas.getContext('2d');
      var radiusB = 240;
      var startAngleB = 1.5 * Math.PI;
      var endAngleB = ((middleval - 25) / 50) * Math.PI;
      //var endAngleB = 0  * Math.PI;
      var counterClockwiseB = false;

      middleline.beginPath();
      middleline.arc(x, y, radiusB, startAngleB, endAngleB, counterClockwiseB);
      middleline.lineWidth = 30;

      // line color
      middleline.strokeStyle = 'orange';
      if(middleval != 0){
      middleline.stroke();
      }
      //Inner line
      var innerline = canvas.getContext('2d');
      var radiusC = 210;
      var startAngleC = 1.5 * Math.PI;
      var endAngleC = ((innerval - 25) / 50) * Math.PI;
      //var endAngleC = 0.5 * Math.PI;
      var counterClockwiseC = false;

      innerline.beginPath();
      innerline.arc(x, y, radiusC, startAngleC, endAngleC, counterClockwiseC);
      innerline.lineWidth = 30;

      // line color
      innerline.strokeStyle = 'blue';
      if(innerval != 0){
      innerline.stroke();
      }

}
</script>
</body>
</html> 

Solution

  • Clear the canvas before the re-render is the safest way to handle it. The value is changing but it doesn't automatically clear the canvas.

    outerline.clearRect(0, 0, canvas.width, canvas.height);
    

    before your

    outerline.beginPath();
    

    will do the job