曼德博集合(Mandelbrot)

由 Rust + WebAssembly 驱动

🖱️ 滚轮 缩放  |  🖱️ 拖拽 平移  |  单击 居中

📖 原理说明

曼德博集合是复平面上所有使迭代 zn+1 = zn² + c(从 z0 = 0 开始)始终不发散的点 c 的集合。它的边界无限复杂,无论放大多少倍都能看到新的细节。

🧮算法原理

zn+1 = zn² + c逃逸条件:|z|² > 4
逃逸时间算法
画布上每个像素对应一个复数 c。反复迭代,一旦 |z|² > 4(即 |z| > 2)就可以断定它必然发散,记下此时的迭代次数;达到最大迭代次数仍未逃逸的点视为属于集合,画成黑色。
平滑着色
直接用整数迭代次数上色会出现一圈圈色带。代码使用归一化迭代次数 n + 1 − ln(ln|z|²) / ln 2 得到连续值,再映射到 HSV 色相,颜色过渡更平滑。
自适应迭代深度
放大后边界细节需要更多次迭代才能分辨,最大迭代次数随缩放倍数增长:256 × log₂(zoom + 1),限制在 64 ~ 2048 之间。

🔄Rust 与 JavaScript 的分工

  1. JSJS 处理鼠标滚轮、拖拽、点击,维护视野中心和缩放倍数。
  2. JSJS 调用 mandelbrot_set(宽, 高, 最大迭代, 中心x, 中心y, 缩放)。
  3. RustRust 逐像素计算,返回 宽 × 高 × 4 字节的 RGBA 数组(Vec<u8>)。
  4. JSJS 把数组包装成 ImageData,用 putImageData() 一次性画到 Canvas。

⚡性能要点

  • 每个像素的计算互不依赖,是典型的计算密集型任务:画布最大 800×800,也就是 64 万个像素,每个像素最多迭代上千次。
  • 这种紧凑的 f64 循环在 WASM 中运行时没有垃圾回收停顿和类型检查开销,适合交给 Rust。
  • JS 和 WASM 之间每帧只传递一次整块像素数据,避免逐像素跨边界调用。

源码crates/graphics/mandelbrot/src/lib.rswww/mandelbrot/index.js