如何在 JavaScript 中绘制具有渐近行为的函数,例如 tan(x)、ln(x) 和 log(x)?

问题描述 投票:0回答:1

我正在开发一个项目,需要在 JavaScript 中绘制数学函数的图形,特别是在某些点表现出渐近行为或接近无穷大的函数,例如 tan(x)、ln(x) 和 log(x) 。我正在努力解决如何准确表示这些函数,特别是在它们接近无穷大的点附近(例如,tan(x) 的接近垂直渐近线)。

这是我绘制函数的代码:

export function drawFunction(latexStr) {
  let isTan;
  // Draw function
  console.log(canvas.height);
  console.log(canvas.width);

  let prevY; // Stores the previous Y value
  let startY = true; // To know when a new line is needed

  ctx.beginPath();
  ctx.strokeStyle = "blue";
  ctx.lineWidth = 2;
  // Draw the function in small steps
  for (let x = -canvas.width / 2; x <= canvas.width / 2; x += stepSize) {
    let y = parser(latexStr, x)[0]; // f(x)
    isTan = parser(latexStr, x)[1];
    console.log(isTan);
    // Skip drawing the graph if it's infinite or too large for the canvas
    if (Math.abs(y) > canvas.height / scaleFactor && !isTan) {
      startY = true;
      y = (y < 0 ? -1 : 1) * (canvas.height / scaleFactor - 1);
    }

    const adjustedX = canvas.width / 2 + x * scaleFactor; // Calculation of the small X line
    const adjustedY = canvas.height / 2 - y * scaleFactor; // Calculation of the small Y line

    /*     if (Math.round(x * 100) / 100 === stepSize)
      ctx.moveTo(adjustedX, adjustedY); */

    // Draw or move to position
    if (startY) {
      ctx.moveTo(adjustedX, adjustedY);
      startY = false;
    } else {
      if (prevY !== undefined && Math.abs(y - prevY) > 1 * scaleFactor) {
        if (isTan) {
          ctx.stroke(); // Draw the current line
          ctx.beginPath(); // Start a new line
          ctx.moveTo(adjustedX, y < 0 ? canvas.height : 0); // Move to the edge of the canvas
        } else {
          ctx.moveTo(adjustedX, adjustedY); // Move to the new starting position
        }
      } else {
        ctx.lineTo(adjustedX, adjustedY);
      }
    }

    prevY = y;
    //console.log(Math.round(x * 100) / 100);
  }

  ctx.stroke(); // Draw the function
}

绘制像“y = x+2”这样的普通函数没有问题,但是像“y = tan(x)”这样的函数就会出现问题,如下图所示:

这些值是正确的,所以这似乎不是计算的问题,而是绘图处理方式的问题。我到处搜索但找不到解决方案。有谁对我如何改进绘图算法以更好地处理 tan(x) 等函数的无穷点有建议吗?

提前感谢您的帮助!

javascript html plot canvas html5-canvas
1个回答
0
投票

你的问题不太清楚,并且你没有提供完整的代码...
从你的图像中,我假设你不满意的是一些线条没有一直到达画布的边缘,如下图所示:

问题

这里有一些简单的代码重现您的问题:

var canvas = document.getElementById('plotCanvas');
var ctx = canvas.getContext('2d');

var startX = -20;
var endX = 20;
var scaleFactor = 25;

ctx.beginPath();
for (var x = startX + 0.01; x <= endX; x += 0.01) {
  xP = (x - startX) * (canvas.width / (endX - startX));
  yP = canvas.height / 2 - Math.tan(x) * scaleFactor
  if (xP > 0 && yP > 0 && xP < canvas.width && yP < canvas.height) {
    ctx.lineTo(xP, yP);
  } else {
    ctx.moveTo(xP, yP)
  }
}
ctx.strokeStyle = 'blue';
ctx.stroke();
canvas {
  border: 1px solid black;
}
<canvas id="plotCanvas" width="400" height="400"></canvas>


解决方案

边距的条件需要更灵活一点,让我们在画布边界之外画几条线,而不是像我那样停在 0 我让它去

-canvas.width
,仅此而已

var canvas = document.getElementById('plotCanvas');
var ctx = canvas.getContext('2d');

var startX = -20;
var endX = 20;
var scaleFactor = 25;

ctx.beginPath();
for (var x = startX + 0.01; x <= endX; x += 0.01) {
  xP = (x - startX) * (canvas.width / (endX - startX));
  yP = canvas.height / 2 - Math.tan(x) * scaleFactor
  if (xP > -canvas.width && yP > -canvas.height && xP < canvas.width && yP < canvas.height) {
    ctx.lineTo(xP, yP);
  } else {
    ctx.moveTo(xP, yP)
  }
}
ctx.strokeStyle = 'blue';
ctx.stroke();
canvas {
  border: 1px solid black;
}
<canvas id="plotCanvas" width="400" height="400"></canvas>

© www.soinside.com 2019 - 2024. All rights reserved.