javascript - 使用 JavaScript 和 HTML5 canvas 绘制线性函数

标签 javascript html function canvas plot

我的代码有什么问题?我尝试绘制一个线性函数 (y=a*x+b) 输入 ab 作为输入,每次线经过点 (0,0 ) 即使我设置了 b != 0.
为此,我使用 Canvas 和 JavaScript。 CSS 也是如此,但元素的样式在这里并不重要。

谁能指出我的错误?

<!DOCTYPE html>
<html lang="pl">
<head>
  <meta charset="utf-8" />
  <title>Ploter</title>
  <style>
    body {
      background-color: #303030;
      margin-right: auto;
      margin-left: auto;
      text-align: center;
    }

    h1,
    h2 {
      color: #ADADAD;
    }
  </style>
  <script>
    var canvas;
    var context;

    window.onload = function() {
      canvas = document.getElementById("plotCanvas");
      context = canvas.getContext("2d");

    }

    function plot() {
      var a = document.getElementById("inputA").value;
      var b = document.getElementById("inputB").value;

      document.getElementById("funEquation").innerHTML = "y=" + a + "x+" + b;
      context.clearRect(0, 0, canvas.width, canvas.height);

      var x0 = 0.5 * canvas.width;
      var y0 = 0.5 * canvas.height;
      var scale = 40; //40px per 1 unit
      var x;
      var y;
      var dx = 4;
      var xMax = Math.round((canvas.width - x0) / dx);
      var xMin = Math.round(-x0 / dx);
      var axes = {};
      axes.x0 = x0;
      axes.y0 = y0;
      axes.scale = scale;

      drawAxes(context, axes);

      context.beginPath();
      context.strokeStyle = "white";
      context.lineWidth = 2;

      for (var i = xMin; i < xMax; i++) {
        x = dx * i;
        y = (a * x + b) / scale;
        if (i == xMin) context.moveTo(x0 + x, y0 - y);
        else context.lineTo(x0 + x, y0 - y);

      }
      context.stroke();
    }

    function drawAxes(context, axes) {
      var x0 = axes.x0;
      var y0 = axes.y0;
      var width = context.canvas.width;
      var height = context.canvas.height;
      var xmin = 0;
      context.beginPath();
      context.strokeStyle = "red";
      context.lineWidth = 5;
      //----Y axis----
      context.moveTo(xmin, y0);
      context.lineTo(width, y0);
      //----X axis-----
      context.moveTo(x0, 0);
      context.lineTo(x0, height);

      //---X arrow---
      context.moveTo(width, height / 2);
      context.lineTo(width - 15, (height / 2) + 10);
      context.moveTo(width, height / 2);
      context.lineTo(width - 15, (height / 2) - 10);
      //---Y arrow---
      context.moveTo(width / 2, 0);
      context.lineTo((width / 2) - 10, 15);
      context.moveTo(width / 2, 0);
      context.lineTo((width / 2) + 10, 15);

      //X - signs
      for (var i = x0; i < width; i += 50) {
        context.moveTo(i, (height / 2) - 7);
        context.lineTo(i, (height / 2) + 7);
      }
      for (var i = x0; i > 0; i -= 50) {
        context.moveTo(i, (height / 2) - 7);
        context.lineTo(i, (height / 2) + 7);
      }

      //Y - signs
      for (var i = y0; i < height; i += 50) {
        context.moveTo((width / 2) - 7, i);
        context.lineTo((width / 2) + 7, i);
      }
      for (var i = y0; i > 0; i -= 50) {
        context.moveTo((width / 2) - 7, i);
        context.lineTo((width / 2) + 7, i);
      }

      context.stroke();
    }
  </script>
</head>
<body>
  <header>
    <h1>Ploter XY</h1>
  </header>
  <main>
    <section>
      <div id="inputContainer">
        <label for="inputA">a:</label>
        <input id="inputA" type="text" />
        <br />
        <label for="inputB">b:</label>
        <input id="inputB" type="text" />
        <br />
        <p>Equation: <span id="funEquation"></span></p>
        <input id="confirmButton" type="button" value="Draw" onclick="plot()"></input>
      </div>
      <div id="plotContainer">
        <canvas id="plotCanvas" height="500" width="700" />
      </div>
      <section>
  </main>
</body>
</html>

最佳答案

当您从输入框中获取 ab 时,它们都是以字符串形式出现的,您需要将它们转换为 Number 使下面的等式起作用。

错误发生在下一行

y=(a*x+b)/scale;

这里如果 x = 11, b = 22, x = 1 那么因为 ab 是字符串而不是数学加法所以有执行的字符串连接。值 y 变为 1122/scale

你必须改变以下内容

var a = Number(document.getElementById("inputA").value);
var b = Number(document.getElementById("inputB").value);

或快捷方式

var a = +document.getElementById("inputA").value;
var b = +document.getElementById("inputB").value;

下面的代码还有一个错误

x=dx*i;
y=(a*x+b)/scale;

您必须对 xy 都应用缩放,而不仅仅是 y。它应该像下面这样

x=dx*i;
y=(a*x+b);

x /= scale;
y /= scale;

规模也太大了,这会减小小值的图形大小

请在下面找到工作示例

var canvas;
var context;

window.onload = function()
{
	canvas = document.getElementById("plotCanvas");
	context = canvas.getContext("2d");

}

function plot()
{
	var a = Number(document.getElementById("inputA").value);
	var b = Number(document.getElementById("inputB").value);


	document.getElementById("funEquation").innerHTML = "y=" + a +"x+" + b;

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


	var x0 = 0.5 * canvas.width;
	var y0 = 0.5 * canvas.height;
	var scale = 1;  //40px per 1 unit
	var x;
	var y;
	var dx = 4;
	var xMax = Math.round((canvas.width-x0)/dx);
	var xMin = Math.round(-x0/dx);
	var axes={};
	axes.x0 = x0;
	axes.y0 = y0;
	axes.scale = scale;

	drawAxes(context,axes);

	context.beginPath();
	context.strokeStyle = "white";
	context.lineWidth = 2;

	for (var i=xMin; i<xMax; i++)
	{
		x=dx*i;
		y=(a*x+b);
		
		x /= scale;
		y /= scale;
		if(i==xMin) {
			context.moveTo(x0+x,y0-y);
		} else {
			context.lineTo(x0+x,y0-y);
		}
	}

	context.stroke();
}

function drawAxes(context, axes)
{
	var x0=axes.x0;
	var y0=axes.y0;
	var width=context.canvas.width;
	var height = context.canvas.height;
	var xmin = 0;
	context.beginPath();
	context.strokeStyle = "red";
	context.lineWidth = 5;
	//----Y axis----
	context.moveTo(xmin,y0);
	context.lineTo(width,y0);
	//----X axis-----
	context.moveTo(x0,0);
	context.lineTo(x0,height);

	//---X arrow---
	context.moveTo(width,height/2);
	context.lineTo(width-15,(height/2)+10);
	context.moveTo(width,height/2);
	context.lineTo(width-15,(height/2)-10);
	//---Y arrow---
	context.moveTo(width/2,0);
	context.lineTo((width/2)-10,15);
	context.moveTo(width/2,0);
	context.lineTo((width/2)+10,15);


	//X - signs
	for(var i=x0; i<width; i+=50)
	{
		context.moveTo(i,(height/2)-7);
		context.lineTo(i,(height/2)+7);
	}
	for(var i=x0; i>0; i-=50)
	{
		context.moveTo(i,(height/2)-7);
		context.lineTo(i,(height/2)+7);
	}

	//Y - signs
	for(var i=y0; i<height; i+=50)
	{
		context.moveTo((width/2)-7,i);
		context.lineTo((width/2)+7,i);
	}
	for(var i=y0; i>0; i-=50)
	{
		context.moveTo((width/2)-7,i);
		context.lineTo((width/2)+7,i);
	}

	context.stroke();

}
<!DOCTYPE html>
 <html lang="pl">
 <head>
    <meta charset="utf-8" />
    <title>Ploter</title>

    <style>
        body
        {
            background-color: #303030;
            margin-right: auto;
            margin-left: auto;
            text-align: center;
        }

        h1, h2
        {
            color: #ADADAD;
        }   
    </style>

    <script src="app.js"></script>



 </head>
 <body>
    <header>
        <h1>Ploter XY</h1>
    </header>
    <main>
        <section>
            <div id="inputContainer">
                <label for="inputA">a:</label>
                <input id="inputA" type="text" />
                <br />
                <label for="inputB">b:</label>
                <input id="inputB" type="text" />
                <br />
                <p>Equation: <span id="funEquation"></span></p>
                <input id="confirmButton" type="button" value="Draw" onclick="plot()" >
            </div>
            <div id="plotContainer">
                <canvas id="plotCanvas" height="500" width="700" />
            </div>
        <section>
    </main>


 </body>
 </html>

关于javascript - 使用 JavaScript 和 HTML5 canvas 绘制线性函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51198004/

相关文章:

function - 使用_(下划线)时出现"Missing parameter type for expanded function"?

html - 如何在不变形的情况下获得比周围框更大的图片?

javascript - 将 xsl 变量传递给 javascript 函数

javascript - 如何通过扩展在 Chrome 中点击时将用户重定向到新链接?

javascript - jquery 将焦点放在动态内容上?

javascript - V-validate 不适用于插值属性

javascript - 在 Google Maps javascript API v3 中持续更新矩形边界非常慢

html - <q>、<blockquote> 和 <cite> 的有效使用

javascript - 我无法阻止 CSS 发光效果

带有回调的 Javascript 函数,该回调将启动的对象作为参数传递