Storing shapes in JavaScript array to redraw after some operation - javascript

I am developing an editor in html5. I have buttons for creating shapes when clicked, including triangle, rectangle, hexa, penta, heptagons, lines, and so on. Now I also want to perform operations on these shapes such as rotate, flip, undo, redo, ...etc. I want to save these drawn objects in a JavaScript array or something so I can create them after performing operations on the canvas, since individual shapes cannot be rotated or flipped in canvas, we have to redraw it. How can I achieve this? Thanks in advance.

I have a project where if you click on an image of a rectangle you can then draw a rectangle, click on an ellipse then you can draw an ellipse. My shapes are stored as objects which are then drawn using Canvas and can be flipped, rotated etc I have not implemented undo redo.
My project is at http://canvimation.github.com/
The source code for my project is at https://github.com/canvimation/canvimation.github.com
The master branch is the current working code. You are welcome to use any of the code or fork the project.

as you said, you have to clear your context and redraw your shapes any time you change them.
It's not mandatory to clear and redraw all the context, you can just redraw the region in which a shape is modified.
So you have to think your shapes as objects (in a OOP way) with their own properties and render method.
What I'd do is to create another class to apply transformations to a shape (a flip is just a -1 scale).
If you go this way, it could become a huge work (the more features you add, the more complexe your code becomes and the first design of your application may be re-think during the work).
What I can suggest to you is to use a framework that already does the job.
For example, cgSceneGraph is designed to let developers add their own rendering method and provides a lot of methods to manipulate them. I'm the designer of the framework, feel free to ask more on about how to apply transformations or create your own nodes (tutorials and examples are already on the website, but I'll please to help you).

Related

Canvas: reset pixels taken into consideration for composite operation

I am currently trying to build a relatively complex application using HTML5 Canvas objects and JS. To efficiently and realistically color areas I want to generate shadow maps based on image masks.
My problem is that the project is highly interactive, and I want to be as efficient as possible - so if anyhow possible I want to stay in one canvas. What I would now like to do is kinda "reset" the pixels taken into consideration for composite operations, so I can draw everything I want to draw onto my canvas, "reset" it (NOT clearing!), draw my mask and draw my shadow map (e. g. using source-in) on top of it.
Is this anyhow possible, or will I have to use a second canvas for this purpose?
Thanks!

Can this sequence be done in HTML5?

I certainly don't expect anyone to actually provide a working solution for this. My question at this point is a simple one: can this be done with an HTML5 canvas, or would I be spinning my wheels in the attempt?
I'm a programmer, but my forte is in PHP, JavaScript, traditional HTML, etc. ...I haven't had a chance to play with HTML5 yet.
The elements you see in the example, I can save out as individually as necessary. So to make the blocks rotate around the center, I was thinking I save a square image with the block in the appropriate corner, respectively. Then rotating the image would pivot around center appropriately, unless you can set a point of origin on an image a la PhotoShop.
The KineticJS library looks promising for this type of animation as well, but I'll leave the recommendations to you fine folks.
Anyway, here is the example I want to replicate:
I won't give any library recommendations for the same reasons that #Diodeus points out, but maybe I can help your selection process. What you're trying to do can be done multiple ways in the browser right now: Canvas, SVG, and/or CSS3 animations.
Your example above is basically a few vector graphics composed together with a gradient on your center "pie timer". Because of this I would lean towards using S V G, especially if you want to allow interactions with your component (each SVG element can have event handlers).
The canvas element is better for "pixel by pixel" control of your visual content on the page. Adding content in the canvas doesn't grow the DOM (like with SVG) so it will normally perform better, but you lose things like native event handlers and animations that you will end up having to re-implement on your own.
More about the choice between SVG and Canvas, and an SVG animation example
Once you have the components in the page, they'll need to be wired up and animated. The animation can be broken down into:
Scaling
Background color fading
Rotation
"Weird gradient pie timer" example with CSS3
These can be done with CSS animations, SVG animations, or with plain old javascript. The choice depends on what you'll be animating. If I was selecting a library I would want to find one that tried to use the newer methods (SVG/CSS3) when it can, and gracefully degrade when it cannot.
I would be weary of libraries that try to re-implement things that are already available natively in the browser. Relying more on the browser instead of your own code to do things like animations means that the browser can optimize its operations and use things like hardware acceleration to improve your performance.
Hopefully this can aid your library selection. Remember, libraries come and go all the time so don't get too attached to one. An ideal implementation should allow for you to easily swap out your animation or display code without having to touch other unrelated pieces.
Sure, it's not all that difficult when you break it down into pieces.
Here are some technologies and techniques to get you started.
You use Canvas by (1) displaying some drawings, (2) erasing, (3) displaying some new drawings
When you do this redrawing rapidly, you get animated effects like your image shows.
Html Canvas uses a context to draw with (think of it as the pen for the canvas)
drawing a path: context.beginPath + context.moveTo + context.lineTo will define a path that creates your "fan blade" polygons. You can use context.fillStyle to fill the polygons with you colors.
fading: context.globalAlpha will change the opacity of new drawings
rotating: context.translate(centerX,centerY) + context.rotate(radianAngle) will rotate new drawings (like your rotating polygons, your tick-marks, )
scaling: context.translate(centerX,centerY) + context.scale(scaleX,scaleY) will scale your polygons.
arcs: context.arc(centerX,centerY,radius,beginningAngle,endingAngle) will draw an arc with a specified centerpoint and sweeping from a beginning angle to an ending angle.
math: circleCircumferenceX = centerX+radius*Math.cos(radianAngle) circleCircumferenceY = centerY+radius*Math.sin(radianAngle) uses trigonometry to calculate an xy coordinate on the circumference of a circle. You can combine this trig + Math.random to place your "speckles" in an arc around your centerpoint.

Raphael cumulative vs absolute scaling/rotation/translation?

I'm trying to draw an interactive map in Javascript, using Raphael to do the heavy lifting.
The map background is a fairly complicated thing containing a grid, the map elements, labels, etc. On top of this I'm then going to draw the stuff the user is actually working with. Because the background is complex, I don't want to have to rerender it every frame. So, after drawing it I would like to reuse those drawing elements, merely changing the translation, rotation, scaling of the background as the user pans, zooms, etc.
Unfortunately I'm rather confused by Raphael's transformation primitives: they're not behaving as I would expect. If I call scale(), the scaling appears to apply to the original size of the drawing element; but translate() is cumulative, so it applies to the previous translation. rotate() can be either, as it has an option I can set...
Is it possible to do absolute translation? That is, to be able to specify the absolute coordinates of the new center of my objects (which are usually paths)? Failing that, is keeping track of the old location so I can apply a delta when I want to move it to the new location a reasonable way of doing this?
Or would I be better off simply rerendering the whole thing every frame? (I see suggestions that Raphael isn't good at transformations of complex drawings, as most of it is done in Javascript; looking at the SVG that's being produced, I see that the translation appears to be getting backed into the path data, which would bear this out...)
(BTW, FWIW I'm using the GWT Raphael interface for all this.)
You can use Element.attr to set absolute positions. Just change x and y properties:
myElement.attr("x", myX);
myElement.attr("y", myY);
I've used the raphael-zpd plugin with success. I'm not sure if that will plug into GWT - you could check out their source code and adapt it to your use case.
Project: https://github.com/somnidea/raphael-zpd
Source: https://github.com/somnidea/raphael-zpd/blob/master/raphael-zpd.js

How to resize or remove one object from canvas using Javascript?

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

Choosing right technology (SVG vs Canvas)

I'm writing an app for shape manipulation, such that after creating simple shapes the user can create more complex ones by clipping the shapes against each other (i.e. combining two circles together into a figure 8 stored using a single path rather than a group, or performing intersection of two circles to create a "bite" mark), and am trying to decide on a graphics library to use.
SVG seems to handle 80% of the functionality I need out of the box (shape storage, movement, rotation, scaling). The problem is that the other 20% (using clipping to create a new set of complex polygons) seems impossible to achieve without recreating SVG functionality in my own modules (I'd have to store the shape once for drawing inside SVG, and once for processing clipping myself). I could be wrong about SVG, but by reading about Raphael library (based on SVG), it seems like it only handles clipping using a rectangle, and even that clipping is temporary (it only renders part of the shape, but still stores entire shape to be rerendered once the clipping rectangle is moved). Perhaps I'm just confused about SVG standard, but even retrieving/parsing the paths to compute a new path using subsets of previous paths seems non-obvious in SVG (there is a Subpath() function, but I don't see anything to find the points of intersection of two polygon perimeters, or combine several subpaths into a single path).
As a result, Canvas seems like a better alternative since it doesn't introduce the extra overhead by keeping track of shapes I'd already have to keep track of to make my own clipping implementation work. Not only that, I've already implemented the polygon class that can be moved, rotated, and scaled. Canvas has some other issues, however (I'd have to implement my own redraw method, which I'm sure will not be as efficient as SVG one that takes advantage of browser-specific frameworks in Chrome and Firefox; and I'd have to accept IE incompatibility which is handled for free with libraries like Raphael).
Thanks
This may address what you're mentioning.
Clipping can be done using non-rectangular objects using the 'clipPath' element.
For example, I have element with id of 'clipper' that defines what to clip out, and a path that is subject to the clipping. Not sure if they intersect in this snippet.
<g clip-rule="nonzero">
<clipPath id="clipper">
<ellipse rx="70" ry="95" clip-rule="evenodd"/>
</clipPath>
<!-- stuff to be clipped -->
<path clip-path="url(#clipper)" d="M-100 0 a100 50"/>
</g>
This is just a snippet from something I have. Hope it helps.
Seems to me that you are trying to do 2D constructive geometry. Since SVG runs in retained mode, the objects you draw are stored and then the various operations performed. With Canvas you are running against a bit map so the changes are effected immediately. Since your users will in turn perform more operations on your simpler shapes to create ever more complex ones Canvas should in the long term be a better fit.
The only outstanding question is what will be done with those objects once your users are finished with them. If you zoom the image it will get the jaggies. SVG will avoid that problem but you trade-off with greater complexity and performance impact.
Both svg and canvas are a vector graphical technology.Each one having some different functionality.
Canvas
Canvas is a bitmap with an immediate modegraphics application programming interface (API) for drawing on it. Canvas is a “fire and forget” model that renders its graphics directly to its bitmap and then subsequently has no sense of the shapes that were drawn; only the resulting bitmap stays around.
More Information about canvas - http://www.queryhome.com/51054/about-html5-canvas
SVG
SVG is used to describe Scalable Vector Graphics
SVG is known as a retained mode graphics model persisting in an in-memory model. Analogous to HTML, SVG builds an object model of elements, attributes, and styles. When the element appears in an HTML5 document, it behaves like an inline block and is part of the HTML document tree.
More Information about SVG - http://www.queryhome.com/50869/about-svg-part-1
See here for more information about canvas vs svg in detail - Comparing svg vs canvas
You're right - you'll have to mathematically perform the clipping and creation of new shapes regardless of whether you use SVG or Canvas. I'm biased, it seems like it would be more useful to use SVG since you also get things like DOM events on the shapes (mouse, dragging) and serialization into a graphical format for free.

Categories

Resources