html5 - How to check for shapes drawn on canvas? - html

I have made a webpage on which there's a canvas on which we can draw freehandly. Now I wanted to know that is there's a way to find that the user has now drawn a "square", "circle" or "rectangle"? I mean that if I draw a square on the canvas, how can I write the code to check that I have drawn a square?

Not many details to work with from you.
Also, “freehand” means very imprecise shapes.
So here’s a generic answer to determine your shape:
Determine the bounding box of a freehand shape (minX,maxX,minY,maxY).
Test#1: if (maxX-minX) is largely different from (maxY-minY), then you have a rectangle.
Test#2: Walk one of corners towards the center. If you quickly cross part of the drawing, you have a square.
By process of elimination, if Test#1 and Test#2 fail, then you have a circle.

Related

what is it that you can do with canvas and not with SVG?

I am working on project I need to choose between the SVG and Canvas. I am finding SVG best at most of the things.
Are there anythings that you can not do with the SVG but you can with Canvas?
First,
If you already have invested time in the SVG learning curve, you might well complete your project without Canvas because these 2 elements do remarkably similar things. Canvas has a fairly large & steep learning curve that you might want to avoid "mid-project".
Contrary to popular opinion...Both Canvas and SVG use vector drawing commands!
They use vector commands to paint lines and curves on their drawing surfaces. Both Canvas and SVG render those drawings onto their element surfaces as pixels.
And...
Both Canvas and SVG can transform (offset, rotate and scale) their drawings. Both Canvas and SVG can apply style to their drawings (fill color, stroke color, opacity, etc).
But...
SVG goes one step further and "remembers" all the drawing commands. This means SVG can reissue those drawing commands even when scaling. So SVG is ideal for drawings that must be scaled without becoming "jaggy". You can even use CSS to re-style your drawings (change colors, opacity, position, rotation, etc). That's often very useful. For example, you can make an SVG leopard change the color of its spots with CSS!
Canvas just "draws and forgets" -- it remembers nothing about what or where it's drawn. As such, it's a lighter element. You say: "But canvas does all those games with moving players". With canvas, the programming practice is to erase the canvas and redraw any shapes in their new positions. This gives the illusion that the shapes are being commanded to move (which they are not). Canvas is built to be extremely fast at these redraws and will easily redraw modestly complex game scenes at 60 frames per second. This speed comes at the cost. You must "remember" where your scene elements are so you can later re-render them in their new positions and with their new stylings. (No simple CSS ability to make a canvas leopard change its spots).
SVG drawings come with the traditional mouse events already built in. Canvas only fires the traditional mouse events on the canvas as a whole and not on individual drawings (because canvas forgets about the shapes it's drawn). Therefore, if you want to get mouse events related to an individual canvas shape you must (1) Remember where you drew your shapes (2) listen for the mouse event on the whole canvas, (3) check if the mouse is inside any shape (this is easily done mathematically) and then handle the mouse event for your discovered shape. Canvas elements require more code to impliment.
IMHO, one particular use-case where canvas shines:
In addition to these functional differences, Canvas lets you examine and change any pixel on the canvas surface. In particular, this valuable pixel information lets you do some nice tasks with images:
Recolor any part of an image at the pixel level (if you use HSL you can even recolor an image while retaining the important Lighting & Saturation so the result doesn't look like someone slapped paint on the image),
"Knockout" the background around a person/item in an image,
Detect and Floodfill part of an image (eg, change the color of a user-clicked flower petal from green to yellow -- just that clicked petal!),
Do Perspective warping (e.g. wrap an image around the curve of a cup),
Examine an image for content (eg. facial recognition),
Answer questions about an image: Is there a car parked in this image of my parking spot?,
Apply standard image filters (grayscale, sepia, etc)
Apply any exotic image filter you can dream up (Sobel Edge Detection),
Combine images. If dear Grandma Sue couldn't make it to the family reunion, just "photoshop" her into the reunion image. Don't like Cousin Phil -- just "photoshop him out,
Play a video / Grab a frame from a video,
Export the canvas content as a .jpg | .png image (you can even optionally crop or annotate the image and export the result as a new image),
Many more image pixel manipulations that haven't come to mind!
Canvas is a pixel manipulation element.
SVG is vector element container.
I feel distinction between these two is outside the scope of StackOverflow to dicuss, as it is related to computer art basics, not programming and there is a lot of information available if not in search engines then in WikiPedia. For example one would use pixel-based media for pixel games.

Shape with inner stroke

By default, adding a Stroke to a Shape in WPF / WinRT XAML creates an outline that is centered around the edges, meaning that half of the outline is outside the shape. But I need to create a shape with stroke und no fill that has the same silhouette as the shape with fill and no stroke. Is there an easy way to change the stroke so that the whole outline is inside?
I could create an OpacityMask that covers the inverted shape, but OpacityMasks are not supported in WinRT XAML. I could also create a smaller shape via inward polygon buffering (An algorithm for inflating/deflating (offsetting, buffering) polygons), but I was hoping for a simpler solution, e.g. a simple property to change the stroke to "inside".
I've really been trying to come up with an answer to this one. Over and over every attempt has some type of limitation. I'm afraid the answer is, you cannot do this - not with dynamic vectors at least. You can always create an image to simulate it. But that sucks.

Canvas: Mouse Events

I know it is not possible to add eventhandlers to specific circles or rectangles in canvas. But there are some nice frameworks like EaselJS, KineticJS, Paper.js, Fabric.js that support the eventhandling on specific elements.
Can someone explain me how do they work?
I think there are only two solutions.
1. You create for each element a new canvas region and put them on each other. In this way you can give each region an event handler.
2. You have only one canvas region and one event handler. In this way you have to do complex mathematical calculations to find out if a specific element was clicked. If you have only circles or rectangles, this solution might be easy. But if you have path with lots of curves, this solution is quite difficult.
I don't want to use the libraries. So it would be nice, if someone can help me.
Here's a BRIEF summary of how canvas drawing libraries work
An unaltered canvas is just a big bitmap. Once you draw shapes on the canvas, they are unaccessible, forgotten pixels.
Canvas drawing libraries store all your shapes into “retained” objects. Each shape object has sufficient information about itself to allow the drawing library to redraw it whenever necessary.
The canvas drawing libraries are the "controllers" for objects. The libraries have the algorithms necessary to track, manipulate and redraw all shape objects as necessary.
The following information is retained about every shape object:
Basic identification
ID,
Shape name
Parent or Container
Inherent properties of the shape:
Rectangular shapes( rect, image, text) know width and height.
Circular shapes (circles, elipses, regular polygons, stars) know radius and sidecount.
Lines know length.
Curved shapes (arcs, beziers, paths) know anchor points and control points.
Text also knows…well, the text!
Images also know their pixel data (usually stored in javascript Image objects)
Transformational information:
Starting X/Y coordinate
Translations—accumulated movements off the starting coordinate.
Rotations—accumulated rotations of this shape (usually in radians).
Scalings—accumulated resizings
Other transforms (less common) are skews and warps
Layering information—the current z-index
Styling information:
StrokeColor,
StrokeWidth,
FillColor,
Opacity,
isVisible,
lineCaps,
cornerRadius
Tracking abilities:
Bounding box—the smallest rectangle that completely contains this shape
This is used for “hit testing” to see if the mouse is inside this object (for selecting and dragging)
If you don't want to use a library, you may find my answer in this thread helpful. As markE says once the canvas is written to there is no way of tracking that data (unless you care to loop through each individual pixel and test its colour; though that is only really useful for pixel level collision detection).

Canvas Arc or QuadCurve OnMouseOver function possible?

I have a round diagram for which I need to display a div when users hover over each section (arcs).
I was going to use canvas: http://www.html5canvastutorials.com/labs/html5-canvas-planets-image-map/
But I have not been able to draw an arc in canvas - or should I use any other technology to create this?
You can draw an arc in HTML5 Canvas, using either the arc() or arcTo() methods of the context.
You can see an example of arcs drawn in HTML5 Canvas in this little game I wrote:
http://phrogz.net/tmp/connections.html
The game concept is not mine, just the implementation.
Note that with a squared-off line cap style, you can even draw wedges (circle segments) with a single arc command.

html5 canvas shapes fill

I have a basic paint application on a canvas, and I want to make a drawing-border and by that create a stencil. In other words, I want to make a shape, and then I want the user to be able to draw only inside it, even when he tries to draw outside.
Do you have any idea how can i do it?
thanks
This can be achieved by making a clipping region. The basic idea is that there is a path on the canvas that all drawing is constrained to.
Make the shape, and instead of calling stroke() or fill(), call clip()
If you don't quite get how clipping regions work, there are a few examples around.