Canvas 图形开发高频算法面试题

文章目录

一、判断点是否在闭合路径内(射线法 / 奇偶规则)

这是 Canvas 面试100% 会考的题,用于判断鼠标点击是否在多边形、不规则图形内。

1. 算法原理(射线法)

  • 从目标点向右发射一条水平无限长射线
  • 统计射线与闭合路径边的相交次数
  • 奇数次 = 在图形内,偶数次 = 在图形外

2. 通用代码(支持任意多边形 / 闭合路径)

javascript 复制代码
/**
 * 判断点是否在多边形内部 (射线法)
 * @param {Object} point - 目标点 {x, y}
 * @param {Array} polygon - 多边形顶点数组 [{x,y}, {x,y}, ...]
 * @returns {Boolean} 在内返回 true,在外 false
 */
function isPointInPolygon(point, polygon) {
  let inside = false;
  const px = point.x;
  const py = point.y;

  // 遍历多边形所有边(首尾相连)
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
    const xi = polygon[i].x, yi = polygon[i].y;
    const xj = polygon[j].x, yj = polygon[j].y;

    // 核心判断:点的y坐标在边的y区间内 + 射线与边相交
    const intersect = 
      ((yi > py) !== (yj > py)) 
      && 
      (px < (xj - xi) * (py - yi) / (yj - yi) + xi);

    if (intersect) inside = !inside;
  }
  return inside;
}

3. Canvas 原生简化方案

Canvas 自带 isPointInPath() API,性能更高、支持圆弧 / 贝塞尔曲线:

javascript 复制代码
// 绘制闭合路径
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(200, 100);
ctx.lineTo(150, 200);
ctx.closePath();

// 判断点 (150,150) 是否在路径内
const isInPath = ctx.isPointInPath(150, 150); 

二、判断点是否在圆形内

超简单,勾股定理计算距离即可。

javascript 复制代码
/**
 * 判断点是否在圆内
 * @param {Object} point - 点 {x,y}
 * @param {Object} circle - 圆 {x,y,r}
 * @returns {Boolean}
 */
function isPointInCircle(point, circle) {
  const dx = point.x - circle.x;
  const dy = point.y - circle.y;
  // 距离平方 < 半径平方(避免开方,提升性能)
  return dx * dx + dy * dy <= circle.r * circle.r;
}

三、线段相交判断

用于碰撞检测、路径裁剪。

javascript 复制代码
/**
 * 判断两条线段是否相交
 */
function isSegmentsIntersect(a1, a2, b1, b2) {
  // 向量叉乘计算
  function cross(p1, p2, p0) {
    return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
  }

  const d1 = cross(b1, b2, a1);
  const d2 = cross(b1, b2, a2);
  const d3 = cross(a1, a2, b1);
  const d4 = cross(a1, a2, b2);

  // 跨立实验(快速判断)
  if (d1 * d2 < 0 && d3 * d4 < 0) return true;
  
  return false;
}

四、贝塞尔曲线点判断

直接用 Canvas 原生 API,手写算法复杂且没必要:

javascript 复制代码
// 绘制二次贝塞尔曲线
ctx.beginPath();
ctx.moveTo(50,50);
ctx.quadraticCurveTo(100,100, 150,50);
ctx.lineTo(150,100);
ctx.lineTo(50,100);
ctx.closePath();

// 判断点是否在曲线围成的区域内
ctx.isPointInPath(x, y);

面试回答万能模板(背这个)

面试官问:如何判断点在 Canvas 闭合图形内?

标准回答:

  1. 对于多边形,我使用射线法:从点向右发射水平射线,统计与边的相交次数,奇数在内、偶数在外;
  2. 对于圆形,用距离公式判断点到圆心距离是否小于半径;
  3. 实际开发中,我优先使用 Canvas 原生 isPointInPath(),支持所有路径(多边形、圆弧、贝塞尔曲线),性能最优、代码简洁。

总结

  1. 核心必考:射线法判断点在多边形内 + isPointInPath 原生 API;
  2. 基础算法:点圆、点矩形、矩形碰撞、线段相交;
  3. 面试技巧:先讲原理,再写代码,最后提原生 API 优化。
相关推荐
MediaTea1 小时前
AI 术语通俗词典:F1 值(分类)
人工智能·算法·机器学习·分类·数据挖掘
望舒3292 小时前
KMP算法
数据结构·算法
潇楠Web3哨兵2 小时前
桌面级Web3交易终端的底层炼狱:自研多源报价引擎、移除重型依赖、跨进程钱包桥接与强制安全拦截
算法·web3
贾斯汀玛尔斯2 小时前
每天学一个算法--回溯算法(Backtracking)
算法
cpp_25012 小时前
P2871 [USACO07DEC] Charm Bracelet S
数据结构·c++·算法·动态规划·题解·洛谷·背包dp
CoderCodingNo2 小时前
【CSP】CSP-J 2019 江西真题 | 面积 luogu-P5681 (适合GESP一级、二级考生练习)
算法
Mr_pyx2 小时前
【LeetHOT100】合并两个有序链表——Java多解法详解
算法
yu85939583 小时前
利用MATLAB进行木材图像去噪
开发语言·算法·matlab
cpp_25013 小时前
P2722 [USACO3.1] 总分 Score Inflation
数据结构·c++·算法·动态规划·题解·洛谷·背包dp