|
| 1 | +# An Infinite Canvas Tutorial |
| 2 | + |
| 3 | +What is an Infinite Canvas? The term "infinite" in [infinitecanvas] is described as follows: |
| 4 | + |
| 5 | +- High scalability. Users can freely organize content structures in a non-linear fashion. |
| 6 | +- Zooming. Emulates the "zoom in" to get an overview and "zoom out" to observe details as in the real world. |
| 7 | +- Direct manipulation. Provides intuitive editing capabilities for basic shapes, including moving, grouping, and modifying styles. |
| 8 | + |
| 9 | +The [infinitecanvas] showcases numerous examples ranging from design tools to creative boards, including some well-known products such as: [Figma], [Modyfi], [rnote], [tldraw], [excalidraw] and so on. |
| 10 | + |
| 11 | +As a front-end developer, I am very interested in the rendering technologies involved. Although tldraw, excalidraw, and others generally use more user-friendly technologies like Canvas2D/SVG, there are also many editors and design tools in the JS and Rust ecosystems that use more low-level rendering technologies for 2D graphics with GPU acceleration to achieve better performance and experience: |
| 12 | + |
| 13 | +- [Figma] uses a tile-based rendering engine written in C++, compiled into WASM and then calls WebGL for rendering. |
| 14 | +- [Modyfi] uses [wgpu] from the Rust ecosystem, also compiled into WASM and then calls WebGL2 for rendering. |
| 15 | +- [Zed] uses GPUI to render rectangles, shadows, text, images, and other UI elements. |
| 16 | +- [Vello] and [xilem] experimentally use Compute Shader for 2D rendering. |
| 17 | + |
| 18 | +Therefore, in this tutorial, I hope to implement the following features: |
| 19 | + |
| 20 | +- Use [@antv/g-device-api] as a hardware abstraction layer, supporting WebGL1/2 and WebGPU. |
| 21 | +- Referencing [mapbox] and [Figma], attempt to use tile-based rendering. |
| 22 | +- Use SDF (Signed Distance Field) rendering for circles, ellipses, rectangles, etc. |
| 23 | +- GPU-accelerated text and Bezier curve rendering. |
| 24 | +- Use [rough.js] to support hand-drawn styles. |
| 25 | +- Use CRDT (Conflict-free Replicated Data Type) to support collaborative [Yjs]. |
| 26 | + |
| 27 | +I hope to rewrite the rendering part of the canvas with Rust in the future, but the current project completion is still relatively low: |
| 28 | + |
| 29 | +- [wgpu] is a very reliable hardware abstraction layer, which can even implement the backend for [piet]. |
| 30 | +- Shaders can basically be reused. |
| 31 | +- Hand-drawn styles can use [rough-rs]. |
| 32 | +- [y-crdt] is the Rust implementation of [Yjs]. |
| 33 | + |
| 34 | +Let's get started! |
| 35 | + |
| 36 | +## Getting Started |
| 37 | + |
| 38 | +The course project uses pnpm workspace, so you need to install pnpm first. |
| 39 | + |
| 40 | +```bash |
| 41 | +pnpm i |
| 42 | +``` |
| 43 | + |
| 44 | +After entering the course directory, run [vite]: |
| 45 | + |
| 46 | +```bash |
| 47 | +cd packages/lesson_001 |
| 48 | +pnpm run dev |
| 49 | +``` |
| 50 | + |
| 51 | +## Lesson 1 |
| 52 | + |
| 53 | +In Lesson 1, we will introduce: |
| 54 | + |
| 55 | +- A hardware abstraction layer based on WebGL1/2 and WebGPU. |
| 56 | +- Canvas API design. |
| 57 | +- Implementing a simple plugin system. |
| 58 | +- Implementing a rendering plugin based on the hardware abstraction layer. |
| 59 | + |
| 60 | +[infinitecanvas]: https://infinitecanvas.tools/ |
| 61 | +[Figma]: https://madebyevan.com/figma/building-a-professional-design-tool-on-the-web/ |
| 62 | +[Modyfi]: https://digest.browsertech.com/archive/browsertech-digest-how-modyfi-is-building-with/ |
| 63 | +[rnote]: https://github.com/flxzt/rnote |
| 64 | +[tldraw]: https://github.com/tldraw/tldraw |
| 65 | +[excalidraw]: https://github.com/excalidraw/excalidraw |
| 66 | +[rough.js]: https://github.com/rough-stuff/rough |
| 67 | +[rough-rs]: https://github.com/orhanbalci/rough-rs |
| 68 | +[zed]: https://zed.dev/blog/videogame |
| 69 | +[wgpu]: https://wgpu.rs/ |
| 70 | +[vello]: https://github.com/linebender/vello |
| 71 | +[xilem]: https://github.com/linebender/xilem |
| 72 | +[piet]: https://github.com/linebender/piet |
| 73 | +[@antv/g-device-api]: https://github.com/antvis/g-device-api |
| 74 | +[mapbox]: https://blog.mapbox.com/rendering-big-geodata-on-the-fly-with-geojson-vt-4e4d2a5dd1f2?gi=e5acafcf219d |
| 75 | +[Yjs]: https://yjs.dev/ |
| 76 | +[y-crdt]: https://github.com/y-crdt/y-crdt |
0 commit comments