我目前正在使用 HTML Canvas 和 JavaScript 开发一个函数绘图应用程序。该应用程序旨在绘制用户输入的各种数学函数。它完美地处理线性函数(如 y=x 和 y=x+2),并在画布上正确渲染它们。
但是,我遇到了倒数函数的特定问题,特别是像 y=2/x 这样的函数。当我尝试绘制此类函数时,画布保持空白,并且不会在控制台中显示任何错误消息或日志。
这是我处理绘图的代码片段:
var canvas = document.getElementById('plotCanvas');
var ctx = canvas.getContext('2d');
var startX = -20;
var endX = 20;
var scaleFactor = 25;
var epsilon = 0.0001; // A small number close to zero
ctx.beginPath();
for (var x = startX + 0.01; x <= endX; x += 0.01) {
xP = (x - startX) * (canvas.width / (endX - startX));
let y = 2/x
yP = canvas.height / 2 - y * 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;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="plotCanvas" width="400" height="300"></canvas>
</body>
</html>
我认为问题是因为当 x = 0 时,它将趋于无穷大,而这是不可能绘制的。
我该如何解决这个问题?
您可以对所有 y 值进行排序,并找到将包含特定百分位数值的
min
和 max
。
请注意,如果您选择较大的范围或非常小的 delta x,这会产生一些开销。
这是一个例子,我:
const cvs = document.getElementById('plotCanvas');
const ctx = cvs.getContext('2d');
const minX = -20;
const maxX = 20;
const dx = 0.1;
const points = graph(
x => 2 / x,
minX,
maxX,
dx
);
const yRange = range(0.01, 0.99, points.map(p => p.y));
ctx.beginPath();
for (const { x, y, i } of points) {
const px = scale(x, minX, maxX, 0, cvs.width);
const py = scale(y, yRange.max, yRange.min, 0, cvs.height);
const prev = points[i - 1];
// Do not draw lines to/from (-)Infinity
if (
!prev ||
y === Infinity ||
y === -Infinity ||
prev.y === Infinity ||
prev.y === -Infinity) {
ctx.moveTo(px, py);
} else {
ctx.lineTo(px, py);
}
}
ctx.strokeStyle = 'blue';
ctx.stroke();
function scale(from, minFrom, maxFrom, minTo, maxTo) {
const pFrom = (from - minFrom) / (maxFrom - minFrom);
return minTo + (maxTo - minTo) * pFrom;
}
function graph(
f,
startX = -20,
endX = 20,
dx = 0.1,
) {
const points = [];
for (let i = 0; i < (endX - startX) / dx; i += 1) {
const x = startX + i * dx;
const y = f(x)
points.push({ x, y, i });
}
return points;
}
function range(fromP, toP, values) {
const p0 = Math.round(values.length * fromP);
const p1 = Math.round(values.length * toP);
const s = Array.from(values).sort((a,b) => b - a);
return { min: s[p0], max: s[p1] };
}
<canvas id="plotCanvas" width="400" height="300" style="border: 1px solid black"></canvas>