我正在开发一个项目,需要在 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) 等函数的无穷点有建议吗?
提前感谢您的帮助!
你的问题不太清楚,并且你没有提供完整的代码...
从你的图像中,我假设你不满意的是一些线条没有一直到达画布的边缘,如下图所示:
这里有一些简单的代码重现您的问题:
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>