
本文详解反比例函数在 canvas 绘图中因无穷间断点(x=0)导致空白画布的问题,提供分步计算、动态 y 轴范围裁剪、无穷值跳过及坐标映射的完整解决方案。
本文详解反比例函数在 canvas 绘图中因无穷间断点(x=0)导致空白画布的问题,提供分步计算、动态 y 轴范围裁剪、无穷值跳过及坐标映射的完整解决方案。
在使用 HTML5 Canvas 绘制数学函数时,线性函数(如 y = x)表现稳定,但反比例函数(如 y = 2/x)极易引发绘图失败——根本原因在于 x = 0 处函数无定义,JavaScript 中 2 / 0 返回 Infinity,而 Infinity 或 -Infinity 无法被合法映射到画布像素坐标,进而导致 lineTo() 抛出静默错误或路径断裂,最终画布显示为空白。
要可靠绘制此类函数,需从三个层面重构逻辑:数据预处理 → 坐标安全映射 → 渲染状态控制。以下是经过验证的专业实现方案:
✅ 1. 分离计算与渲染:先生成点集,再统一处理
避免在循环中实时计算并绘图,防止 Infinity 立即污染路径。推荐将函数采样封装为独立函数,返回带索引的 {x, y, i} 对象数组:
function graph(f, startX = -20, endX = 20, dx = 0.1) {
const points = [];
for (let i = 0; i 2 / x, -20, 20, 0.1);
✅ 2. 动态裁剪 Y 轴范围:排除异常极值
直接使用全局 minY/maxY 会导致缩放失真(如 y=2/x 在 [-20,20] 内理论值域为 (-∞, ∞))。应采用百分位截断法(Percentile Clipping),保留中间 98% 的有效 y 值,自动过滤无穷大和极端离群点:
function range(fromP, toP, values) {
const validYs = values.filter(y => Number.isFinite(y)); // 先剔除 Infinity/NaN
if (validYs.length === 0) return { min: -10, max: 10 }; // 降级兜底
const sorted = [...validYs].sort((a, b) => a - b);
const p0 = Math.max(0, Math.min(sorted.length - 1, Math.floor(sorted.length * fromP)));
const p1 = Math.max(0, Math.min(sorted.length - 1, Math.floor(sorted.length * toP)));
return { min: sorted[p0], max: sorted[p1] };
}
const yRange = range(0.01, 0.99, points.map(p => p.y));
⚠️ 注意:
range()中必须先filter(Number.isFinite),否则Infinity会破坏sort()行为(Infinity > any_number恒为 true,但排序稳定性不可靠)。
✅ 3. 安全坐标映射与路径管理
使用通用 scale() 函数完成双线性映射,并在绘制时严格检查相邻点是否含无穷值——一旦检测到 Infinity 或 NaN,立即调用 moveTo() 中断当前线段,避免跨渐近线“乱连”:
function scale(value, minFrom, maxFrom, minTo, maxTo) {
const t = Math.max(0, Math.min(1, (value - minFrom) / (maxFrom - minFrom)));
return minTo + t * (maxTo - minTo);
}
ctx.beginPath();
for (const { x, y, i } of points) {
const px = scale(x, -20, 20, 0, canvas.width);
const py = scale(y, yRange.max, yRange.min, 0, canvas.height); // 注意:y轴翻转,max在上
const prev = points[i - 1];
const isInvalid = !Number.isFinite(y) || !prev || !Number.isFinite(prev.y);
if (isInvalid) {
ctx.moveTo(px, py); // 新起点,不连线
} else {
ctx.lineTo(px, py);
}
}
ctx.strokeStyle = 'blue';
ctx.stroke();
? 补充说明与优化建议
-
X 轴采样优化:对反比例函数,建议在
x=0附近加密采样(如分段使用dx=0.01),远离区域稀疏采样(dx=0.5),兼顾性能与精度; -
多分支支持:若需绘制
y=1/(x-1)等平移函数,只需调整graph()的startX/endX,range()仍自动适应; -
视觉增强:可添加虚线渐近线(如
x=0和y=0),提升数学可读性; -
错误防御:在
f(x)调用处包裹try...catch,捕获用户输入的非法表达式(如y=2/(x-0)未加空格导致解析失败)。
通过以上三步重构,您将获得一个鲁棒、可扩展且符合数学直觉的函数绘图器——不仅能正确呈现 y=2/x 的双曲线分支,也为后续支持 tan(x)、log(x) 等更多病态函数奠定坚实基础。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











