Streamlit Drawable Konva
Live demo: drawable-konva-demo.streamlit.app
Streamlit custom component (Components v2) that provides a sketching canvas
using Konva.js / react-konva.
The public Python API is intentionally compatible with
streamlit-drawable-canvas-fix
(st_canvas → CanvasResult(image_data, json_data)). Object JSON uses
Konva-oriented fields (x/y/points/…), not Fabric.js schemas.
Features
- Freehand, line, rect, circle, point, polygon, spline (Catmull-Rom through clicks) drawing
- Rect crop — single crop region with dimmed overlay (
rect_cropmode) - Image comparison (0.5) —
st_image_comparisonbefore/after slider companion - Interaction locks & groups (0.3) — per-object
locked,groupId, axisdragConstraint,transform_options - Transform mode (move / scale / rotate); double-click to delete
- Viewport zoom, pan, and tilt (display-only; see below)
- Background color or image
- Realtime or on-demand updates to Streamlit
- Undo / redo / clear toolbar
- Returns RGBA
image_dataand scenejson_data - Host-agnostic mount (0.4) —
standalone.js/DrawableKonvaCanvas.mountfor Violit embeds
Viewport: zoom / pan / tilt
Enabled by default (enable_viewport_controls=True). These change how the
canvas is viewed, not the stored object coordinates or exported
image_data.
| Control | How |
|---|---|
| Zoom | Mouse wheel, or toolbar Zoom + / − |
| Pan | drawing_mode="pan" and drag; or Alt+drag; or middle-mouse drag |
| Tilt | Toolbar Tilt ↶ / ↷ (view rotation, ±15°) |
| Reset | Toolbar Reset view |
Try them in the demo page Zoom / pan / tilt.
Why Konva.js (vs Fabric.js)?
Konva is not universally “better” than Fabric — both are mature 2D canvas libraries. For this Streamlit component, Konva is the better fit.
| Concern | Konva | Fabric |
|---|---|---|
| React integration | First-class via react-konva (declarative scene tree) |
Imperative fabric.Canvas; React wrappers are thinner / more brittle |
| Mental model | Stage → Layer → Shape (clear export boundaries) | Single canvas object model; background vs drawing export needs extra care |
| Bundle / focus | Leaner, scene-graph oriented | Heavier; strong textile/image-editing heritage |
| Transforms | Built-in Transformer for select / scale / rotate |
Excellent selection UX; historically the gold standard for editors |
| Ecosystem | Strong for interactive UIs and annotation tools | Huge installed base; many Fabric JSON examples in the wild |
Why we chose Konva here
- React + Streamlit Components v2 — the official CCv2 React template maps
cleanly onto
react-konva. Drawing state stays in React; updates go out viasetStateValuewithout fighting an imperative canvas singleton. - Layered export — background images can live on a non-exported layer while
strokes/shapes export cleanly to
image_data, matching the upstream “background is not round-tripped” behavior with less glue code. - Maintainability — freerdraw / shapes / polygon / transform are ordinary React event handlers and Konva nodes, which is easier to evolve next to a modern Vite + TypeScript frontend than a Fabric-centric CRA-era stack.
- Performance for annotation UIs — Konva’s layer/stage model scales well for ROI / sketching workloads typical in Streamlit apps.
When Fabric may still win
- You need byte-compatible Fabric JSON (existing pipelines, demos, or
tutorials that assume
left/top/pathFabric schemas). - You want Fabric’s mature free-transform / skew / complex text editing out of the box without reimplementing edge cases.
This package keeps a compatible Python API (st_canvas → CanvasResult) so
apps can migrate from streamlit-drawable-canvas-fix, while accepting that
json_data is Konva-oriented rather than a Fabric dump.
Install (uv)
uv sync
Build the frontend once (required before first Streamlit run):
cd streamlit_drawable_konva/frontend
npm install
npm run build
cd ../../
Editable install is handled by uv sync via the local pyproject.toml.
Demo
uv run streamlit run app.py
Development
CCv2 watches a production-style build into frontend/build (no separate webpack
dev server URL). Use two terminals:
Terminal A — frontend watch build
cd streamlit_drawable_konva/frontend
npm install
npm run dev
Terminal B — Streamlit
uv sync
uv run streamlit run app.py
Refresh the browser after frontend rebuilds.
API
from streamlit_drawable_konva import st_canvas
result = st_canvas(
fill_color="rgba(255, 165, 0, 0.3)",
stroke_width=3,
stroke_color="#000000",
background_color="#eee",
background_image=None,
update_streamlit=True,
height=400,
width=600,
drawing_mode="freedraw", # freedraw|line|rect|rect_crop|circle|point|polygon|spline|transform|pan
initial_drawing=None,
display_toolbar=True,
point_display_radius=3,
enable_viewport_controls=True,
key="canvas",
)
# result.image_data -> np.ndarray | None
# result.json_data -> dict | None
Image comparison (st_image_comparison)
Before/after slider companion (same package; also available on Violit as
vl_image_comparison):
from streamlit_drawable_konva import st_image_comparison
st_image_comparison(
img1, # PIL / path / ndarray / data URL
img2,
label1="Before",
label2="After",
width=700,
starting_position=50,
)
Crop controls (rect_crop)
- Draw one rectangle; a new draw replaces the previous crop
- Drag the box or use handles to move / resize
- Double-click the crop box to remove it
- Read coordinates with
crop_box_from_json(result.json_data)→(x, y, width, height) - Crop overlay is excluded from exported
image_data
Spline data (spline)
json_data stores control points only — the clicks you placed:
from streamlit_drawable_konva import splines_from_json, spline_control_points, sample_spline
splines = splines_from_json(result.json_data)
control = spline_control_points(splines[0]) # [(x, y), ...] from JSON
dense = sample_spline(splines[0], samples_per_segment=16) # interpolated polyline
Each spline object looks like:
{"id": "...", "type": "spline", "points": [x1, y1, x2, y2, ...], "tension": 0.5}
The smooth curve is not in JSON; use sample_spline() (Catmull-Rom, same tension) when you need a dense path for masking, metrics, or export.
Interaction locks, groups, handles (0.3)
Object fields (in initial_drawing / json_data):
locked: true— visible, not interactive in transform modegroupId+ optionaltype: "group"descriptor — move/rotate togetherdragConstraint: { type: "axis", axis: {x, y}, min, max }— constrained handle drag- Per-object:
draggable,selectable,scalable,rotatable,deletable
Python kwarg:
st_canvas(..., transform_options={"allow_scale": False})
Polygon controls
- Left-click: add point
- Right-click: close polygon
- Double-click: remove latest point
Transform controls
- Click object to select
- Drag / resize / rotate with the transformer
- Double-click selected object to delete
Viewport controls
- Wheel / Zoom ±: zoom toward cursor (wheel) or canvas center (buttons)
- Pan mode / Alt-drag / middle-mouse: move the view
- Tilt ↶↷: rotate the view
- Reset view: 100% zoom, 0° tilt, centered pan
Migrating from Fabric drawable canvas
See MIGRATION.md for import renames, JSON field mapping, and
behavioral differences vs streamlit-drawable-canvas / -fix.
Packaging notes
- Registered as
streamlit-drawable-konva.st_canvasandstreamlit-drawable-konva.st_image_comparisonvia the in-packagestreamlit_drawable_konva/pyproject.tomlmanifest (asset_dir = frontend/build). - Requires Streamlit
>= 1.51(Components v2). - Frontend toolchain targets Node
>= 18(Vite 6). - Host-agnostic mount:
frontend/build/standalone.jsexposeswindow.DrawableKonvaCanvas.mountandwindow.DrawableKonvaCanvas.mountImageComparisonfor non-Streamlit hosts (e.g. Violit). Streamlit usesbuild/index.jsandbuild/comparison.js.
Publishing (GitHub / PyPI / Streamlit Cloud / gallery)
Step-by-step instructions: PUBLISHING.md (includes updating
GitHub / PyPI / Streamlit Cloud / gallery after the first release).
Current version: 0.5.0.
Order: push to GitHub → publish to PyPI → deploy app.py on Community Cloud →
submit gallery/streamlit-drawable-konva.json
as a PR to streamlit/gallery.
License
MIT
Metadata
Release files for streamlit-drawable-konva 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| streamlit_drawable_konva-0.5.0.tar.gz | 380.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| streamlit_drawable_konva-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 759.9 kB
Release files / streamlit_drawable_konva-0.5.0.tar.gz
| Download URL | streamlit_drawable_konva-0.5.0.tar.gz |
|---|---|
| Size | 380.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9c9afb7fb197171db064567ca6d402be7d92f0a43aa897d5fb51aee1da077f93
|
|
BLAKE2b-256 checksum How to use checksums |
d71393d9c63d0937c1a54f430ac59a31deb20447afc9eb285c2a45b1a46e7849
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / streamlit_drawable_konva-0.5.0-py3-none-any.whl
| Download URL | streamlit_drawable_konva-0.5.0-py3-none-any.whl |
|---|---|
| Size | 379.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3846f66ebf38051cc41df462ee8fced76904eec1f372f6614ae512631c2690cb
|
|
BLAKE2b-256 checksum How to use checksums |
e8957c4b8456ddcd0a6c1f99902436e45b64e86de7d4c137c134f8870d3d5e1a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|