What is an Infinite Canvas? The term "infinite" in infinitecanvas is described as follows:
- High scalability. Users can freely organize content structures in a non-linear fashion.
- Zooming. Emulates the "zoom in" to get an overview and "zoom out" to observe details as in the real world.
- Direct manipulation. Provides intuitive editing capabilities for basic shapes, including moving, grouping, and modifying styles.
The infinitecanvas showcases numerous examples ranging from design tools to creative boards, including some well-known products such as: Figma, Modyfi, Motiff, rnote, tldraw, excalidraw and so on.
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:
- Figma uses a tile-based rendering engine written in C++, compiled into WASM and then calls WebGL for rendering.
- Motiff also uses a tile-based rendering engine with WebGL.
- Modyfi uses wgpu from the Rust ecosystem, also compiled into WASM and then calls WebGL2 for rendering.
- Zed uses GPUI to render rectangles, shadows, text, images, and other UI elements.
- Vello and xilem experimentally use Compute Shader for 2D rendering.
Therefore, in this tutorial, I hope to implement the following features:
- Use @antv/g-device-api as a hardware abstraction layer, supporting WebGL1/2 and WebGPU.
- Referencing mapbox and Figma, attempt to use tile-based rendering.
- Use SDF (Signed Distance Field) rendering for circles, ellipses, rectangles, etc.
- GPU-accelerated text and Bezier curve rendering.
- Use rough.js to support hand-drawn styles.
- Use CRDT (Conflict-free Replicated Data Type) to support collaborative Yjs.
I hope to rewrite the rendering part of the canvas with Rust in the future, but the current project completion is still relatively low:
- wgpu is a very reliable hardware abstraction layer, which can even implement the backend for piet.
- Shaders can basically be reused.
- Hand-drawn styles can use rough-rs.
- y-crdt is the Rust implementation of Yjs.
Let's get started!
The course project uses pnpm workspace, so you need to install pnpm first.
pnpm iAfter entering the course directory, run Vite devserver:
cd packages/lesson_001
pnpm run devOr you can run the site locally:
pnpm run build
cd packages/site
pnpm run devLesson 1 - Initialize canvas π
- A hardware abstraction layer based on WebGL1/2 and WebGPU.
- Canvas API design.
- Implementing a simple plugin system.
- Implementing a rendering plugin based on the hardware abstraction layer.
Lesson 2 - Draw a circle π
- Adding shapes to the canvas.
- Drawing a circle using SDF.
- Anti Aliasing.
- Dirty flag design pattern.
Lesson 3 - Scene graph and transform π
- Transformations. Make shapes support pan, zoom, rotate, and skew transformations.
- Scene graph.
Lesson 4 - Camera π
- What is a Camera?
- Projection transformation.
- Camera transformation.
- Camera animation. Using Landmark transition between different camera states.
Lesson 5 - Grid π
- Drawing straight lines using Line Geometry or screen-space techniques.
- Drawing dots grid.
- Drawing wireframe for Geometry.
| Grid | Wireframe |
|---|---|
![]() |
![]() |
Lesson 6 - Event system π
- Implement an event system compatible with DOM Event API.
- How to pick a circle.
- Implement a drag-and-drop plugin based on our event system.
- Support for pinch zoom gestures.
Lesson 7 - Web UI π
- Developing Web UI with Lit and Shoelace
- Implementing a canvas component
- Implementing a zoom toolbar component
- Implementing a dark theme
Lesson 8 - Optimize performance π
- What is a draw call
- Reducing draw calls with culling
- Reducing draw calls by combining batches
- Using spatial indexing to improve pickup efficiency
Lesson 9 - Draw ellipse and rectangle π
- How to derive the SDF representation of an ellipse or rounded rectangle
- Render drop-shadow and inner shadow for SDF
- How to determine if a point is inside an ellipse or rounded rectangle
| Drop Shadow | Inner Shadow |
|---|---|
![]() |
![]() |
Lesson 10 - Import and export images π
- Exporting canvas content to PNG, JPEG and SVG formats
- Rendering images in the canvas
- Extending the capabilities of SVG, using
stroke-alignmentas an example
Lesson 11 - Test and server-side rendering π
- Jest-based test environment setup, including local and CI environments
- Using unit tests to improve code coverage
- Visual regression testing
- Server-side rendering based on headless-gl, targets WebGL1
- E2E testing base on Playwright, targets WebGL2 & WebGPU
- E2E UI testing
- Browser Compatibility Test based on BrowserStack
- Render in WebWorker
Lesson 12 - Draw polyline π
- Why not just use
gl.LINES? - Building Mesh in the CPU or Shader
- Building segments, caps and joints, antialiasing, and drawing dashed lines in shader
- How to calculate its bounding box?
Lesson 13 - Draw path and hand-drawn shapes π
- Experimenting with SDF
- Trying to draw fills using some triangulating methods and strokes using polylines
- Support earcut and libtess.js two triangulation schemes
- Handle holes in the path correctly
- Support
fillRuleproperty
- Draw some hand-drawn shapes
| Path and rough shapes | Fill rule |
|---|---|
![]() |
![]() |
Lesson 14 - Canvas mode and auxiliary UI π
- Implement
zIndexandsizeAttenuation - Add more canvas modes, e.g. move and select and shapes
Lesson 15 - Draw text π
- What's TextMetrics and how to get it in server and browser side
- What's shaping? Implement letterSpacing and kerning
- Paragraph layout
- Auto wordbreak
- BiDi
- Handle clusters
- Support text-align
- How to generate SDF atlas and use it to draw
- How to use ESDT and MSDF to improve text rendering quality
- How to draw bitmap font
- How to draw emoji
Lesson 16 - Advanced text features π
- Using Bezier curves to render text, shaping with OpenType and Harfbuzz
- Render TeX math
- Text decoration and dropshadow
- Physical text rendering
- Load web font with web font loader
Lesson 17 - Gradient and Pattern π
- Use CanvasGradient to implement gradients
- Imperative. Create textures using the Device API
- Declarative. Supports CSS gradient syntax:
linear-gradient,radial-gradient,conic-gradient - Use Shoelace to implement gradient configuration panel
- Use Shader to implement Mesh Gradient
- Simulate random
- Value Noise and Gradient Noise
- Voronoi, FBM and Domain Warping
- Export SVG
- Use CanvasPattern to implement repeating patterns
| Linear, Radial, Conic Gradient | Mesh Gradient |
|---|---|
![]() |
![]() |
Lesson 18 - Refactor with ECS π
- What is ECS architecture
- Using ECS architecture to refactor the application
Lesson 19 - History and Collaboration π
- Implement a simple history system, including undo and redo
- Implement collaboration through CRDT

















