Frontend Development 14 min read

Introducing Pictode: A Konva.js‑Based Graphical Editor Framework with Tutorials and Plugin Guide

This article presents Pictode, a Konva.js‑driven graphics editor framework, explains its core features, demonstrates how to set up a canvas, use drawing tools, selector and history plugins, and provides step‑by‑step code examples for integration with Vue or other front‑end projects.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Introducing Pictode: A Konva.js‑Based Graphical Editor Framework with Tutorials and Plugin Guide

Origin

Inspired by many technical experts sharing their own graphic editor projects on Juejin, the author decided to create a personal editor named Pictode using spare time over two months.

Previous work includes a 3D editor based on Three.js, a BPMN editor, a topology editor based on X6, and a low‑code editor with Vue, but corporate constraints prevented those from reaching the desired level.

Since August, the author has been developing Pictode , which now integrates useful functions such as tool switching, property editing, context menu, local saving, image export, canvas zoom/drag, history, language and theme switching.

Pictode Main Features Demo

Graphic Drawing

Selection / Transformation

Layer Move

Align / Distribute

Group / Ungroup

Export Image

Tip: Experience the editor yourself at https://pictode.com/#/ and star the GitHub repository.

What Pictode Can Bring You

Many articles show how to build a canvas or image editor, but often the code is hard to reuse in your own project, especially when the original editor is built with a different framework.

Pictode is framework‑agnostic, built on Konva.js, allowing easy integration with Vue, React, or plain JavaScript, and provides a lightweight API.

DIY Canvas

Below is a quick guide to creating a canvas with Pictode.

Creating the Canvas

Install the core package:

npm install @pictode/core

Instantiate the App object:

import { App } from "@pictode/core";

const app = new App();

Mount the canvas to a DIV container:

<script setup lang="ts">
import { ref, onMounted } from "vue";
import { App } from "@pictode/core";

const canvasRef = ref<HTMLDivElement>();
const app = new App();

onMounted(() => {
  if (canvasRef.value) {
    app.mount(canvasRef.value);
  }
});
</script>

<template>
  <div class="wrapper">
    <div ref="canvasRef"></div>
  </div>
</template>

Drawing Tools

Install the tools package:

npm install @pictode/tools

Instantiate a rectangle tool:

import { RectTool } from "@pictode/tools";

new RectTool({
  config: {
    stroke: "black",
    strokeWidth: 2,
    fill: "gray",
    cornerRadius: 0,
    opacity: 1,
  },
});

Switch to the rectangle tool:

app.setTool(
  new RectTool({
    config: {
      stroke: "black",
      strokeWidth: 2,
      fill: "gray",
      cornerRadius: 0,
      opacity: 1,
    },
  })
);

Selection / Transformation

Install the selector plugin:

npm install @pictode/plugin-selector

Instantiate and load it:

import { SelectorPlugin } from "@pictode/plugin-selector";

const selectorPlugin = new SelectorPlugin();
app.use(selectorPlugin);

Use app.select(...) / app.cancelSelect(...) for selection, and hold Shift for multi‑select.

To avoid interference between drawing and selection, disable the selector when a drawing tool is active and re‑enable it when the tool is cleared:

app.setTool(tool); // disables selectorPlugin
app.setTool(null); // re‑enables selectorPlugin

The @pictode/tools package also provides a dedicated SelectTool with onActive and onInactive hooks to manage this automatically.

const selectTool = new SelectTool({
  hooks: {
    onActive() { selectorPlugin.enable(); },
    onInactive() { selectorPlugin.disable(); },
  },
});

const rectTool = new RectTool({
  config: { stroke: "black", strokeWidth: 2, fill: "gray" },
  hooks: { onActive() { app.cancelSelect(); } },
});

app.setTool(selectTool);

Undo / Redo

Install the history plugin:

npm install @pictode/plugin-history

Instantiate and load it:

import { HistoryPlugin } from "@pictode/plugin-history";
const historyPlugin = new HistoryPlugin();
app.use(historyPlugin);

Now app.undo() and app.redo() work, e.g.:

<button @click="app.undo()">Undo</button>
<button @click="app.redo()">Redo</button>

Align / Distribute

Install the alignment plugin:

npm install @pictode/plugin-alignment

Instantiate and load it:

import { AlignmentPlugin } from "@pictode/plugin-alignment";
const alignmentPlugin = new AlignmentPlugin();
app.use(alignmentPlugin);

Use methods such as app.alignTop , app.alignRight , app.alignBottom , app.alignLeft , app.alignCenterX , app.alignCenterY , as well as app.distributeX and app.distributeY to arrange objects.

Note: All @pictode/* packages are currently pre‑release versions undergoing testing and bug fixing.

Architecture and Technology Choices

Pictode aims to be a universal graphics editor framework, choosing konva.js as the core library because of its clear TypeScript support, active community, and stable API. An earlier consideration of fabric.js was dropped due to messy code structure and outdated syntax.

Design

The library consists of two parts: a core engine that is UI‑framework independent, and a Vue 3 based UI layer that demonstrates how to use the core.

The design follows separation of concerns and event‑driven data interaction, offering flexible plugins and tool mechanisms for easy extension.

Project Roadmap

v1.0.0

(Roadmap image omitted)

v2.0.0

(Roadmap image omitted)

v3.0.0

(Roadmap image omitted)

Open‑Source Plan

The author intends to open source Pictode, seeking help with licensing, issue tracking, and community building.

Conclusion

If you find Pictode interesting, please star the GitHub repository, like, collect, and follow the author for updates.

🎨 Experience Pictode: https://pictode.com/#/

✨ Star on GitHub: https://github.com/JessYan0913/pictode

JavaScriptplugincanvasVueGraphics EditorKonva.jsPictode
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.