可视化热门面试题
使用说明
本篇共 54 道题。
可视化面试会同时考数据表达、渲染技术和交互性能。回答先说明数据规模、图形类型和交互要求,再选 SVG、Canvas 或 WebGL。
Q1: 数据可视化的核心目标是什么?
答案:
把数据关系映射为人能准确、快速理解的视觉编码,帮助比较、发现趋势、分布、异常和关系,而不是单纯把页面做得炫。
图表类型要匹配问题,保留必要上下文和不确定性,避免截断坐标轴、面积误导和过多装饰。
- 先明确用户任务是比较、趋势、分布、组成还是关系,再选视觉编码;位置和长度通常比面积、角度和颜色更容易精确比较。
- 图表必须保留单位、基线、样本和不确定性,避免 3D、截断坐标轴或过度动画制造错误结论。
Q2: 常见视觉编码的准确性如何?
答案:
通常位置和长度最容易准确比较,角度、面积、颜色强度和体积更难做精确判断。
因此精确比较优先条形图/点图而不是饼图和 3D 图。颜色更适合分类或范围提示,并考虑色觉差异。
- 定量比较的准确性通常是共同尺度上的位置最高,其次是长度/角度,再到面积、颜色深浅和体积;分类数据可用位置、形状和色相。
- 颜色还要考虑色觉差异与屏幕环境。需要精确读取时配合标签、Tooltip 或表格,而不是让用户仅凭颜色猜数值。
Q3: SVG 和 Canvas 怎么选?
答案:
| 维度 | SVG | Canvas |
|---|---|---|
| 渲染方式 | 保留模式(DOM 树) | 即时模式(像素绘制) |
| 事件处理 | 原生 DOM 事件 | 需手动实现命中检测 |
| 性能 | 元素 < 1000 | 可渲染数万图形 |
| 缩放 | 无损缩放(矢量) | 放大失真 |
| 动画 | CSS/SMIL/WAAPI | requestAnimationFrame |
| 可访问性 | 支持(ARIA、title) | 不支持 |
| 适用场景 | 图标、简单图表、交互多 | 大数据量、动画、游戏 |
选择建议:
- 数据量 < 1000、需要丰富交互 → SVG
- 数据量 > 1000、频繁动画更新 → Canvas
- 3D 场景、超大数据量 → WebGL
- 详见 Canvas 与 SVG
Q4: Canvas 为什么会模糊?
答案:
CSS 展示尺寸与 Canvas 内部像素尺寸不一致,尤其在高 DPR 屏幕上,浏览器会拉伸低分辨率位图。
按 CSS 尺寸乘 devicePixelRatio 设置画布像素,再缩放绘图坐标,同时限制超高 DPR 带来的内存和绘制成本。
Q5: Canvas 如何做事件命中检测?
答案:
Canvas 没有每个图形的 DOM 事件,需要把指针坐标转换到画布坐标,再用几何判断、空间索引、隐藏颜色拾取或 Path2D 判断命中。
数据量大时使用四叉树/R-tree 缩小候选集合,并处理变换矩阵、DPR 和命中容差。
- 先把 pointer 坐标从 CSS 像素转换到 Canvas 内部坐标,再通过当前 Transform 的逆矩阵还原到世界坐标。
- 少量图形可用几何/Path2D 判断,大量对象先用四叉树或 R-tree 筛候选;颜色拾取适合复杂形状,但要处理 DPR、抗锯齿和命中容差。
Q6: Transform 矩阵在可视化中有什么作用?
答案:
二维仿射矩阵可以统一表示平移、缩放、旋转和斜切。多个变换可以通过矩阵乘法组合,场景图只需维护父子矩阵,就能把局部坐标逐层转换到世界坐标和屏幕坐标。
常见用途:
- Zoom/Pan 时统一变换整张图。
- 图元使用局部坐标,父节点负责整体布局。
- 命中检测时使用逆矩阵把指针的屏幕坐标还原到图元局部坐标。
- 导出、动画插值和 GPU Shader 共享同一变换语义。
矩阵乘法有顺序,先平移后旋转与先旋转后平移结果不同;还要统一行/列向量约定、DPR 和坐标原点。
Q7: D3 的数据绑定是什么?
答案:
它把数据项与 DOM 元素关联,并通过 enter/update/exit 描述新增、更新和退出集合,让图形随数据声明式变化。
稳定 key 能正确跟踪对象。现代 D3 的 join API 可简化流程,但仍要理解三种集合的含义。
- D3 根据 key 把旧节点和新数据分为 update、enter、exit 三组:已有节点更新,新数据创建节点,失效数据移除。
selection.join()简化了写法,但稳定 key 仍决定动画和节点状态是否正确延续;索引 key 在排序后会造成错误复用。
Q8: 比例尺和坐标轴有什么区别?
答案:
比例尺是数据域到视觉范围的映射函数,例如线性、时间、对数和分类型;坐标轴是比例尺的可视化表现,生成刻度、标签和轴线。
选择比例尺要符合数据语义,对数轴不能直接处理非正值,也要明确告知用户。
- 比例尺是纯映射,例如把时间域映射到像素范围;坐标轴只是读取比例尺,生成刻度、标签和轴线。修改轴不会改变数据映射。
- 选择线性、对数、时间或 band scale 要符合数据语义,并处理零值、负值、时区和刻度密度。
Q9: ECharts 的核心使用模型是什么?
答案:
通过声明式 option 描述数据、坐标系、系列、视觉和交互,ECharts 负责数据处理、布局、渲染和增量更新。
复杂项目应封装业务配置与主题,而不是复制巨大 option;更新时控制合并策略和对象稳定性。
- ECharts 的
option是声明式模型,series、dataset、axis、visualMap 和组件共同描述图表;setOption负责差量合并和渲染。 - 业务封装应稳定数据标识并控制
notMerge/replaceMerge,统一主题、空态和事件清理,避免每次更新都销毁重建实例。
Q10: SVG/Canvas 图表如何做响应式?
答案:
监听容器尺寸而不是只监听 window,重新计算布局、比例尺和画布像素;可用 ResizeObserver,并防止更新反馈循环。
窄屏不只是等比缩小,还可能需要减少刻度、调整图例、滚动或切换图形。
- 用 ResizeObserver 监听实际容器,重新计算绘图区、比例尺和标签密度;Canvas 同时更新 CSS 尺寸与 DPR 像素,SVG 更新 viewBox 或布局。
- 小屏不一定等比缩放,常需隐藏次要标签、调整图例、允许横向滚动或切换更合适的图形。
Q11: WebGL 渲染管线大致是什么?
答案:
CPU 准备顶点和状态,顶点着色器处理顶点,图元组装与光栅化生成片元,片元着色器计算颜色,再经过深度、混合写入帧缓冲。
性能关键是减少 Draw Call、状态切换和数据上传,让 GPU 批量处理。
- CPU 上传顶点属性、索引和纹理并设置状态;顶点着色器变换顶点,图元组装后光栅化为片元,片元着色器计算颜色,再经过深度、模板和混合测试写入帧缓冲。
- 性能分析要看 Draw Call、状态切换、Buffer 上传、过度绘制和填充率,不能只看顶点数量。
Q12: 为什么 WebGL 适合大量图元?
答案:
数据放入 GPU Buffer 后,着色器可并行处理大量顶点/片元,并通过批处理和实例化减少 CPU 与 GPU 往返。
瓶颈仍可能是填充率、显存、过度绘制和数据更新。少量普通图形使用 WebGL 可能得不偿失。
- 顶点数据进入 GPU Buffer 后,GPU 可并行执行同一着色器;批处理、实例化绘制和纹理图集能显著减少 CPU 提交开销。
- 如果每帧重新上传大量数据或产生过多 Draw Call,WebGL 仍会卡;静态数据应复用 Buffer,动态数据按变化范围更新。
Q13: 百万数据点如何渲染?
答案:
先判断是否有必要同时展示全部点,再做抽样/聚合、LOD、视口裁剪和空间索引;渲染层选择 Canvas/WebGL 并批处理。
交互查询使用索引或离屏拾取,计算放 Worker。性能优化不能以隐藏异常或扭曲分布为代价。
- 第一问应是“用户是否真的需要同时看一百万个点”。通常先按像素聚合、抽样或 LOD,再做视口裁剪与空间索引。
- 渲染用 Canvas/WebGL 批处理,计算放 Worker,交互用索引或 GPU picking。抽样必须保留异常与分布特征,并向用户说明聚合尺度。
Q14: 图表动画如何保证性能和信息价值?
答案:
动画应帮助用户理解状态变化,控制时长、数量和同时运动对象,使用 rAF 并优先更新合成友好的属性或在 Canvas/WebGL 中批量重绘。
尊重 prefers-reduced-motion,数据高频更新时降采样或直接切换,避免动画积压。
Q15: 地图可视化要注意什么?
答案:
处理坐标系与投影、GeoJSON 体积、瓦片、缩放层级和空间查询。经纬度不能直接当平面距离,跨日期变更线也要处理。
热力图和面积着色要按人口/面积等分母标准化,否则容易误导。
- 先确认坐标系和投影,Web Mercator 上的像素距离不等于真实地理距离;跨日期变更线、极区和行政边界也需特别处理。
- 大数据使用瓦片、分层和视口查询。分级设色要按人口或面积归一化,热力图参数和颜色范围保持可解释,避免大区域天然显得更重要。
Q16: 关系图为什么容易卡顿?
答案:
力导向布局计算、边数量、标签、命中和频繁全量重绘都会增长。可在 Worker 计算布局,聚类/裁剪边,分层渲染并限制迭代。
更重要的是先简化信息结构,大型“毛线团”即使渲染流畅也不可读。
- 力导向布局本身要多轮迭代,边数量可能接近平方增长;标签、命中和每帧全量重绘又叠加主线程压力。
- 可聚类和按层级展开,裁剪非关键边,在 Worker 计算布局、Canvas/WebGL 分层渲染,并在稳定后降低或停止迭代。
Q17: 如何封装通用图表组件?
答案:
抽象数据 Schema、尺寸、主题、空/错/加载状态、事件和可访问性,保留合理扩展点,但不要直接把底层库所有 option 原样暴露。
组件要处理 Resize、销毁、更新合并、截图和测试,并通过真实业务场景验证抽象。
- 通用层封装容器尺寸、实例生命周期、主题、加载/空态/错误态和事件清理;业务层只提供稳定的数据模型与少量语义配置。
- 不要把整个 option 暴露后又声称“统一封装”。API 应支持受控扩展,并通过快照、视觉回归和真实大数据验证更新性能。
Q18: 图表如何做好可访问性?
答案:
提供明确标题、摘要、单位和数据表/下载替代,保证颜色对比和非颜色编码,键盘能访问关键点,并对动态变化给适度提示。
Canvas/WebGL 不具有节点语义,尤其需要额外 DOM 描述。不是给整个图加一个 aria-label 就完成。
- 提供等价标题、摘要、数据表或可下载数据,让屏幕阅读器不依赖像素理解信息;SVG 节点可补 role、label 和合理焦点顺序。
- 交互同时支持键盘,颜色不是唯一编码,并遵循对比度和 reduced motion。高频 Tooltip 变化要避免让
aria-live持续打扰用户。
Q19: 可视化的数据转换层为什么不应写进渲染组件?
答案:
过滤、聚合、排序、堆叠、分箱和降采样属于数据语义;SVG/Canvas/WebGL 属于渲染实现。把两者混在组件中,会让同一指标在不同图表重复计算,也难以测试和切换渲染器。
更好的结构是:
- 原始数据先经过可测试的纯转换管线。
- 输出统一的图形数据模型和稳定 ID。
- 渲染层只负责比例尺、布局、绘制和交互。
- 大数据转换可缓存、增量计算或放到 Worker。
- Tooltip 和导出复用同一语义结果,避免口径不一致。
Q20: OffscreenCanvas 适合解决什么问题?
答案:
OffscreenCanvas 允许在 Worker 中创建或接管 Canvas 绘制,把部分绘图和计算移出主线程,适合大图表、图片处理和持续动画。
它的收益依赖场景:DOM 事件和布局信息仍在主线程,双方需要传递尺寸、输入和状态;频繁传大对象可能抵消并行收益。优先传递 ArrayBuffer 等 Transferable,并控制消息频率。
浏览器支持、字体、导出和 WebGL 上下文能力需要按目标环境验证。它不会自动让算法更快,只是提供线程隔离和调度空间。
Q21: SVG 的 viewBox 是什么?有什么作用?
答案:
viewBox 定义 SVG 的逻辑坐标系(用户坐标系),格式为 "minX minY width height"。它与实际显示尺寸(width/height 属性)配合,实现内容的自动缩放。配合 preserveAspectRatio 控制缩放行为。这使 SVG 天然支持响应式。
Q22: CSS transform 中的 matrix(a, b, c, d, e, f) 各参数含义?
答案:
对应 2D 仿射变换矩阵的 6 个参数:
a, d:缩放(水平/垂直方向)b, c:旋转和斜切e, f:平移(水平/垂直方向)
变换公式:,。单位矩阵是 matrix(1, 0, 0, 1, 0, 0),表示无变换。
Q23: 什么是 AABB?有什么优缺点?
答案:
AABB(Axis-Aligned Bounding Box)是轴对齐包围盒,即不旋转的矩形。判断两个 AABB 是否碰撞只需 4 次比较,。
优点:极其简单高效,适合宽相位预检测。 缺点:不支持旋转图形。对于旋转的或不规则的形状,AABB 包围盒会比实际图形大很多,产生大量误检(false positive),需要窄相位再次精确判断。
Q24: D3 的 Enter/Update/Exit 模式是什么?
答案:
这是 D3 数据绑定的核心机制。当数据数组与 DOM 元素绑定后:
- Enter:新数据没有对应 DOM → 需要创建新元素
- Update:数据和 DOM 都存在 → 需要更新属性
- Exit:DOM 没有对应数据 → 需要移除元素
D3 v7 用 join() 简化了这个模式。
Q25: ECharts 的 Canvas 和 SVG 渲染模式如何选择?
答案:
Canvas 适合大数据量(>1000 数据点)和频繁动画场景,SVG 适合小数据量、需要高清打印或无障碍支持的场景。通过 echarts.init(dom, null, { renderer: 'svg' }) 切换。
Q26: WebGL Instancing 为什么能减少 Draw Call?
答案:
普通绘制大量相同网格时,每个对象一次 Draw Call 会产生明显 CPU 到 GPU 的调用和状态切换成本。Instancing 让一次绘制复用同一套顶点/索引数据,并为每个实例提供位置、颜色、矩阵等属性。
它适合散点、粒子、重复图标和大量相同模型。实例属性通常设置 divisor,让 GPU 按实例而不是按顶点推进。
若每个对象材质和几何完全不同,Instancing 收益有限;还要关注实例 Buffer 更新、透明排序、拾取 ID 和单次批次过大带来的填充率问题。
Q27: 前端地图可视化技术如何选型?
答案:
轻量 2D → Leaflet;高质量 + 3D → Mapbox GL;国内项目 → 高德/腾讯;大数据量 → Deck.gl/L7;3D 地球 → CesiumJS。选型考虑:数据量、3D 需求、国内外、费用。
Q28: Canvas 的脏矩形重绘是什么?什么时候值得使用?
答案:
脏矩形记录一帧中真正变化的区域,只清除并重绘这些区域,而不是每帧重画整个画布。它适合背景稳定、局部对象移动且影响范围容易计算的 2D 场景。
实现步骤:
- 记录对象变化前后的包围盒,并扩展描边、阴影等影响范围。
- 合并重叠或相邻矩形,避免产生过多小区域。
- 清理合并后的区域,重绘与区域相交的对象。
- 用空间索引减少相交对象查询成本。
对象很多、全屏变化、透明叠加复杂或矩形合并成本过高时,全量重绘可能更快。是否使用要基于帧耗时和绘制面积实测。
Q29: 力导向布局的原理是什么?
答案:
模拟物理系统:所有节点之间有斥力(库仑力,防止重叠),有边连接的节点之间有引力(弹簧力,保持连接)。通过迭代模拟直到系统达到能量最低的平衡态。D3 用 Barnes-Hut 算法把 优化到 。
Q30: 什么是缓动函数?常用的有哪些?
答案:
缓动函数将线性时间进度 映射为动画进度,控制速度曲线。常用类型:linear(匀速)、easeOut(先快后慢,最常用)、easeIn(先慢后快)、easeInOut(两端慢中间快)、elastic(弹性)、bounce(弹跳)。CSS 中的 cubic-bezier() 就是三次贝塞尔缓动。
Q31: 数据大屏如何做屏幕适配?
答案:
最常用的是 scale 等比缩放方案:按设计稿尺寸(如 1920x1080)开发,运行时计算屏幕与设计稿的缩放比,对整个容器应用 CSS transform: scale()。优点是实现简单、保持比例不变形;缺点是可能有留白。其他方案包括 vw/vh + rem、CSS Grid 响应式布局。
Q32: 如何封装一个通用的 ECharts React 组件?
答案:
核心要点:(1) useRef 持有容器 DOM 和 ECharts 实例;(2) useEffect 中 init/dispose 管理实例生命周期;(3) ResizeObserver 监听容器尺寸变化自动 resize;(4) option 变化时用 setOption 更新;(5) 支持事件绑定和 Loading/Empty 状态。
Q33: 低代码可视化搭建的核心技术是什么?
答案:
- Schema 驱动:用 JSON 描述页面结构和组件配置
- 拖拽引擎:Pointer Events 实现拖放、缩放、对齐
- 组件注册表:动态注册和渲染不同图表类型
- 属性面板:根据组件 Schema 动态生成配置表单
- 渲染引擎:将 Schema 解析为实际组件树
Q34: 什么是视觉编码?如何选择合适的视觉通道?
答案:
视觉编码是将数据维度映射到图形的视觉属性。选择原则:
- 精确度优先:定量数据用位置 > 长度 > 角度 > 面积
- 类别区分:分类数据用颜色色相 > 形状 > 纹理
- 认知负荷:同时使用的视觉通道不宜超过 3-4 个
- 冗余编码:重要信息用多种通道同时编码(如颜色+标签)
Q35: Canvas 绘制文字为什么要等待字体加载?
答案:
Canvas 不保存文字 DOM。调用 fillText 时若目标 Web Font 尚未就绪,浏览器可能先用回退字体绘制;字体后来加载也不会自动重绘 Canvas,导致字形和测量宽度不一致。
可通过 document.fonts.load() 或 document.fonts.ready 等待关键字体,再重新测量和绘制。字体失败时要有明确回退,并避免为了所有字重阻塞首屏。
文本换行仍需应用根据 measureText 自己实现;国际化还要考虑字形、方向、Emoji 和设备像素比。
Q36: SVG 路径的 d 属性如何理解?
答案:
d 属性包含一系列绘图命令:M(移动)、L(直线)、C/Q(贝塞尔曲线)、A(圆弧)、Z(闭合)。大写为绝对坐标,小写为相对坐标。所有 SVG 基本形状(rect、circle 等)都可以转成 path 形式。
Q37: 如何实现绕任意点旋转?
答案:
三步:
- 将旋转中心平移到原点
translate(-cx, -cy) - 绕原点旋转
rotate(angle) - 平移回去
translate(cx, cy)
用矩阵表示:
CSS 的 transform-origin 正是简化了这个操作。在 Canvas 中需要手动实现:
ctx.translate(cx, cy);
ctx.rotate(angle);
ctx.translate(-cx, -cy);
SVG 的 rotate() 可以直接指定旋转中心:rotate(45, 100, 100)。
Q38: 什么是宽相位和窄相位?为什么要分两个阶段?
答案:
- 宽相位(Broad Phase):用简单快速的算法(AABB + 空间索引)快速筛掉绝大部分不可能碰撞的图形对。从 降到接近
- 窄相位(Narrow Phase):对宽相位筛选出的少量候选对,用精确算法(SAT、GJK 等)做最终判定
分两阶段的原因:精确算法比较耗时,如果对所有图形对都做精确检测,性能无法接受。宽相位用极低成本排除大部分无关图形对,让窄相位只处理少量候选。
Q39: D3 和 ECharts 的区别?如何选择?
答案:
| 维度 | D3.js | ECharts |
|---|---|---|
| 定位 | 底层可视化工具库 | 开箱即用的图表库 |
| 学习曲线 | 高 | 低 |
| 定制化 | 极高(自由绑定) | 中等(配置驱动) |
| 图表类型 | 需自己组合 | 内置 30+ 种 |
| 渲染方式 | 主要 SVG | Canvas/SVG 可选 |
| 大数据量 | 需自行优化 | 内置大数据优化 |
| 适用场景 | 高度定制化可视化 | 快速开发标准图表 |
Q40: ECharts 如何处理大数据量?
答案:
sampling: 'lttb':降采样算法,减少渲染点数large: true:开启大数据优化模式progressive:渐进式渲染,分帧绘制dataZoom:只展示可视区域数据appendData:增量追加数据dataset:统一数据管理,避免重复计算
Q41: Three.js 的核心概念有哪些?
答案:
Scene(场景容器)、Camera(相机,定义观察视角)、Renderer(渲染器,输出画面)、Mesh(网格体 = Geometry 几何体 + Material 材质)、Light(灯光)。渲染流程:创建场景 → 添加物体和灯光 → 设置相机 → 渲染循环。
Q42: GeoJSON 是什么?有哪些几何类型?
答案:
GeoJSON 是地理空间数据的 JSON 标准格式(RFC 7946)。几何类型:Point(点)、LineString(线)、Polygon(面)、Multi* 变体、GeometryCollection。Feature 包含 geometry 和 properties,FeatureCollection 是 Feature 数组。
Q43: 什么是 LTTB 降采样算法?
答案:
Largest-Triangle-Three-Buckets,将数据分桶后在每个桶中选择能与前后参考点形成最大三角形面积的点保留。这样在大幅减少数据点的同时保留了数据的视觉特征(极值、趋势),是 ECharts 内置的降采样算法。
Q44: 如何优化大规模图的渲染?
答案:
- 渲染层:Canvas/WebGL 替代 SVG
- 布局计算:Web Worker 或服务端计算
- LOD:远距离只显示节点,近距离显示标签和边
- 聚合:社区检测后合并密集子图
- 虚拟化:只渲染视口内节点
Q45: 可视化中的 Zoom & Pan 如何实现?
答案:
维护一个变换状态(translateX、translateY、scale)。滚轮控制缩放(以鼠标位置为中心)、拖拽控制平移。渲染前将变换应用到 Canvas context(setTransform 或 translate + scale)。鼠标坐标需通过逆变换映射到数据坐标。详见 Transform 变换与矩阵。
Q46: 大屏的实时数据如何处理?
答案:
用 WebSocket 推送实时数据,配合数据过渡动画平滑更新。非实时指标可用定时轮询。注意控制更新频率、做断线重连、长时间运行的内存管理。
Q47: 图表组件库的主题系统如何设计?
答案:
定义 ChartTheme 接口包含色板、背景色、文字色等 Design Token。提供预设主题(light/dark),支持自定义覆盖。通过 React Context 注入主题,将 Token 转换为底层图表库的配置(如 ECharts theme 对象)。配合 CSS 变量实现运行时切换。
Q48: 如何设计可视化搭建平台的 Schema?
答案:
页面 Schema 包含全局配置(尺寸、背景)和组件数组。每个组件 Schema 包含:type(组件类型)、props(属性配置)、position/size(位置尺寸)、dataSource(数据源配置)。Schema 需要支持序列化存储和版本管理。
Q49: WebGL Context Lost 是什么?应用怎样恢复?
答案:
GPU 重置、资源压力或驱动问题可能让 WebGL Context 丢失,之前创建的 Buffer、Texture、Program 等 GPU 资源失效,画布停止正常绘制。
应用应监听 webglcontextlost,阻止默认行为并暂停渲染;在 webglcontextrestored 后,从 CPU 侧数据重新创建所有 GPU 资源和状态。
因此重要纹理、几何和 Shader 来源要有可恢复描述,不能只存在 GPU 中。恢复期间显示降级 UI,并记录设备、驱动和资源规模,排查是否因过量纹理或 Context 数量导致。
Q50: 多指缩放和拖拽交互怎样统一处理?
答案:
优先使用 Pointer Events,把鼠标、触摸和触控笔统一成 pointer ID。单指移动可做 Pan,两指根据中心点和距离变化计算平移与缩放,并把屏幕坐标通过逆矩阵转换到世界坐标。
实现要点:
- 使用
setPointerCapture保持拖拽期间事件连续。 - 维护活跃 Pointer Map,正确处理
pointerup/cancel。 - 通过
touch-action明确哪些原生手势交给页面。 - 缩放围绕手势中心保持数据点不漂移。
- 对滚轮、键盘和无障碍提供等价操作。
不要同时混用 touch 和 mouse 监听导致重复触发。
Q51: 如何实现 SVG 描边动画?
答案:
利用 stroke-dasharray(线段间距)和 stroke-dashoffset(偏移量):先用 getTotalLength() 获取路径总长度,设置 dasharray 和 dashoffset 都等于总长度(隐藏),然后动画将 dashoffset 从总长度过渡到 0,产生"逐渐画出"的效果。
Q52: 什么是逆矩阵?在可视化中有什么用?
答案:
逆矩阵执行反向变换——如果矩阵 把点 变换到 ,那么 把 变回 。
最常见的用途是坐标转换:在缩放平移的画布中,鼠标点击的是屏幕坐标,但我们需要知道对应的数据坐标才能做命中检测。公式:
逆矩阵的计算依赖行列式 。当行列式为 0 时,矩阵不可逆(例如 scale(0) 把所有点压缩到了一条线上,无法恢复)。
Q53: 解释分离轴定理(SAT)的原理和步骤
答案:
SAT 的核心定理是:两个凸多边形不碰撞,当且仅当存在一条轴,使得两个多边形在该轴上的投影区间不重叠。
步骤:
- 收集所有候选分离轴(两个多边形所有边的法向量)
- 将两个多边形的所有顶点分别投影到每个候选轴上(用点积),得到两个区间 [min, max]
- 检查两个区间是否重叠
- 只要有任何一个轴上不重叠 → 不碰撞(短路返回);所有轴都重叠 → 碰撞
候选轴选择边法向量的原因:如果存在分离轴,它一定与某条边的法向量平行。
Q54: D3 的比例尺有哪些类型?
答案:
- 连续型:
scaleLinear(线性)、scalePow(幂)、scaleLog(对数)、scaleTime(时间) - 离散型:
scaleOrdinal(序数)、scaleBand(带宽度的分类)、scalePoint(点) - 颜色型:
scaleSequential(连续色)、scaleDiverging(发散色) - 分段型:
scaleQuantize(等分)、scaleQuantile(分位数)、scaleThreshold(阈值)