DrawBox-Enhanced

Interactive canvas component enabling freehand and shape drawing with customizable background, stroke size, color/opacity, eraser, fill, eyedropper, spray, undo/redo, bitmap import/export.

Android JVMJVMKotlin/NativeWasmJS
GitHub stars1
Dependents0
LicenseApache License 2.0
Creation date6 months ago

Last activity2 months ago
Latest release2.1.2 (2 months ago)

Kotlin

Platform Android Platform iOS Platform JVM Platform WASM

DrawBox Enhanced

Building on the work of Mark Yavorskyi's DrawBox, DrawBox Enhanced is a Compose Multiplatform library to quickly and easily provide a canvas for your users to draw on.

Features

  • Compose Multiplatform, targeting: JVM, Android, WASM, iOS
  • Customisable background, stroke size, colours and opacities
  • Eraser tool
  • Fill tool
  • Eyedropper tool
  • Spray can tool
  • Shape tools (line, rectangle, oval)
  • Undo, redo, or clear all brushstrokes
  • An easy implementation

Planned features:

  • Maybe a select/translate tool
  • Maybe a text tool
  • Layers

Download

Using Gradle Kotlin DSL:

implementation("uk.codecymru.drawbox:DrawBox-Enhanced:2.1.2")

Usage

val controller = remember { DrawController() }
DrawBox(drawController = controller, modifier = Modifier.fillMaxSize())

Configuring settings

// The following optional parameters can be set to 
val controller = remember {
    DrawController(
        startingTool = CanvasTool.BRUSH,
        startingOpacity = 1f,
        startingStrokeWidth = 10f,
        startingColor = Color.Red,
        startingBackground = DrawBoxBackground.NoBackground,
        startingCanvasOpacity = 1f
    )
}

Enabling undo/redo

val enableUndo by controller.canUndo.collectAsState(false)
val enableRedo by controller.canRedo.collectAsState(false)

// Then create a button for each:
IconButton(onClick = controller::undo, enabled = enableUndo) {
    Icon(imageVector = Icons.Default.ArrowBack, contentDescription = "undo")
}
IconButton(onClick = controller::redo, enabled = enableRedo) {
    Icon(imageVector = Icons.Default.ArrowForward, contentDescription = "redo")
}

Switching tools

// To see the current tool
val tool by controller.canvasTool.collectAsState()

// To set the current tool, as an example:
TextButton(onClick = { controller.canvasTool.value = CanvasTool.BRUSH }) {
    Text("Brush")
}
TextButton(onClick = { controller.canvasTool.value = CanvasTool.ERASER }) {
    Text("Eraser")
}
// etc...

Importing a bitmap

val bitmap: ImageBitmap = /* (...) */
drawController.open(bitmap)

Exporting a bitmap

// This provides the up-to-date drawn bitmap
controller.internalBitmap

// As an example, on the JVM target we could save this via:
TextButton(onClick = { saveImage(controller.internalBitmap) }) {
    Text("Save")
}

fun saveImage(bitmap: ImageBitmap) {
    val dialog = FileDialog(null as Frame?, "Save Image", FileDialog.SAVE)

    dialog.file = "image.png"
    dialog.isVisible = true

    val directory = dialog.directory
    val fileName = dialog.file

    if (directory != null && fileName != null) {
        val file = File(directory, fileName)

        ImageIO.write(
            bitmap.toAwtImage(),
            "png",
            file
        )
    }
}

Creating another viewer

// FinishDrawingUpdate means that this viewer won't show the user any in-progress strokes as they draw
DrawBoxViewer(
    controller = controller,
    subscription = DrawBoxSubscription.FinishDrawingUpdate,
    modifier = Modifier.size(200.dp).border(width = 1.dp, color = Color.Red)
)

Examples

Two useful samples of this library's basic usage can be found, written by Mark, in the sample package:

For example projects, see the following:

  • Farsigraphy (where it is used to allow users to practise drawing letters from the Farsi alphabet) (REPO CURRENTLY PRIVATE)
  • PaintWindow (where it is used to emulate an old MS Paint on my personal website) (REPO CURRENTLY PRIVATE)

Author

The original project was created by Mark Yavorskyi, with the Enhanced edition being created by Cyrus Castle

Mark's Message

I love my work. The idea of creating this open-source project appeared because I needed a multiplatform (Android + desktop) library for drawing. I found several popular libs for Android but there was ZERO for using in KMM/KMP. I still have some aspects to improve and I will be happy if you share your feedback or propose an idea!

Hope you enjoy it!
Mark

License

Licensed under the Apache License, Version 2.0, click here for the full license.

Android JVMJVMKotlin/NativeWasmJS
GitHub stars1
Dependents0
LicenseApache License 2.0
Creation date6 months ago

Last activity2 months ago
Latest release2.1.2 (2 months ago)

Kotlin

Platform Android Platform iOS Platform JVM Platform WASM

DrawBox Enhanced

Building on the work of Mark Yavorskyi's DrawBox, DrawBox Enhanced is a Compose Multiplatform library to quickly and easily provide a canvas for your users to draw on.

Features

  • Compose Multiplatform, targeting: JVM, Android, WASM, iOS
  • Customisable background, stroke size, colours and opacities
  • Eraser tool
  • Fill tool
  • Eyedropper tool
  • Spray can tool
  • Shape tools (line, rectangle, oval)
  • Undo, redo, or clear all brushstrokes
  • An easy implementation

Planned features:

  • Maybe a select/translate tool
  • Maybe a text tool
  • Layers

Download

Using Gradle Kotlin DSL:

implementation("uk.codecymru.drawbox:DrawBox-Enhanced:2.1.2")

Usage

val controller = remember { DrawController() }
DrawBox(drawController = controller, modifier = Modifier.fillMaxSize())

Configuring settings

// The following optional parameters can be set to 
val controller = remember {
    DrawController(
        startingTool = CanvasTool.BRUSH,
        startingOpacity = 1f,
        startingStrokeWidth = 10f,
        startingColor = Color.Red,
        startingBackground = DrawBoxBackground.NoBackground,
        startingCanvasOpacity = 1f
    )
}

Enabling undo/redo

val enableUndo by controller.canUndo.collectAsState(false)
val enableRedo by controller.canRedo.collectAsState(false)

// Then create a button for each:
IconButton(onClick = controller::undo, enabled = enableUndo) {
    Icon(imageVector = Icons.Default.ArrowBack, contentDescription = "undo")
}
IconButton(onClick = controller::redo, enabled = enableRedo) {
    Icon(imageVector = Icons.Default.ArrowForward, contentDescription = "redo")
}

Switching tools

// To see the current tool
val tool by controller.canvasTool.collectAsState()

// To set the current tool, as an example:
TextButton(onClick = { controller.canvasTool.value = CanvasTool.BRUSH }) {
    Text("Brush")
}
TextButton(onClick = { controller.canvasTool.value = CanvasTool.ERASER }) {
    Text("Eraser")
}
// etc...

Importing a bitmap

val bitmap: ImageBitmap = /* (...) */
drawController.open(bitmap)

Exporting a bitmap

// This provides the up-to-date drawn bitmap
controller.internalBitmap

// As an example, on the JVM target we could save this via:
TextButton(onClick = { saveImage(controller.internalBitmap) }) {
    Text("Save")
}

fun saveImage(bitmap: ImageBitmap) {
    val dialog = FileDialog(null as Frame?, "Save Image", FileDialog.SAVE)

    dialog.file = "image.png"
    dialog.isVisible = true

    val directory = dialog.directory
    val fileName = dialog.file

    if (directory != null && fileName != null) {
        val file = File(directory, fileName)

        ImageIO.write(
            bitmap.toAwtImage(),
            "png",
            file
        )
    }
}

Creating another viewer

// FinishDrawingUpdate means that this viewer won't show the user any in-progress strokes as they draw
DrawBoxViewer(
    controller = controller,
    subscription = DrawBoxSubscription.FinishDrawingUpdate,
    modifier = Modifier.size(200.dp).border(width = 1.dp, color = Color.Red)
)

Examples

Two useful samples of this library's basic usage can be found, written by Mark, in the sample package:

For example projects, see the following:

  • Farsigraphy (where it is used to allow users to practise drawing letters from the Farsi alphabet) (REPO CURRENTLY PRIVATE)
  • PaintWindow (where it is used to emulate an old MS Paint on my personal website) (REPO CURRENTLY PRIVATE)

Author

The original project was created by Mark Yavorskyi, with the Enhanced edition being created by Cyrus Castle

Mark's Message

I love my work. The idea of creating this open-source project appeared because I needed a multiplatform (Android + desktop) library for drawing. I found several popular libs for Android but there was ZERO for using in KMM/KMP. I still have some aspects to improve and I will be happy if you share your feedback or propose an idea!

Hope you enjoy it!
Mark

License

Licensed under the Apache License, Version 2.0, click here for the full license.