Open-source project
leaferjs/LeaferJS avatar
leaferjs/LeaferJS

LeaferJS is a Canvas engine aimed at a million interactive shapes

好用的 Canvas 引擎,轻松构建可交互、可编辑的图形应用,AI 时代的无限画布引擎。An easy-to-use Canvas engine for building interactive and editable graphics applications — an infinite canvas engine for the AI era.

596 stars61 forksJavaScriptMIT

At a glance

What is it?
LeaferJS is a JavaScript and TypeScript graphics engine for building interactive and editable canvas applications, distributed as a set of sibling repositories around an integration repo, with a DOM-like API, Flex layout, an editor plugin and builds for web, Node.js and mini program targets. Its performance claims come with a stated test environment, and its editor features are partly commercial.
Who is it for?
Adopt LeaferJS if you are building an editor, whiteboard or diagram tool in the browser and you need high shape counts with drag and hit testing, because the scene tree, the DOM-like API and the built-in editor plugin cover much of what a Figma-style tool needs.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

An integration repo wrapped around a family of sibling repositories

The repository you land on is not the engine. The README states that this repository is the LeaferJS integration repository, which brings together the core engine and related extensions, and provides local development, running examples and custom packaging.

The actual pieces live in siblings, and the table of sub-repositories is the clearest map of the architecture:

| Repository | Role | | --- | --- | | leafer | the core engine | | leafer-ui | UI components and graphics capability | | leafer-in | official plugins | | leafer-draw | drawing scenarios | | leafer-game | game scenarios | | leafer-editor | editor scenarios |

A second table in the README widens that list with leafer-x for community plugin submissions, plus separate test, code, docs repositories. The main repository holds an index.ts entry file, a src directory, a public directory, a rollup.config.js, a vite.config.ts, a pnpm-workspace.yaml and a .gitmodules, and the package.json names the package leaferjs at version 2.3.1.

That structure is the first thing to understand when evaluating the project. You are not depending on one package, you are depending on a family, and the split between the core engine, the UI layer and the plugins is where the boundaries of your dependency lie.

The primary language is JavaScript with TypeScript used throughout the source, the licence is MIT, the default branch is main, and the last push was on 2026-10-13. The recent releases are v2.3.1 on 2026-10-09, v2.3.0 on 2026-09-28 and v2.2.11 on 2026-09-17.

The performance table, and what the test environment allows you to conclude

The README publishes a comparison table for one million interactive rectangles, with a stated test environment of a 2K screen laptop and Chrome V143.0, and the note that the data is for reference only and actual performance depends on the hardware.

| Test item (1 million interactive rectangles) | Traditional Canvas library | LeaferJS | Improvement | | --- | --- | --- | --- | | First screen creation speed | ~9-15 seconds | 1.28 seconds | about 8 times faster | | Memory usage | ~2-4GB, browser may crash | 320 MB | about 8 times less | | Single element drag frame rate | 0-4 FPS | 60 FPS | about 15 times smoother |

The third row is the one to read carefully, because it is not a throughput number. A drag frame rate of 0 to 4 FPS against 60 FPS says that in the traditional case, dragging a single element does not reach an interactive frame rate, while in LeaferJS it does. The first row is about how long the scene takes to exist, and the second is about the memory the browser is willing to hold before it gives up.

What the table does not establish is how the numbers behave on a different scene. A million rectangles is a specific shape: simple, uniform, easy to cull. A scene with ten thousand complex paths, a lot of text and heavy hit testing is a different workload, and nothing in the README describes how the engine behaves there.

There is also a benchmark site linked, benchmark.leaferjs.com, and a performance page, so the project does publish more than the summary table. The honest reading is that the engine is built for high shape counts, and the table is the author's measurement of that claim on a specific machine, not a general guarantee.

A DOM-like API, Flex layout and the editor plugin

The core capability list is where the design shows. There is a complete graphics system with a full scene tree structure, supporting vector graphics, SVG paths and pixel operations. There is native support for dragging, scaling and multi-touch, with millisecond-level hit testing. There is a modern layout engine, and the README highlights as rare in a Canvas engine a native Flex layout, so you can lay things out as you would in HTML. There are state-driven animations, with built-in high performance transitions and path animations. And there is a full cross-platform adaptation, one codebase running on web, Node.js, WeChat mini programs and mobile H5.

The editor support is the piece with a commercial edge. The built-in Editor plugin gives a one-click enablement of zoom, rotation, movement and multi-select for graphics. The README is explicit that this is one-click enabling of those capabilities, and the commercial section says PxGrow provides optional commercial plugins focused on complex business problems in industrial-grade applications, including a professional editor suite, complex graphics algorithms and performance optimisation capabilities. The MIT core is described as permanently open source, with the core functionality and basic plugins always open and free.

The small example in the README shows the shape of the API:

ts
import { Leafer, Rect } from 'leafer-ui'

const leafer = new Leafer({ view: window })

const rect = new Rect({
  x: 100,
  y: 100,
  width: 200,
  height: 200,
  fill: '#32cd79',
  draggable: true,
})

leafer.add(rect)

You construct a Leafer with a view, construct a Rect with geometry, a fill and a draggable flag, and add it to the tree. The API reads like a DOM because the project deliberately designed it that way, and the README's stated position is that developers building web graphics face a performance and usability trade-off, and that LeaferJS aims to end that trade-off by rebuilding from the bottom up for large scale, high density and very many layer productivity tools.

Running it locally, and the build targets behind the platform claims

The development loop is three commands, and the first one exists because the engine is split across repositories.

bash
git clone --recurse-submodules https://github.com/leaferjs/LeaferJS.git
cd LeaferJS

The --recurse-submodules option is what pulls in all the sub-repositories at once, and the same applies when you update:

bash
git pull --recurse-submodules

Then install the dependencies with npm install and start the development environment with npm run start, after which the browser opens on http://localhost:10101. To try an example, you copy the sample code from the LeaferJS site into index.ts and see it run live in the browser.

The package.json shows how the platform targets are wired. Every build is the same Rollup invocation with a different PLATFORM environment variable, and the scripts in the README are the ones the README documents:

| Command | What it does | | --- | --- | | npm run core | package the core code and its dependencies | | npm run web | package only the Web environment code | | npm run all | package the code for all environments | | npm run dts | generate TypeScript declaration files for all packages | | npm run clear | clean the build output |

The scripts list in the manifest shows the full set of platform values: core, web, worker, node, miniapp, draw and in, alongside dts, clear, all, test, update and start. The start script itself runs Rollup in watch mode with NODE_ENV=development, and the build scripts set PLATFORM and run Rollup without watch. Tests run under vitest, and the tooling around it is Rollup with the TypeScript, terser, commonjs, node-resolve, html and multi-entry plugins, plus a separate rollup-plugin-dts for the declaration output.

The pnpm workspace and the pinned pnpm 8.7.6 are the package manager story, and the repository is ESM, with type set to module and main pointing at index.ts.

The AI canvas argument, and where the commercial boundary sits

The README frames the project's motivation around a shift in what a graphics engine is for. In the era of generated content, the challenge has shifted from how to draw to how to orchestrate and refine, and three points follow from that.

The first is carrying capacity, described as a million interactive layers staying responsive so that AI generated fragments can be held. The second is semantic editing, where a structured scene tree lets an AI manipulate graphics the way it manipulates a DOM, and the README ties this to a Skills and Leafer AI knowledge base repository, an MCP entry, and an Ask AI entry.

The third is native editing, where the built-in Editor plugin gives AI generated content one-click precise rotation, scaling and multi-select. That is the same Editor plugin described earlier as part of the MIT core, and it is the feature that connects the engine to a workflow where a model produces a rough result and a human refines it.

The application scenarios the README lists are grouped as AI scenarios, productivity tools such as graphic editors, online design platforms, electronic whiteboards and low code engines, industrial visualisation with tens of thousands of nodes in power dispatch diagrams, flowcharts, asset monitoring and large topology graphs, digital content generation for batch images and posters, short video frame rendering on the Node.js side, and interactive applications such as lightweight games and high frequency data screens.

The commercial structure is worth being blunt about. The core engine and the basic plugins stay MIT, and PxGrow sells the professional editor suite, complex graphics algorithms and performance optimisations for industrial applications. So a team that wants the standard editing affordances can stay on the open source side, and a team that wants the industrial editor toolset is buying a separate product. That is a reasonable arrangement, and it is also a boundary to check early rather than after you have built on the free tier.

Where LeaferJS is the wrong tool

Three boundaries, and the first is about the rendering model itself.

The first is that a canvas engine is not an SVG document model. A canvas draws pixels, and everything you want to draw must be drawn by the engine, which means no text selection by the browser, no native accessibility semantics from the DOM for canvas content, and no ability to hand the result to another tool as a document. For a diagramming or whiteboard product where users expect to select text and copy it, that is a real constraint rather than a detail.

The second is that the multi-repository structure is a dependency risk, not just a documentation inconvenience. The engine, the UI layer and the plugins are separate packages with separate release cycles, and a mismatch between them is the kind of problem that surfaces as a rendering bug rather than a version conflict. The sub-repository table also means the set of packages you depend on is a decision you have to make deliberately, and the fact that some of the functionality is in the commercial plugins means the shape of your application can change depending on a commercial decision.

The third is that the platform breadth is a claim, not something the README demonstrates with specifics beyond the build scripts. There is a build target for the miniapp platform and for Node.js, and the marketing says one codebase runs on web, Node.js, WeChat mini programs and mobile H5, but the example given is a browser example, and the WeChat mini program target in particular has constraints around package loading and canvas support that the README does not discuss.

The alternative approach, and it is the obvious one, is to use SVG in the browser for a diagram or whiteboard product with a few thousand shapes, which gives you accessibility, text selection and a document model for free, and to reach for a canvas engine when the shape count or the frame budget genuinely demands it. The difference in approach is that LeaferJS is a canvas engine that adds a DOM-like API and an editor plugin to make canvas authoring practical, which is the right trade when you are building a Figma-style tool, and the wrong one if a modest diagram would have been fine in SVG.

Editorial conclusion

Adopt LeaferJS if you are building an editor, whiteboard or diagram tool in the browser and you need high shape counts with drag and hit testing, because the scene tree, the DOM-like API and the built-in editor plugin cover much of what a Figma-style tool needs. Do not adopt it expecting the full professional editor toolset for free, because the industrial editor suite and the advanced graphics and optimisation work sit in the commercial PxGrow plugins, and do not treat the performance table as a guarantee, since the README states the figures are for reference only and depend on the hardware. Verify first that the sibling repositories you actually need are published under the npm scope you plan to depend on, that the platform you target, web, Node.js, WeChat mini program or mobile H5, has a build script, and that your shape count and interaction model fit a canvas model rather than an SVG document model.

Frequently asked questions

What is LeaferJS and what is it built for?

LeaferJS is an easy-to-use Canvas engine for building interactive and editable graphics applications, described as an infinite canvas engine for the AI era. It targets large scale, high density applications with very many layers, and its core capabilities include a full scene tree, native drag, scale and multi-touch with hit testing, a Flex layout engine, and state-driven animation.

How do I get the LeaferJS development environment running?

Clone the repository with git clone --recurse-submodules so all the sub-repositories come with it, then run npm install and npm run start, and open http://localhost:10101 in the browser. To try an example, copy the sample code from the LeaferJS site into index.ts and it runs live locally.

What performance does the LeaferJS README claim?

For one million interactive rectangles it reports first screen creation of 1.28 seconds against roughly 9 to 15 seconds for a traditional Canvas library, 320 MB of memory against about 2 to 4 GB, and 60 FPS dragging a single element against 0 to 4 FPS. The test environment is a 2K screen laptop with Chrome V143.0, and the README notes the data is for reference only and depends on the hardware.

Is the LeaferJS editor plugin free?

The core engine and basic plugins stay MIT licensed and open source, including a built-in Editor plugin that enables zoom, rotation, movement and multi-select. The commercial PxGrow plugins add a professional editor suite, complex graphics algorithms and performance optimisations aimed at industrial applications.

Which platforms can LeaferJS build for?

The build scripts in the package.json set a PLATFORM variable for core, web, worker, node, miniapp, draw and in, and the README describes one codebase running on web, Node.js, WeChat mini programs and mobile H5. The browser example in the README is the one that is shown in full.

Official sources

  1. leaferjs/LeaferJS on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/leaferjs-leaferjs.svg)](https://hysenlabs.com/projects/leaferjs-leaferjs)

Was this useful?