How to fill custom shape/path using EaselJS - javascript

I am exploring CreateJS. This question concerns EaselJS.
I have managed to draw 3 arcs and fill them with a color.
Although, I want the final result to look like this:
If I draw a triangle to fill the missing space, how can I remove the color inside the bottom arc?
If I set it to transparent it will display the triangle color.
I could set it to white to look like what I want in this case, but it would look bad on top of a colored background.
Is there any method in the API that I am missing in order to do something similar to a flood fill inside a shape drawn with multiple arcs/lines?

Instead of drawing three separate arcs, you should use arcTo to keep the path continuous.
Something like this (of course replacing the numbers with your points/control points):
new Graphics().beginStroke(STROKE_COLOR)
.moveTo(0, 20)
.arcTo(150, 20, 150, 70, 50)
.arcTo(150, 20, 150, 70, 50)
.arcTo(150, 20, 150, 70, 50)
.endStroke();

Related

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:
The user draws a circle.
Afterwards he draws lines over that circle so will be split in multiple areas.
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:
Using paint bucket user can fill certain areas of that circle:
Any feedback will be very welcomed.
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/konva#3.2.6/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!
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 :)
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:
Draw circle, arrow and free hand: https://codesandbox.io/s/43wzzv0l37
Vanilla Paint Program: https://codepen.io/falldowngoboone/pen/zxRXjL

EaselJS triangle with rounded corners?

How can I create a triangle with rounded corners in EaselJS? I'm using drawPolyStar to create the triangle,
var polystar = new createjs.Shape();
polystar.graphics.drawPolyStar(100, 100, 60, 3, 0, -90);
This is an image of what I want the triangle to look like:
EDIT: Image link doesn't seem to work. This is what the triangle should look like :
But actual triangle has sharp corners.
There are no canvas APIs for rounding corners of polygons that works like the roundRect API.
There are a few approaches I can think of:
Do the round corners yourself using arcTo. This would take some math to figure out, and there may even be some libraries or examples floating around.
[EDIT] I spent a little time making a sample https://jsfiddle.net/lannymcnie/cga60tsf/1/
Using rounded stroke edges, you can sort of fake it. This fiddle shows how a thick line with round ends can make the outer edges look round. You could draw another smaller triangle on top to give the desired effect.
Sample
// Line outer radius
context.lineJoin = "round";
context.lineWidth = cornerRadius;

Have a background image in paper.path with raphael?

I want to put some background image to my paper.path I've created with raphael
paper.path(arc([xCenter, yCenter], radius, startAngle, endAngle)).attr({
'stroke': "#ccc",
'stroke-width': rinc - 1
});
The result:
http://jsfiddle.net/n4Rvr/
I just want to put some image instead the #ccc color. Is it possible? However, I didn't find something interesting on internet.
You want to fill the stroke of the path? There's no support for using patterns on the stroke in Raphaël, so it's not as easy as it is in pure svg, where you can either stroke with a pattern or mask an image with the given path to get the effect you're after.
To get something similar in Raphaël you'll need to build the stroked path as a new path, basically tracing around the inner and outer arcs so that you can fill it. Then use 'fill' instead of 'stroke' and pass in the url of the image you want.

KineticJS strokeWidth of 1 causes a blurred, semi-opaque line instead of a sharp 1 pixel line

I've looked around the internet and found nothing, I've looked on other KineticJS examples that use a strokeWidth of 1 on their rectangles and they all appear to have a semi-opaque 2 pixel line rather than a nice sharp 1px opaque black line.
Now, I am guessing that as Google has nothing that the solution is either really simple or impossible, but.. do you know how I can get a one px border using KineticJS?
$(window).load(function(){
var stage = new Kinetic.Stage({container: "kineticdiv", width: 700, height: 400});
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: stage.attrs.width/2, y: stage.attrs.height/2,
width: 100, height: 100,
fill: "#eee", stroke: "black", strokeWidth: 1
});
layer.add(rect);
stage.add(layer);
});
Anyone got any ideas?
when you draw a line from (x,y1) to (x,y2) (say; the same is true for horizontal lines) you need to worry about whether x is "in the middle of a pixel". if the line is "between pixels" then it will be half in one and half in another. the result will look blurred (it's basically anti-aliasing).
graphics systems vary on whether coordinates are for corners or centres, but you can fix the issue by experimenting a little - you just need to add half a pixel width to the coord and try again.
in the case of an html5 canvas (0,0) is the top left corner, so if you have no transform i guess the top left pixel centre is at (0.5, 0.5).
Another approach: if you use Integer numbers as coordinates and ortogonal 1px weight lines, then you can move the whole stage by [0.5, 0.5] and you dont have to add the half of a pixel to each coordinate, you can then use Integer numbers as coordinate as your whole stage will be moved half of pixel to right and the same to down.
There is a cool approach to get exactly what you want: group two similar shapes. The one at the lower level is one pixel larger then the one at the top. Fill the bottom one with the color you want your border (in your case: Black). works fine for me and has the precision and quality of CSS
The easiest way of solving this with Kinetic is to use the offset properties. So, rather than shifting individual coordinates of what you're drawing, your entire line/shape/group/layer/stage is offset by that much, theoretically getting it where you want it with minimum fuss:
var rect = new Kinetic.Rect({
x: stage.attrs.width/2, y: stage.attrs.height/2,
width: 100, height: 100,
fill: "#eee", stroke: "black", strokeWidth: 1,
offsetX: 0.5,
offsetY: 0.5
});
or, to get a whole bunch of stuff at once:
var layer = new Kinetic.Layer({
offsetX: 0.5,
offsetY: 0.5
});
That said, not all items benefit from this trick. Some, in fact, get fuzzier. So, make sure to apply the offset at the most atomic level that avoids contaminating shapes that don't benefit from it.

JavaScript-clearRect()-pendant for ActionScript?

Is there a ActionScript-version of JavaScript's Canvas.clearRect()?
I only know graphics.drawRect(...) which allows me draw but not remove rectangles.
If there is no such method in ActionScript, how can I emulate it?
There is not an equivalent in ActionScript to clearRect. If you need to do that, then you may want to have multiple sprites, and draw to them separately. That would allow you to adjust z-order, and to remove sections.
If you need to cut out a section of a shape, then you can use drawPath.
mike
graphics.clear();
Not very intuitive, but, in the same fill operation, redrawing again on the same pixel will actually "cut it". So, for example:
graphics.clear();
graphics.beginFill(0x000000);
graphics.drawRect(0, 0, width, height);
graphics.drawRect(10, 10, width - 10, height - 10);
graphics.endFill();
Should actually draw an external border of 10 pixels, leaving the rest of the object transparent. However, once you finish the fill operation, AFAIK there is no way to clear an area without clearing all the graphics of the DisplayObject.

Categories