Lucaci Sergiu
Lucaci Sergiu

Reputation: 574

Is it possible to implement a Paint Bucket using Konva.js?

I’ve managed to implement, using konva, multiple tools that allow users to draw different shapes and patterns like: rectangle, circle, arrows, free draw, eraser, et. c.

I’m trying to achieve something like: using a paint bucket, users should be able to fill different parts of a shape, if over that shape are drawn other shapes or patterns.

Maybe this use case helps to understand better my question:

  1. The user draws a circle.
  2. Afterwards he draws lines over that circle so will be split in multiple areas.
  3. The user uses now the paint bucket and tries to fill only the areas of that circle.

I’m wondering if, using konva, is possible to achieve this functionality.

Until now I've manage only to fill entire shapes, similar to this.

Update

Added images for the use case above.

1 & 2. User draws a circle and lines over it: enter image description here

  1. Using paint bucket user can fill certain areas of that circle: enter image description here

Any feedback will be very welcomed.

Upvotes: 0

Views: 1933

Answers (3)

Lucaci Sergiu
Lucaci Sergiu

Reputation: 574

I’ve came up with a solution: https://codesandbox.io/s/stupefied-northcutt-1y0cg.

In short, what this solution does is that when the stage is mounted, the paint bucket is setup targeting the canvas generated by konva. The pixels around the one clicked are colored using a cell automaton algorithm, as per Antoni's suggestion.

Okay, but the downside of this approach is that whenever you’re drawing a shape after paint bucket is used, the paint bucket changes get lost because (I assume) render() doesn’t know about the "vanilla" changes made in setupPaintBucket().

Another downside of this approach is that the canvas is blurry.

Sources:

  1. Draw circle, arrow and free hand: https://codesandbox.io/s/43wzzv0l37

  2. Vanilla Paint Program: https://codepen.io/falldowngoboone/pen/zxRXjL

Upvotes: 0

Sanxofon
Sanxofon

Reputation: 981

Bad news: What you want cannot be done with Konvajs, as it is designed to work with vectorial images. Each figure is created as a whole by an equation and is "separated" of other figures (as the lines X and Y and the circle are separate in the Snippet below. It is not a raster layer. To do a paint bucket tool in vector graphics is hard.

(See Good news at the end!)

var width = window.innerWidth;
var height = window.innerHeight;

var stage = new Konva.Stage({
  container: 'container',
  width: width,
  height: height
});

var layer = new Konva.Layer();

var circle = new Konva.Circle({
  x: 180,
  y: 120,
  radius: 50,
  fill: 'red',
  stroke: 'black',
  strokeWidth: 4
});
var lineX = new Konva.Line({
  x: 180, // 180-50
  y: 120,
  points: [-100, 0, 100, 0],
  stroke: 'black',
  strokeWidth: 4
});
var lineY = new Konva.Line({
  x: 180, // 180-50
  y: 120,
  points: [0, -100, 0, 100],
  stroke: 'black',
  strokeWidth: 4
});

circle.on('click', function() {
  var fill = this.fill() == 'red' ? '#00d00f' : 'red';
  this.fill(fill);
  layer.draw();
});

layer.add(circle);
layer.add(lineX);
layer.add(lineY);
stage.add(layer);
body {
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #f0f0f0;
}
<script src="https://unpkg.com/[email protected]/konva.min.js"></script>
<div id="container"></div>

Good news: But you can do it with Canvas, HTML5 and Javascript.

Here you have a good tutorial which includes a DEMO (on top of the page) and the SOURCE CODE to Create a Paint Bucket Tool in HTML5 and JavaScript

Hope this helps you!

Upvotes: 4

Antoni Silvestrovič
Antoni Silvestrovič

Reputation: 1035

Unless konva has a specific implementation for it that I don’t know of, this is more of an algorithmic problem.

One approach you could take if you decide to implement it on your own is something like a cell automaton. You would create one pixel somewhere in the middle, and it would grow over time (of course you don’t need to show the growth). The rules for it would be that any pixel of the specified color must colorize any pixel around it if it is the same as the average color of pixels around original point (where you clicked to fill color).

Hope this helps :)

Upvotes: 2

Related Questions