I need some help increasing the height of HTML canvas lines

Viewed 39

I am doing a project where the user selects what programming language they enjoy out of a radio box. It sets an object to the Local Storage and creates a bar graph and the bars go up depending on what choice the select. I'm having trouble though where if the user selects the language for the third time, it turns out what is in the image. I change the height each time and for some reason it also goes over the axis. I just want the height to change. I'm not super familiar with the canvas. Is there a way I could go about doing this? I just simply want the bar to start at the origin and go up, but not down. Code below:

<!--
Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
Click nbfs://nbhost/SystemFileSystem/Templates/Other/html.html to edit this template
-->
<!DOCTYPE HTML>
<html>
<head>
      <title>Extra Credit Challenge</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
            #entryArea{
                border: 1px solid black;
                width: 30%;
                border-radius: 100px;
                text-align: center;
                margin: auto;
            }
            #myCanvas{
                border-radius: 25px;
                border: 1px;
            }
            #submitButton{
                border-radius: 15px;
                background-color:lightblue;
                font-size: 25px;
                width: 30%;
            }
            input{
                font-size: 25px;
            }
            #resetButton{
                border-radius: 15px;
                background-color:lightblue;  
                font-size: 25px;
                width: 30%;  
            }
        </style>
</head>
<body onload="init()">
    <canvas id="myCanvas" width="500" height="450" style="border:1px solid #000000;"></canvas>

    <div id="entryArea"> 
            <p style="font-size: 20px">What is your favorite programming language?</p>
            <p><input name="language" type="radio" value="Web Design">Web Design</p> 
            <p><input name="language" type="radio" value="Java">Java</p>
            <p><input name="language" type="radio" value="Python">Python</p>
            <p><input name="language" type="radio" value="Other">Other</p>
            <button id="submitButton">Submit</button><br><br>
            <button id="resetButton">Reset</button>
    </div>
    
    <script> 
         function init(){ 
                unCheckItems();
                drawAxes();
                walkThroughStorage();  
                document.getElementById("submitButton").addEventListener("click", setItemToStorage);
                document.getElementById("resetButton").addEventListener("click", clearCanvas); 
            }
            function walkThroughStorage(){
                var ele = document.getElementById("entryArea").querySelectorAll("input");
                var curTextStorage = localStorage.getItem("ClickedBoxes");
                var c = document.getElementById("myCanvas");
                var ctx = c.getContext("2d");
                ctx.beginPath();
                curTextStorage = JSON.parse(curTextStorage);
                if(curTextStorage !== null){    
                    for(let i = 0; i<ele.length; i++){
                        let height = (curTextStorage[ele[i].value] || 0) * 40;  
                        if(ele[i].value === "Web Design"){
                            if(curTextStorage[ele[i].value] > 1){ 
                                ctx.rect(80, 310-(height/2), 30, height);
                                ctx.lineWidth = 1;
                                ctx.stroke(); 
                            } 
                            if(curTextStorage[ele[i].value] === 1){
                                ctx.rect(80, 310, 30, 40);
                                ctx.lineWidth = 1;
                                ctx.stroke();  
                            }
                        }
                        else if(ele[i].value === "Java"){
                            if(curTextStorage[ele[i].value] > 1){
                                ctx.rect(180, 310-(height/2), 30, height);
                                ctx.lineWidth = 1;
                                ctx.stroke();
                            }
                            if(curTextStorage[ele[i].value] === 1){
                                ctx.rect(180, 310, 30, 40);
                                ctx.lineWidth = 1;
                                ctx.stroke();  
                            }    
                        }
                        else if(ele[i].value === "Python"){
                            if(curTextStorage[ele[i].value] > 1){
                               ctx.rect(255, 310-(height/2), 30, height);
                               ctx.lineWidth = 1;
                               ctx.stroke();  
                            }
                            if(curTextStorage[ele[i].value] === 1){
                               ctx.rect(255, 310, 30, 40);
                               ctx.lineWidth = 1;
                               ctx.stroke(); 
                            }      
                        }
                        else{
                            if(curTextStorage[ele[i].value] > 1){  
                               ctx.rect(335, 310-(height/2), 30, height);
                               ctx.lineWidth = 1;
                               ctx.stroke();    
                            }
                            if(curTextStorage[ele[i].value] === 1){
                              ctx.rect(335, 310, 30, 40);
                              ctx.lineWidth = 1;
                              ctx.stroke();   
                            }                           
                        }
                    }           
               }
               ctx.closePath();
            }
            function drawAxes(){
                var c = document.getElementById("myCanvas");
                var ctx = c.getContext("2d");
                ctx.beginPath();
                //draw x axis
                ctx.moveTo(20,350); 
                ctx.lineTo(500,350);
                ctx.lineWidth = 4;
                ctx.stroke();
                ctx.closePath();
                //draw y axis
                ctx.beginPath();
                ctx.moveTo(40,400);
                ctx.lineTo(40,0);  
                ctx.stroke();
                ctx.closePath();
                //draw names at the bottom
                ctx.font = "15px Arial";
                ctx.fillText("Web Design", 60,370);
                ctx.fillText("Java", 180,370);
                ctx.fillText("Python", 250,370);
                ctx.fillText("Other", 330,370);
            }
            function unCheckItems(){ 
                var ele = document.getElementById("entryArea").querySelectorAll("input");
                for(let i = 0; i < ele.length; i++) {
                    if(ele[i].checked){
                        ele[i].checked = false;
                    } 
                }
            }
            function setItemToStorage(){
                var savedClicks = localStorage.getItem("ClickedBoxes");
                let clickDict = JSON.parse(savedClicks) || {};
                var ele = document.getElementById("entryArea").querySelectorAll("input");
                for(let i = 0; i < ele.length; i++){
                    if(ele[i].checked){                  
                        if(!clickDict[ele[i].value]){     
                            clickDict[ele[i].value]=1;
                        }   
                        else//the key of 1,2,3,4 or 5 (contents of curRandNum) exist in theDict so add one to its value 
                        {
                            clickDict[ele[i].value] += 1;    
                        }   
                    }
                    localStorage.setItem("ClickedBoxes",JSON.stringify(clickDict));
               }
               drawBars(); 
            }
            function drawBars(){
               var savedClicks = localStorage.getItem("ClickedBoxes");     
               savedClicks = JSON.parse(savedClicks);
               var c = document.getElementById("myCanvas");
               var ctx = c.getContext("2d");
               ctx.beginPath(); 
               var ele = document.getElementById("entryArea").querySelectorAll("input");
                for(let i = 0; i < ele.length; i++) {
                    let height = (savedClicks[ele[i].value] || 0) * 40;
                    if(ele[i].checked){
                        if(ele[i].value === "Web Design"){
                            if(savedClicks[ele[i].value] > 1){
                                clearBar();
                                //ctx.clearRect(80, 300, 30, 40);   
                                ctx.rect(80, 310-(height/2), 30, height);
                                ctx.lineWidth = 0;
                                ctx.stroke();
                            }  
                            if(savedClicks[ele[i].value] === 1){ 
                                ctx.rect(80, 310, 30, 40);
                                ctx.lineWidth = 1;
                                ctx.stroke(); 
                            }
                        }
                        else if(ele[i].value === "Java"){
                            if(savedClicks[ele[i].value] > 1){
                                clearBar();
                                ctx.rect(180, 310-(height/2), 30, height);
                                ctx.lineWidth = 0;
                                ctx.stroke();
                            }
                            if(savedClicks[ele[i].value] === 1){
                                ctx.rect(180, 310, 30, 40);
                                ctx.lineWidth = 1;
                                ctx.stroke();  
                            }    
                        }
                        else if(ele[i].value === "Python"){
                            if(savedClicks[ele[i].value] > 1){
                                clearBar();
                                ctx.rect(255, 310-(height/2), 30, height);
                                ctx.lineWidth = 0;
                                ctx.stroke();
                            }
                            if(savedClicks[ele[i].value] === 1){
                               ctx.rect(255, 310, 30, 40);
                               ctx.lineWidth = 1;
                               ctx.stroke(); 
                            }      
                        }
                        else{
                            if(savedClicks[ele[i].value] > 1){
                                clearBar();
                                ctx.rect(335, 310-(height/2), 30, height);
                                ctx.lineWidth = 0;
                                ctx.stroke();
                            }                    
                            if(savedClicks[ele[i].value] === 1){
                              ctx.rect(335, 310, 30, 40);
                              ctx.lineWidth = 1;
                              ctx.stroke();
                            }                           
                        }
                    }
                }
                ctx.closePath();
            }
            function clearBar(){
                var c = document.getElementById("myCanvas");
                var ctx = c.getContext("2d"); 
                ctx.clearRect(0, 0, c.width, c.height);
                init();
            }
            function clearCanvas(){
                var c = document.getElementById("myCanvas");
                var ctx = c.getContext("2d"); 
                ctx.clearRect(0, 0, c.width, c.height);
                localStorage.clear(); 
                init();    
            }
    </script>  
</body>
</html>

Here is the image photo Thanks in advance!

2 Answers

You have a miscalculation when drawing your rectanlges.

The lines

ctx.rect(255, 310-(height/2), 30, height);

should be changed to

ctx.rect(255, 350 - height, 30, height);

That's a bit too much copy-paste. The basic issue is what @Ruan shows: if you want to draw a rectangle which ends at y=350, you just subtract its height from 350, without any division.

Other things added/removed here are:

  • 0-1-many are not handled separately any more, a zero-sized rectangle conveniently stays inside the horizontal axis, so you can draw it, and 40 doesn't differ from 1*40, so there is no need to draw it separately
  • the code parts for drawing the 4 bars differred in their x coordinates only, even if their spacing is irregular, they can be picked from an array, see the [80, 180, 255, 335][i] part - bit nasty, but does the job
  • walkwhatever was removed, it was doing the same as drawBars()
  • a single reDraw() method was added for handling redraw of everything
  • duplicated canvas clearing removed
  • instead a clear() method was added for clearing existing data and calling reDraw()
  • init() is not reused anymore, as that would add click handlers again, which usually leads to interesting behaviour.

(And a fake localStorage has been added, simply because it's disabled for snippets hosted here on StackOverflow)

// this is just for simulating localStorage here on StackOverflow
const localStorage = {m: new Map(),
  getItem: function(k) {return this.m.has(k) ? this.m.get(k) : null;},
  setItem: function(k, v) {this.m.set(k, v);},
  clear: function() {this.m.clear();}};

function init() {
  unCheckItems();
  drawAxes();
  drawBars();
  document.getElementById("submitButton").addEventListener("click", setItemToStorage);
  document.getElementById("resetButton").addEventListener("click", clear);
}

function drawAxes() {
  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");
  ctx.beginPath();
  //draw x axis
  ctx.moveTo(20, 350);
  ctx.lineTo(500, 350);
  ctx.lineWidth = 4;
  ctx.stroke();
  ctx.closePath();
  //draw y axis
  ctx.beginPath();
  ctx.moveTo(40, 400);
  ctx.lineTo(40, 0);
  ctx.stroke();
  ctx.closePath();
  //draw names at the bottom
  ctx.font = "15px Arial";
  ctx.fillText("Web Design", 60, 370);
  ctx.fillText("Java", 180, 370);
  ctx.fillText("Python", 250, 370);
  ctx.fillText("Other", 330, 370);
}

function unCheckItems() {
  var ele = document.getElementById("entryArea").querySelectorAll("input");
  for (let i = 0; i < ele.length; i++) {
    if (ele[i].checked) {
      ele[i].checked = false;
    }
  }
}

function setItemToStorage() {
  var savedClicks = localStorage.getItem("ClickedBoxes");
  let clickDict = JSON.parse(savedClicks) || {};
  var ele = document.getElementById("entryArea").querySelectorAll("input");
  for (let i = 0; i < ele.length; i++) {
    if (ele[i].checked) {
      if (!clickDict[ele[i].value]) {
        clickDict[ele[i].value] = 1;
      } else //the key of 1,2,3,4 or 5 (contents of curRandNum) exist in theDict so add one to its value 
      {
        clickDict[ele[i].value] += 1;
      }
    }
    localStorage.setItem("ClickedBoxes", JSON.stringify(clickDict));
  }
  reDraw();
}

function drawBars() {
  var savedClicks = localStorage.getItem("ClickedBoxes");
  savedClicks = JSON.parse(savedClicks) || {};
  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");
  ctx.lineWidth = 1;
  var ele = document.getElementById("entryArea").querySelectorAll("input");
  for (let i = 0; i < ele.length; i++) {
    let height = (savedClicks[ele[i].value] || 0) * 40;
    ctx.strokeRect([80, 180, 255, 335][i], 350 - height, 30, height);
  }
}

function clearCanvas() {
  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");
  ctx.clearRect(0, 0, c.width, c.height);
}

function reDraw() {
  unCheckItems();
  clearCanvas();
  drawAxes();
  drawBars();
}

function clear() {
  localStorage.clear();
  reDraw();
}

init(); // "onload"
#entryArea {
  border: 1px solid black;
  width: 30%;
  border-radius: 100px;
  text-align: center;
  margin: auto;
}

#myCanvas {
  border-radius: 25px;
  border: 1px;
}

#submitButton {
  border-radius: 15px;
  background-color: lightblue;
  font-size: 25px;
  width: 30%;
}

input {
  font-size: 25px;
}

#resetButton {
  border-radius: 15px;
  background-color: lightblue;
  font-size: 25px;
  width: 30%;
}
<canvas id="myCanvas" width="500" height="450" style="border:1px solid #000000;"></canvas>

<div id="entryArea">
  <p style="font-size: 20px">What is your favorite programming language?</p>
  <p><input name="language" type="radio" value="Web Design">Web Design</p>
  <p><input name="language" type="radio" value="Java">Java</p>
  <p><input name="language" type="radio" value="Python">Python</p>
  <p><input name="language" type="radio" value="Other">Other</p>
  <button id="submitButton">Submit</button><br><br>
  <button id="resetButton">Reset</button>
</div>

Related