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 优化。
相关推荐
夜不会漫长16 分钟前
C++入门(1)
开发语言·c++·算法
wen_zhufeng1 小时前
IndexTTS 2.5 技术报告
人工智能·算法·机器学习
大熊背2 小时前
树莓派相机自动白平衡详解(四)
算法·树莓派·白平衡·isppipeline
一米阳光86612 小时前
软考(中级)软件设计师核心笔记(9)算法——背包问题
笔记·算法·职场发展·软考·软件设计师·中级职称
晚风醉蝶2 小时前
1-11-奇偶排序-OddEvenSort
java·数据结构·算法
旖旎夜光2 小时前
LeetCode 852:山脉数组的峰顶索引(二分查找) —— 题解
数据结构·c++·算法·leetcode·二分查找
..Dauntless..2 小时前
【C++】继承——基类和派生类的配合
开发语言·c++·算法
白露与泡影4 小时前
解密 Pi 的 Harness 工程:Agent 会话如何实现持久化与恢复
java·人工智能·算法
happyprince5 小时前
01-整体观-Codex全貌解读(源码)
算法·ai编程
俊基科技6 小时前
别自己写算法了,让这颗37.5毫米的模组替你“闭嘴干活”
神经网络·算法·硬件开发·ai降噪·语音模块·回音消除