使用 Canvas API 创建一个显示至少 5 个随机数的图表

Create a graph showing at least 5 random numbers using the Canvas API

我已经为这个作业做了一个星期了,我很挣扎。我不想来这里打扰你们大多数人,因为老实说,你们比一些爱哭的学生能提供更多帮助,但在来这里之前我自己已经尝试了很多。我的表单验证工作正常,但我无法弄清楚如何对试图在 canvas 中绘制的图形进行 query.selector 调用用户输入数字范围。我想出了如何让数字显示在条形图的顶部,但是无法在它们的底部找到该死的单词来进行描述,而且我的条形图也不会居中。每次我尝试改变任何东西时,它都会消失。 JavaScript 对我来说真的很有挑战性,而且对初学者来说相当吓人。链接是我的 Codepen.io,它显示了我完成的大部分内容,我正在使用 Tailwind。

CodePen

What we're supposed to attempt - 我们还被告知要在我们身上放置比这个更多的“耀斑”。

document.querySelector("#sendbtn").addEventListener("click",onClick);

function onClick(e){
  console.log("click");
  const minnum = document.querySelector("#minnum");
  const maxnum = document.querySelector("#maxnum");
  if (minnum.checkValidity() && maxnum.checkValidity()){
    e.preventDefault();
    processForm();
  }
}

function processForm(){
  console.log("Form is Valid!")
}

(()=>{
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  ctx.beginPath();
  ctx.font = "14 Helvetica";
  for (let i = 0; i<5; i++) {
    console.log(i);
    let height = Math.floor() * (80 - 0) + 1;
    ctx.fillStyle = "#00FF00";
    ctx.fillRect(i * 50 + 10, 250 - height*3, 20, height*3);
    ctx.fillStyle = "#000000";
    ctx.fillText(height, i * 50 + 14, 248 - height*3)
  }
})();
#canvas {
    border: 2px solid rgb(2, 26, 247); background-color: gray;
    height: 100%;
    width: 100%;
}
<h1 class="bg-blue-600 text-center p-8 text-blue-200 font-bold text-2xl">JavaScript Code Demo - Canvas </h1>
<div class="bg-blue-600 min-h-screen flex items-center text-lg">
   <form action="/" class="p-10 md:w-2/3 lg:w-1/2 mx-auto rounded">
     <div class="shadow">
       <div class="flex items-center bg-blue-400 rounded-t-lg border-blue-500 border-b">
         <label for="minnum" class="w-20 text-right mr-8 p-4 text-blue-200">Min Number</label>
         <input type="number" name="minnum" id="minnum" tabindex="1" required autofocus min="0" placeholder="0" step="1" class="flex-1 p-4 pl-0 bg-transparent placeholder-blue-200               outline-none text-white overflow-ellipsis overflow-hidden">
       </div>
       <div class="flex items-center bg-blue-400  rounded-b-lg border-blue-500 mb-10">
         <label for="maxnum" class="w-20 text-right p-4 mr-8 text-blue-200">Max Number</label>
         <input type="number" name="maxnum" id="maxnum" placeholder="100" required tabindex="2" max="100" step="1" class="flex-1 p-4 pl-0 bg-transparent placeholder-blue-200 outline-           none text-white overflow-ellipsis overflow-hidden">
       </div>
     </div>
     <button type="submit" id="sendbtn" class="bg-green-400 block w-full rounded py-4 text-white font-bold shadow">Submit</button>
   </form>
 </div>
<canvas id="canvas" height="300" width="400"></canvas>

你并不孤单。 JavaScript 一开始可能会很艰难,但看起来您付出了一些努力。坚持下去,你就会掌握它的窍门。这是您要完成的工作的工作版本。我使用了您提供的 Codepen link。我提供的代码可以保存为 HTML 文件,或者您可以将 CSS、JS 和 HTML 分解到您的 Codepen 项目中。

  1. 由于浏览器正在处理基于输入属性的验证,我整合了事件侦听器功能。所以按钮点击会直接调用processForm(),而不是OnClick()。如果您在那里需要额外的步骤,您可以随时将其分解。
  2. 我设置了 canvas CSS 样式来匹配 canvas 标签中的元素宽度和高度属性,但是图表的大小是动态生成的,所以你应该是能够在没有太多麻烦的情况下进行调整。请注意,将 css 样式更改为 100% 会拉伸 canvas,导致图表看起来 pixelated/distorted。有很多方法可以让它响应式和全宽,只需查找响应式 canvas 或类似的东西。我还从蓝色容器中删除了“flex”class,并将 canvas 放入其中,但如果需要,可以随时恢复这些更改。
  3. 我添加了一些评论来帮助理解逻辑,但如果您有任何其他问题,我会尽力提供帮助。
  4. 如果您想在风格方面超越自己,我会考虑使用 rgba() 值 and/or 也许在图表上使用一些渐变填充。 w3schools 有一些非常简单的教程和沙盒,如果您愿意,可以尝试不同的想法。
  5. 我认为这涵盖了大部分内容,但如果我遗漏了什么,请告诉我。

祝你学业顺利,加油!

<!DOCTYPE HTML>
<html lang="en">
<head>
<title>Javascript Code Demo - Canvas</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css">
<style>
#canvas {
    border: 2px solid rgb(2, 26, 247); background-color: gray;
    height: 300px;
    width: 400px;
    margin:0 auto;
}
</style>
</head>
<body>
<h1 class="bg-blue-600 text-center p-8 text-blue-200 font-bold text-2xl">JavaScript Code Demo - Canvas </h1>
<div class="bg-blue-600 min-h-screen items-center text-lg">
   <form action="/" class="p-10 md:w-2/3 lg:w-1/2 mx-auto rounded">
     <div class="shadow">
       <div class="flex items-center bg-blue-400 rounded-t-lg border-blue-500 border-b">
         <label for="minnum" class="w-20 text-right mr-8 p-4 text-blue-200">Min Number</label>
         <input type="number" name="minnum" id="minnum" tabindex="1" required autofocus min="0" placeholder="0" step="1" class="flex-1 p-4 pl-0 bg-transparent placeholder-blue-200               outline-none text-white overflow-ellipsis overflow-hidden">
       </div>
       <div class="flex items-center bg-blue-400  rounded-b-lg border-blue-500 mb-10">
         <label for="maxnum" class="w-20 text-right p-4 mr-8 text-blue-200">Max Number</label>
         <input type="number" name="maxnum" id="maxnum" placeholder="100" required tabindex="2" max="100" step="1" class="flex-1 p-4 pl-0 bg-transparent placeholder-blue-200 outline-           none text-white overflow-ellipsis overflow-hidden">
       </div>
     </div>
     <button type="submit" id="sendbtn" class="bg-green-400 block w-full rounded py-4 text-white font-bold shadow">Submit</button>
   </form>
   <canvas id="canvas" height="300" width="400"></canvas>
 </div>
<script>
document.querySelector("#sendbtn").addEventListener("click",processForm);

function processForm(e){
  e.preventDefault();
  //get min and max values
  const min = +document.querySelector("#minnum").value;
  const max = +document.querySelector("#maxnum").value;
  //get canvas
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  ctx.font = "14 Helvetica";
  //reset canvas with background overlay
  ctx.fillStyle = "gray";
  ctx.fillRect(0, 0,canvas.width, canvas.height);
  //calculate bar width and position intervals based on canvas width and total bars
  const xInt = Math.floor(canvas.width/5);
  const rectWidth = xInt-20;

  for (let i = 0; i<5; i++) {
    //generate a random height between min & max values
    let height = Math.floor((Math.random() * (max - min + 1)) + min);
    //scale the height of the bars based on canvas height and enough margin to allow room for chart title
    let hScaled = (height*(canvas.height/125));

    //draw the bar
    ctx.fillStyle = "#00FF00";
    ctx.fillRect((i*xInt)+10, canvas.height-hScaled-20,rectWidth, hScaled);
    ctx.fillStyle = "#000000";
    ctx.fillText("Test Grades", (canvas.width/2)-20 , 20);
    //calculate x axis position
    let xPos = (i*xInt)+5;
    //y axis label
    ctx.fillText(height, Math.round(xPos+(rectWidth/2)) , canvas.height-hScaled-26);
    //x axis label
    ctx.fillText("Grade "+(i+1), Math.round(xPos+(rectWidth/4)) , canvas.height-10)
  }
}
</script>
</body>
</html>