My free course in Gumroad. Feel free to rate!
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 and WebGPU 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.
- Use Becsy to implement high-performance, highly scalable systems based on the ECS architecture.
- 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.
- Referencing mapbox and Figma, attempt to use tile-based rendering.
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 devIf you want to use it in your own project, you can refer to:
Lesson 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 sketchy style π
- 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 - Text rendering π
- 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, arabic shaping included
- 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
| Render text with SDF atlas | Bitmap font, emoji, BiDi and clusters |
|---|---|
![]() |
![]() |
Lesson 16 - Text advanced features π
- Using Bezier curves to render text, shaping with OpenType and Harfbuzz
- Render TeX math
- Text stroke, decoration, dropshadow and text along path
- Physical text rendering
- Load web font with web font loader
| Shaping TeX with MathJax | Physical text |
|---|---|
![]() |
![]() |
| Text decoration | Text stroke |
|---|---|
![]() |
![]() |
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
- Server-side rendering in AWS lambda function
- 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 with Becsy
- Using Spectrum to implement UIs instead of shoelace
| Top nav and zoom toolbar | Layers and properties panels |
|---|---|
![]() |
![]() |
Lesson 19 - History π
- Implement a simple history system, including undo and redo
Lesson 20 - Collaboration π
- Implement collaboration through CRDT
Lesson 21 - Transformer π
- Resize, lock aspect ratio and centered scaling
- Rotate and change the rotation origin
- Nudge shapes with arrow key
| Rotate anchor | Resize anchor |
|---|---|
![]() |
![]() |
Lesson 22 - VectorNetwork π
- Limitations of SVG Path
- What is VectorNetwork
Lesson 23 - Mindmap π
- Analyze d3-tree, d3-flextree and @antv/hierarchy
| D3 flextree | Mindmap |
|---|---|
![]() |
![]() |
Lesson 24 - Context menu and clipboard π
- How to implement context menu with Spectrum
- Adjust z-index with bring forward and send back
- Writes and reads clipboard content, supports pasting serialized graphics, non-vector images, SVG and plain text
- Drag-and-drop import of image files from file systems and pages
| Context menu | Drag'n'drop image |
|---|---|
![]() |
![]() |
Lesson 25 - Draw rect mode and brush π
- Draw shapes mode: draw rect, ellipse, line and arrow with dragging
- Brush mode
| Draw rect mode | Pencil tool | Draw arrow |
|---|---|---|
![]() |
![]() |
![]() |
Lesson 26 - Selection tools π
- Single and multi-selection with Shift keypress
- Marquee selection
- Lasso tool
Lesson 27 - Snap and alignment π
- Snap to pixel grid
- Snap to objects
| Snap to pixel grid | |
|---|---|
![]() |
Lesson 28 - Integrating with AI π
- Common post-processing
- Integrating with AI
- Use chatbox
- Use Nano banana to edit image, e.g remove background
- Use SAM with WebGPU

































