Canvas erasing doesn't work - javascript

I'm developing a drawing application with canvas.
I would like to implement an erase functionality, but not a simple erase which is a simple white pen, a real rubber.
In fact, I have a transparent canvas added over the application, and I would like, when I draw, I can erase what I drawn, i.e put opacity to 0 !
I already search on Google & stackoverflow and I find that :
Code : JavaScript - Sélectionner
context.globalCompositeOperation = "destination-out";
context.strokeStyle = "rgba(0,0,0,0)";
But it don't work ... Too, I try different modes of globalCompositeOperation shown on MDN but there is no difference.
Help please.

It doesn't work because you draw a transparent line over what you are trying to erase... So it does nothing.
It is easy to erase when you have a white background, you just draw white over. But it is not what you want.
The trick here is to use clearRect which remove what is on the canvas, instead of drawing over other shapes.
context.clearRect(cursorX, cursorY, brushWidth, brushHeight);
It will appear as small squares but I can't see another way to do it, except maybe with pixel manipulation.

Related

Can I reduce D3 geoPath canvas plot point artifacts in Chrome and Firefox on macOS?

I'm plotting paths on a map in D3 using canvas (although it seems to happen using SVG too) and I am getting little dots where the lines connect. This seems to only happen on Chrome and Firefox. Safari seems to be fine.
I'm also getting little white dots sometimes when drawing circles. See the zoomed in image for further detail.
Has anyone else come across this and found a way to reduce these artifacts? Or is this just in the way Chrome and Firefox renders d3 paths (I've noticed it in normal paths and also geoPaths)?
I can fix the black dots by making the path stroke wider, but our designer wants thin strokes.
I managed a kind of a fix for the intermittent dot "stitches" I was getting. I noticed that if I made the context.lineWidth = 1.1 then the dark dots disappeared. But then the line was too dark, so I simply set the context.strokeStyle to an rgba value with the alpha as 0.5.
So here's the code:
// Draw outline of countries
context.beginPath();
context.strokeStyle = "rgba(29,60,67,0.5)";
context.lineWidth = 1.1;
path(borders);
context.stroke();
And here's the result:
(Note: I'm still getting the little white dots, but they aren't as noticeable.)

Selecting Canvas Elements [duplicate]

Take a look at this example:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// First rectangle created
ctx.fillRect(20,20,150,100);
// Second rectangle created
ctx.fillRect(20,150,150,100);
// Third rectangle created
ctx.fillRect(20,300,150,100);
I created three rectangles here. After creating third rectangle I want to rotate first rectangle. How do i get reference of first rectangle now?
A canvas is just a dumb grid of pixels. It doesn't understand what shapes have been drawn on it. Your code (or a library that your code uses) must keep track of the shapes that you've drawn.
Instead, it sounds like you want a library to create a scene graph, like EaselJS, Paper.js, or KineticJS. These libraries will maintain a data structure that tracks what shapes have been drawn on the canvas, and they will then redraw them when you want to manipulate those shapes.
You don't "get the reference" of a rectangle or something with canvas. All you have is a canvas with a context. On which you can draw. Period.
If you want to move the first rectangle, then clear it (using clearRect) and redraw the new one.
Canvas itself is just pixels. It knows how to draw rectangles, but doesn't keep them layered.
To quote Simon Sarris:
HTML5 Canvas is simply a drawing surface for a bit map. You set up a
draw (Say with a color and line thickness) , draw that thing, and then
the Canvas has no knowledge of that thing: It doesn't know where it is
or what it is, it's just pixels. If you want to draw rectangles and
have them move around or be selectable then you have to code all of
that from scratch, including the code to remember that you drew them.
The only exception is the isPointInPath method, but it has limitations.
However, there are some libraries that provide object-oriented interface for Canvas. Like Fabric.js or KineticJS. They remember what you draw as objects (rectangles, circles and so on) and can layer them one over another, move around and add mouse/touch events. Much like DOM.
Drawing functions like fillRect() does not return anything (returns void).
Meaning it simply renders the pixels, it does not create a rectangle object and return it. You'll need to store the rectangle coordinates yourself.

How do I get reference of old generated elements in HTML Canvas?

Take a look at this example:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// First rectangle created
ctx.fillRect(20,20,150,100);
// Second rectangle created
ctx.fillRect(20,150,150,100);
// Third rectangle created
ctx.fillRect(20,300,150,100);
I created three rectangles here. After creating third rectangle I want to rotate first rectangle. How do i get reference of first rectangle now?
A canvas is just a dumb grid of pixels. It doesn't understand what shapes have been drawn on it. Your code (or a library that your code uses) must keep track of the shapes that you've drawn.
Instead, it sounds like you want a library to create a scene graph, like EaselJS, Paper.js, or KineticJS. These libraries will maintain a data structure that tracks what shapes have been drawn on the canvas, and they will then redraw them when you want to manipulate those shapes.
You don't "get the reference" of a rectangle or something with canvas. All you have is a canvas with a context. On which you can draw. Period.
If you want to move the first rectangle, then clear it (using clearRect) and redraw the new one.
Canvas itself is just pixels. It knows how to draw rectangles, but doesn't keep them layered.
To quote Simon Sarris:
HTML5 Canvas is simply a drawing surface for a bit map. You set up a
draw (Say with a color and line thickness) , draw that thing, and then
the Canvas has no knowledge of that thing: It doesn't know where it is
or what it is, it's just pixels. If you want to draw rectangles and
have them move around or be selectable then you have to code all of
that from scratch, including the code to remember that you drew them.
The only exception is the isPointInPath method, but it has limitations.
However, there are some libraries that provide object-oriented interface for Canvas. Like Fabric.js or KineticJS. They remember what you draw as objects (rectangles, circles and so on) and can layer them one over another, move around and add mouse/touch events. Much like DOM.
Drawing functions like fillRect() does not return anything (returns void).
Meaning it simply renders the pixels, it does not create a rectangle object and return it. You'll need to store the rectangle coordinates yourself.

Create javascript countdown

Good day to all.
I need to create a graphical countdown in js. The algorithm for the timer is ordinary. But I need to create a circle filled with a color (lets say green, doesn't matter) and while the counter goes down the circle gets fill with another color. So what I basically need to do is fill a circle with color.
First I thought to simulate some lines inside the circle (from center to margin) and fill it with them. The problem is how to generate lines... and I got to the conclusion that I should generate points to generate lines to fill the circle and even though the code is easy to write sounds like quite a resource eater.
Second option would be to use a drawing library but I fear that it would do the same thing.
So... any ideas how to implement this without wasting too much resources?
Note: The circle must be fill in a circular way... like skill reuse in games for example. (like a clock)
The best way I can think of is to use the Raphael graphis library which allows your code to draw SVG (or VML on older IE). Look at the source of this demo (which basically does what you want):
http://raphaeljs.com/polar-clock.html
The key to understanding the code is understanding this line:
path = [["M", 300, 300 - R], ["A", R, R, 0, +(alpha > 180), 1, x, y]];
And the key to understanding that line is to first understand SVG path specification:
http://www.w3.org/TR/SVG/paths.html
What about to use html5 canvas: with it you can draw arc.
See http://www.html5canvastutorials.com/tutorials/html5-canvas-arcs/
I think you might find what you are looking for here:
http://dev-tips.com/featured/css-tip-how-to-make-ircles-without-images
There is a complete tutorial on how to create circles using css3, it won't work very well in older browsers tho.
Check out this post (using canvas): Using jQuery / HTML5 to animate a circle
Or if you want to do it yourself with an easy CSS, HTML:
You can make a image with a transparent circle in it.
Make a div with a position relative and the size of the image, and the default color of the circle
Make a div with the overlay background color, absolute positioned width 100% bottom 0.
Make a div where the image is as background image width 100% height 100% (so the image is over the default background color.
When the timer ticks out, and you know on what percentage it is, you can change the height of the div you made on step 3. But you won't see any angles on the lines.

HTML5 Canvas: How to fake globalCompositeOperation="darker"

I've googled and googled about this, and all I can find, including on StackOverflow, is "support was and is broken in most major browsers." Not an actual solution to my problem.
This month's Playboy came with a pair of 3D glasses (red/cyan) to view the eye-popping centerfold. Naturally, I hit the Internets to find every single red/cyan anaglyph I could and look at how awesome they are. Eventually I found some animated GIFs, which led to the idea that maybe I should make some cool HTML5 Canvas thing that lets you put shapes on a scene in 3D.
This is how far I got. Only works well in Google Chrome. In Firefox, the "Elevated Text" should look correct, but not the rectangles.
The way I'm generating the scene is thus: There are layers that each contain a Z-index, and you can place a rectangle or some text on whichever layer you want. The concept is simple. When drawing the object, it draws one [Z-index] pixels to the left in pure red, then it draws one [Z-index] pixels to the right in pure cyan.
In theory, the overlapping parts should subtract to become pure black. In Chrome, this happens for filling rectangles, stroking text, but not for filling text. In Firefox, this only happens for stroking text.
Although the intended effect of globalCompositeOperation="darker" should do exactly what I want, it's obvious that going down this road is going to bring nothing but pain.
Does anyone here have an idea as to how I can get the effect I want without using globalCompositeOperation? I tried messing with the alpha channel on the colors but didn't really like how that came together (they never add up to pure black). I could draw a third black rectangle between the red and cyan ones, but that doesn't solve the problem for text or arbitrary shapes.
I could do the pixel-for-pixel rendering myself in the Javascript, but that just seems like overkill. Any thoughts?
If you still need this, I have written a free context-blender library that lets you perform Photoshop-style blend modes between two canvases. I have not yet added 'darker', but you could either:
Fork the project on GitHub, add your own support for darker (it's pretty easy to see how to add a mode) and then send me a pull request, or
Ply me with promises of upvotes to get it added for you. :) The only hard part (as with many of the blending modes) will be attempting to determine what is correct when blending one or two areas which are <100% opacity.
It seems that the correct mode in Firefox is globalCompositeOperation="difference". Haven't tested in Chrome or IE.
Because "difference" is a mathematical operation, there is no ambiguity in the implementation, unlike the subjective term "darker".
Maybe you would like to use darken instead of darker. darker has been removed from the specification in 2007
It's a bit of a hacky way but it worked for me.
You can invert the entire canvas by doing
ctx.globalCompositeOperation = "difference";
ctx.fillStyle = "white";
ctx.fillRect(0,0,canvas.width,canvas.height);
Then render whatever you want to render using globalCompositeOperation = "lighter". Then invert the entire canvas again and it should give the same results as a "darker" blend mode would.

Categories

Resources