0

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.

3
  • @HelderSepulveda thank you for your feedback. This question doesn’t need any piece of code attached. Its something that I didn’t find in konva’s documentation nor in its examples. I want to find if it’s doable using konva’s API or it’s something that I have to create from the ground up. Commented May 24, 2019 at 19:24
  • If is not on the docs nor in its examples, it is safe to assume you have to create it from the ground up... Commented May 24, 2019 at 19:31
  • 1
    Konvajs and similar libraries working over the HTML5 canvas can draw shapes and paths. However, your question requires an algorithm that can discover regions within the overlapping stroke lines and apply colours to those regions. On the basis of keeping it simple, most HTML5 libraries will not provide this level of complex functionality. @Sanxofon answer is practical and the linked article is a good explanation of a way to achieve simple region colouring, but if you want to add gradient fills or textures then you will have a significant task ahead. Commented May 29, 2019 at 11:53

3 Answers 3

4
+50

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!

2

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 :)

0

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

1
  • Hello there, you did a very great work, but after painting when we select other element the last painted data is getting erased can you please check and update the code. Commented Nov 25, 2021 at 5:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.