DrawBox
2.1.0-alpha01indexedPowerful drawing canvas with freehand and shape tools, undo/redo history, SVG/JSON/bitmap export, customizable strokes and opacity, composable API, and MVI-based reactive state management.
Powerful drawing canvas with freehand and shape tools, undo/redo history, SVG/JSON/bitmap export, customizable strokes and opacity, composable API, and MVI-based reactive state management.
DrawBox is a Kotlin Multiplatform drawing SDK for Compose Multiplatform. It helps developers embed editable drawing, annotation, diagramming, and export capabilities across Android, iOS, Web, and Desktop from one shared Kotlin codebase.
Maintainer response policy: issues and pull requests receive a first response within 7 days. Security reports go through SECURITY.md.
Run the sample right in your browser — no install required:
Cross-platform, one codebase
Drawing primitives
Rich elements
Editing
Import / export
samples/ for ready-made examples.Architecture
Intent / Event / Mode / types.A short walkthrough of the SDK in action — pen, shapes, transforms, and the import / export pipeline.
Drawing and shape editing — pen pressure, shapes with independent fill / stroke, multi-select transforms.
Import / export round-trip — JSON in, edits, JSON out, plus SVG and PNG export.
The bundled sample exposes the full SDK surface through a single settings drawer so you can probe each capability without writing host code.
Drawings are serialised as plain JSON ({ "bgColor": "...", "elements": [...] }), which means a flowchart can be authored or programmatically generated and then imported into the SDK. The two scenes below were rendered by importing the sample files in samples/ — no manual drawing involved.
To try them yourself: open the sample app, tap Settings → Import → Import JSON, and paste the contents of either file.
@Composable
fun DrawingScreen() {
val controller = rememberDrawBoxController()
val state by controller.state.collectAsState()
Column(modifier = Modifier.fillMaxSize()) {
DrawBox(
state = state,
onIntent = controller::onIntent,
modifier = Modifier.fillMaxSize().weight(1f)
)
}
}
Latest Version: 2.1.0-alpha01 (KMP Preview)
repositories {
mavenCentral()
}
dependencies {
implementation("io.ak1:drawbox:2.1.0-alpha01")
}
repositories {
mavenCentral()
}
dependencies {
implementation 'io.ak1:drawbox:2.1.0-alpha01'
}
<dependency>
<groupId>io.ak1</groupId>
<artifactId>drawbox</artifactId>
<version>2.1.0-alpha01</version>
</dependency>
<dependency org='io.ak1' name='drawbox' rev='2.1.0-alpha01'>
<artifact name='drawbox' ext='pom' ></artifact>
</dependency>
Full version history and the
1.x → 2.xmigration guide live in CHANGELOG.md.
First pre-release of the 2.1 line. The frozen 2.0 surfaces (DrawBoxController, Mode, Intent, Event, ) are extended only — see the for the one structural change inside made to accommodate pen-pressure data.
See CHANGELOG.md for the full list and the 2.0.x → 2.1.x migration guide.
RangVikalp for the beautiful color picker used in DrawBox
Please report vulnerabilities privately. See SECURITY.md for the supported versions, reporting channel, and disclosure policy.
Licensed under the Apache License, Version 2.0, click here for the full license.
This project was created by Akshay Sharma.
If you appreciate my work, consider buying me a cup of :coffee: to keep me recharged :metal: by PayPal
I love using my work and I'm available for contract work. Freelancing helps to maintain and keep my open source projects up to date!
State2.0 public surfaces (DrawBoxController, Mode, Intent, Event, State) frozen under semver; incubating surfaces opt in via explicit annotations.| Section | What it controls |
|---|
| Export | Download SVG writes the current scene as scalable vector XML. Download PNG rasterises the visible canvas. Export JSON serialises the entire scene (background, elements, styles) to a portable text file. |
| Import | Import JSON loads a previously exported scene or any compatible JSON payload (try the files in samples/). Insert image opens the platform-native picker and places the chosen bitmap as an editable Element.Image. |
| Playback | Replay drawing re-plays the strokes in the order they were created — useful for tutorials, time-lapses, or debugging stroke ordering. |
| Canvas | Background color swaps the canvas tint. Background pattern toggles between None, Graph, Checker, Hideout, and Texture — all tileable SVG patterns rendered through Skia. |
| View | Show grid toggles a world-space grid overlay that scales with zoom. |
| Danger | Clear canvas removes every element. Snapshot-backed, so a single undo restores the cleared scene. |

samples/DrawBox-daily-loop.json — portrait flow with mixed shapes, dashed strokes, a curved loop-back arrow, multi-line text, and connector bindings that auto-snap to the bound shape's facing side.
![]() samples/DrawBox-build-cycle.json — landscape pipeline exercising every shape type (triangle, rectangle, circle), all three stroke styles (solid, dashed, dotted), and three font families (serif, sans, mono).
|
// Drawing Modes
controller.setMode(Mode.PEN) // Freehand drawing
controller.setMode(Mode.RECTANGLE) // Rectangle shapes
controller.setMode(Mode.CIRCLE) // Circle shapes
controller.setMode(Mode.TRIANGLE) // Triangle shapes
controller.setMode(Mode.ARROW) // Arrows
controller.setMode(Mode.LINE) // Lines
// Customization
controller.setColor(Color.Blue) // Set stroke color
controller.setStrokeWidth(5f) // Set stroke width
controller.setOpacity(0.8f) // Set transparency (0.0-1.0)
controller.setBgColor(Color.White) // Set background color
// History Management
controller.undo() // Undo last action
controller.redo() // Redo last undone action
controller.reset() // Clear canvas
// Export & Import
controller.exportPath() // Export as JSON
controller.exportSvg() // Export as SVG
controller.importPath(jsonString) // Import from JSON
controller.saveBitmap() // Save as bitmap
// State Monitoring
controller.canUndo.collect { ... } // Monitor undo availability
controller.canRedo.collect { ... } // Monitor redo availability
controller.events.collect { event -> // Listen to events
when (event) {
is Event.SvgExported -> saveFile(event.svg)
is Event.PngSaved -> processImage(event.bitmap)
is Event.Error -> showError(event.message)
else -> {}
}
}
StateElement.PathElement.Image, Mode.IMAGE) — place, transform, and export bitmaps as first-class canvas elements.Element.Text, Mode.TEXT) — block-level plain text with inline editor, font controls, and SVG export.Element.PathSample carries position, width, and optional tilt / azimuth from Apple Pencil and S Pen. Mouse / capacitive touch defaults to unit pressure with zero overhead.io.ak1.drawbox.input:
pasteImageFromClipboard(...) — JVM, Web (WasmJS + JS), Android, iOS.Modifier.imageDragAndDropTarget(...) — real on Desktop; documented stubs on iOS / Web pending Compose Multiplatform API support.Element.Shape with explicit "none" states for both.Surfaced from shared tags and platforms — no rankings paid for.