I am new to canvas (HTML5) i have to design a paint application on canvas. There is a feature like dynamic addition of the selected image at canvas (on mouse-movements) and functionality to delete and drag that added image (Same for Text addition). Now my Question is how can we delete the images from the canvas (Note :There are no fixed no. of images added to the canvas.) Can you please suggest me the approach ??
An HTML5 Canvas is much like a real-world canvas. When you draw to the canvas the ink changes the canvas, blending with the other contents already there and forever changing them.
Ask Monet "How do you add a new person to your painting?" and he might say "you just paint them where you want them!" Similarly, you use drawImage() to 'paint' an image to your Canvas.
However, if you ask Monet "How do you remove a person from a painting?" and he would likely look at you funny and then respond "Quoi? You would have to either make a new painting, or else paint over top of the person!" Similarly, if you want to "remove" something from your canvas you either have to start over (clear the canvas and draw everything except that thing) or re-paint what was 'behind' your image on top of it.
Here is an example I made that shows one way that you can 'save' part of a canvas (by drawing it to another canvas) and then later drawing it back over something to 'erase' it.
However, I generally advise you not to use an HTML5 Canvas unless you know why you need it. You mention adding and removing items, and also detecting mouse movements. Using a retained-mode drawing system—like HTML or SVG—means that you actually add or remove or change items in an object representation, and it is up to someone else (the browser) to figure out how to best redraw them.
You may be best served by letting the "paint" portions of the user input be done on one or more canvases, and then compositing these canvases with other items (such as <div>s with text, or <img> for pictures, or vector-based SVG artwork).
You can make your own retained-mode system on type of canvas, or you can use someone else's library that does this. But instead I'd suggest that you consider whether this is the best and easiest way to accomplish your goals.
Related
There I am creating a stamp maker in HTML,Jquery and javascript. In the editor of my application image is adding to HTML canvas (simple) and also the text, I just create new line element and then append it to the canvas.But the problem is that I want my image to be in back of text. I googled it alot and also search stackoverflow I got the solution of creating multiple canvases but in last I have to download the canvas to file for user. There is the problem. And I want to export whole canvas along with text one and second image together.If I create seperate canvas for the text and another for image and give image one low zindex it would be fine but there will be one canvas to be exported as image.
Link to multiple layers in canvas html5 - canvas element - Multiple layers
I am hopping that we would come up with an idea of how to download both canvases as an image or find a method to take image to back of the canvas.
Any answer would be appreciated.
If you store the text, second image and first image in variables, you could just draw them on the canvas in the order you prefer. This means that, whenever there's some change in the image or text, you should clean the canvas and redraw everything.
Also, you may be interested in Compositing, since it allows you to decide where a new object is drawn in relation to the existing drawing (on top, behind, etc.)
Question:
Is canvas more suitable than svg in the following case?
Case:
I'm drawing a chart (using d3js library) similar to this one (but with much more data):
http://mbostock.github.com/d3/talk/20111116/iris-parallel.html
It's based on an svg and it works fine for several thousands of lines (up to 5000), adding more lines (svg path) decreases the performance dramatically (scrolling in the page becomes slow)
Keep in mind: That I need to add mouse events (which is handy in svg)
Generally svg is better suited for vector images, like in your example. However canvas has a lot of benefits in modern browsers such as hardware acceleration, so for drawing the lines, as long as zooming, panning ect. isn't required performance will be using canvas.
Mouse events can be a pain using canvas, since you have to manually keep track of everything, so with 5000+ points using canvas it wont be fun. The trade off however will be once the points are drawn, assuming you only draw them once the page will behave fine regardless of the number of lines, since they are all drawn to a raster image and aren't part of the DOM.
Honestly though the best way to find it is to test what you currently have using canvas.
When performance becomes a problem, switching to canvas might be an option. In this case you can draw the canvas once. Afterwards it's pretty much treated like an image. Drawing might take some time, but afterwards it can be scaled pretty quickly. Note that it is possible to draw a rendered SVG to a canvas using the context.drawImage method (example). So you could keep your SVG generation code to create an SVG in the background, and then draw it to the canvas.
But keep in mind that it won't scale as beautiful as an SVG as soon as it is on the canvas. When the user zooms in, it will get blurry or pixely, depending on how the browser scales graphics.
Click events on canvas can be handled in two ways. Either keep an array of click targets, and add an onclick event handler to the canvas. When a click occurs, iterate the array and check which one is closest to the click coordinates.
The other option is to use hit regions. These have to be defined as polygonal paths.
+1 to everything said above. I've seen some amazing performance increases when using canvas over SVG and over compositing images using the DOM.
About manipulating the canvas image with mouse events, I imagine the best approach for an image such as you are describing is to abstract it away using a library like the following:
http://paperjs.org
http://kineticjs.com
http://www.createjs.com/#!/EaselJS
Keep your code away from the canvas itself and let a library do the thinking for you.
What I am trying to do is create a game that has an extreme amount of zoom-ability on a canvas element. I would like to make use of the advantage that vector graphics have insofar as being able to be programmatically created at runtime, with the high performance of bitmap images.
What I would like to do is programmatically create the first-frame image of a game "sprite"... this would be a vector image. After the first frame though, I do not want to keep wasting CPU cycles on drawing the image though.. i would like to cache it as a bitmap/high performance image for that zoom level.
Following this, if the user zooms in by >20%, I then redraw the image with a higher level of detail vector image. As above, this vector image would then be cached and optimized.
As you can see here, this would be a pretty basic space ship.. I would first render it programmatically as a vector and then.. raster it I guess? Goal is to avoid wasting CPU.
If the user zooms in...
A new vector image of the same shape would be drawn, albeit with a much higher level of detail. This is basically a Level Of Detail system. In this case as well, after the initial programmatic draw, I would "raster" the image for maximum performance.
Does anyone have ideas on what tools I would need to make this a reality inside of a HTML canvas? (The rest of the game will be running inside of the canvas element..)
Thank you very much for your thoughts.
**Edit: I wanted to add... perhaps the route of rendering an image via SVG (programmatically), then pushing that png file into the canvas using drawimage(), might provide some success? Something similar? Hmm...
Check out that article , but it seems there is no standard method to do what you want and it may fail in IE.
http://svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back/#svg_to_canvas
You should perhaps go with an all SVG game , or provide a maximum zooming rate to your game and use big images as sprite assets. it would not have been a problem using flash,but i guess you wont go with flash anyway.
Maybe there is a framework that can translate SVG into a "canvas drawing sequence" but i would not bet on high performances in that case.
I managed to answer my own question.
The way to do this is to first create an SVG file, and then convert it to a PNG file on the client using "canvg". The PNG can be created at different levels of details based on what you want, and in this way you could create a dynamic LOD system.
Flash does something similar automatically by cashing a bitmap image of the SVG file... it's called "pre-rendering". If the SVG isn't scaled or the alpha isn't changed, flash will just use the bitmap instead (much faster then continuously re-rendering the SVG file, in complex cases). Size (and thus detail) of the PNG output can be modified however you like, and so pre-rendering could be done based on events as well.
From this information, I have decided to implement the LOD system such that SVG is used whilst the user is actively zooming (scaling the target "sprite"), and then as the zoom slows down, compute a PNG pre-render. Also, at extremely high levels of zoom, I simply use the SVG, as it is much easier for the CPU to compute SVG's at high resolution, then bitmap images that cover most of the screen. (just take a look at some of the HTML5 icon tests that put lots of icons on the screen... the bigger the icons are, the slower it runs).
Thanks very much to everyone's comments here and I hope that my question/answer has helped someone.
Is there any change to remove or resize selected object from Canvas without changing other design.
For example:- I drawn circles (just for help Circle1, circle2, circle3) .
circle1 will be bottom of other two circles. Now I want to remove circle2 or re-size. But it should not effect other circles.
And it there any change do this without using clear Canavas method.
It should work something like powerpoint design just draw and resize and delete.
I do not think that is possible, canvas is a bitmap object as far as I know and anything you draw on it updates the image.
If you like to use circle as an object you probably should look to SVG
Citation:
"once the rectangle is drawn, the fact that it was drawn is forgotten by the system. If its position were to be changed, the entire scene would need to be redrawn, including any objects that might have been covered by the rectangle."
You could try drawing the circles on separate canvases. In this case all you would have to do is to get rid of the Canvas element containing the circle itself.
Of course this means you'll have to do use some CSS trickery (namely z-index and absolute positioning)... It also incurs some overhead. This might be acceptable if you are dealing with an adequate amount of objects.
I agree with David about SVG. That might be a good option.
With Canvas you have to start setting up your own framework. I started a few simple tutorials on the subject, including resizing shapes.
In short, you're gonna have to start keeping track of each object you have drawn so you can re-draw them every time something moves.
One possibility is to use a canvas library like fabric.js, which allows you to draw and access canvas objects programmatically. Having canvas contents as a number of objects makes it easy to modify those objects dynamically, without affecting anything else; move, resize, delete, clone, change properties (color, opacity, etc.)
I've got an HTML5 canvas element in which a user can dynamically move, resize, and rotate a color photo.
I'd like the user to be able to toggle between grayscale and color.
I can think of two approaches, but neither is ideal:
1) Re-render the color image as grayscale (using a pixel-by-pixel loop) on every resize and rotate event (which could be several times a second)
2) Create a grayscale version server-side, and apply any canvas transformations to both images, but show only one of them at a time, depending on the toggle selection.
Can anyone think of a better solution than these two -- or, if no better solution exists, take a guess about which of the two would be the better choice?
Update: I implemented the method suggested below by Phrogz.
Create a second canvas (you don't even have to append it to the document) and use drawImage() to copy the color image onto it, and then (once) use getImageData()/putImageData() to make it greyscale.
Use this canvas as the source for future calls to drawImage() when you need the greyscale version, otherwise use the original image.
You are transforming the context, e.g. context.translate() / context.rotate() / context.scale(), to draw the image easily, right? There is no reason to keep rotating or resizing the source image as the user is transforming it.
You can also draw both images to two canvases (or a big one). That canvas probably doesn't even have to be added to the page, it can just be the element.
Then you draw the proper image from that canvas to the main canvas using the build-in methods. This will both be fast and not require server-side code.
You could even do the conversion to grayscale in a webworker, but that depends on if your clients do support it.