I'm currently working on a web-based drawing app, where I use the position of the pointer to generate a line. The speed determines the width of the line.
My problem is that the browser events does not produce clean data when getting the position, so the width becomes quite "jittery" other then being soft and smooth.
I'm wondering what is the best way to smooth out that sort of data as the drawing is being made? I was thinking on curve fitting, but I'm not sure which algorithm could work better in my case.
P.S. I'm not redrawing the line from start every single time on canvas, I'm only adding the "final part".
Thanks!
You might try pulling both the "smooth" and "simplify" functions out of paper.js (their MIT license allows this). It worked well for me in an edge detection project. Check it out here: http://paperjs.org/tutorials/paths/smoothing-simplifying-flattening.
Related
I am working on a drawing app as a personal project (currently living at http://draw.ist/) and I'd like to get the drawn strokes smooth around the edges but it seems the only way to accomplish this is using clearRect. However, clearRect also clears the canvas every time I start a new path and I'd like to prevent that so the canvas actually accumulates the strokes.
I've seen stuff about creating a secondary canvas to save strokes to or something so the clear doesn't wipe them (at least I think it works somewhat like that) however that method would require a lot of additional code that I'd like to avoid. Most recently I've tried saving the canvas as an imageURL on mouseup and then re-placing it with drawImage right after every clearRect, and this seems to do the trick nicely but it has some bizarre interactions with my eraser and straightline tools, as well as some flickering every time it loads in the saved canvas image.
There isn't necessarily any particular snippet of relevant code here, but for reference the entire site can be found at http://draw.ist/ (Controls: hold shift to draw straight lines, hold spacebar to erase, scroll mousewheel to change brush size)
I'd like all drawn lines to be smooth and have antialiasing but without using the "secondary canvas as memory" method IF POSSIBLE. I think what could help me here as well is understanding why exactly clearRect is necessary to apply antialiasing to strokes in canvas and how it works exactly in layman's terms. I greatly appreciate any assistance on this, whether it's actually helpful or not!
I'm using KineticJS to building an organization chart; one of the main requirements is the ability to have lines which are intelligent enough not to get overlapped by the shapes they are connecting. I have an algorithm for detecting the shortest path between two shapes, but I'm still stuck on how to route them around around any shapes in the way.
The best solution I've come up with so far is to use getIntersection() on every single point on the line to make sure that no point contains more than just the line; but after doing that (which itself feels more than a little wasteful), I'm still not sure what the best way of then routing around the obstacle is.
I'm open to the idea of switching libraries if there's another one which can accomplish this task easily, or even going back to a pure vanilla JS implementation if that's what it takes.
To work with your current solution, you would need to create vertical and horizontal "gutters" between each shape that you can use when drawing your connectors.
Think of these gutters as conduit that you run your connecting wires through.
You will likely have multiple and overlapping connectors in your gutters.
You could color code the connectors for easy identification by your users.
Alternatively:
This canvas diagraming library was created by frequent StackOverflow contributor, Simon Sarris:
http://www.nwoods.com/company/aboutus.htm
Alternatively:
JSPlumb is a javascript based diagamming library
http://jsplumbtoolkit.com/jquery/demo.html
I'm starting a web game, and I would like to know the best way to do it.
The game is a field of hexagons seen from the above, that can be rotated/inclined.
What's the best way to do it? What I was going to do was use a canvas and use 2d transforms to simulate 3d rotations, the problem is that:
The game must work on smartphones
For every rotation i must redraw all the canvas, and there could be 200 hexagons on the screen to redraw many times, so i think canvas are too expensive in terms of resources...
There's two ways I can think of:
Using canvas only. This means quite wide browser support, will have few quirks and generally "just work". Potential problems: Performance on low-end machines like you mentioned. But is rotating the game critical to gameplay? If not, you could consider turning that off on slow smartphones. Users will most likely not miss that feature if it's not important to gameplay.
A combination of canvas and CSS3 transforms (rotating cube example). Could give you better performance than pure canvas solution. Potential problems: requires "mixing" of techniques, which always means a risc of running into unexpected problems or quirks.
You should look at www.kineticjs.com
Canvas is the way to go for drawing 100's of shapes because it doesn't write to the DOM for every path like SVG does.
It has several examples where shapes are programmatically drawn in the 1000s. I recently used it for a similar animation here:
http://movable.pagodabox.com
Morning,
Over the past few months I have been tinkering with the HTML5 Canvas API and have had quite a lot of fun doing so.
I've gradually created a number of small games purely for teaching myself the do's and don'ts of game development. I am at a point where I am able to carry out basic collision detection, i.e. collisions between circles and platforms (fairly simple for most out there but it felt like quite an achievement when you first get it working, and even better when you understand what is actually going on). I know pixel collision detection is not for every game purely because in many scenarios you can achieve good enough results using the methods discussed above and this method is obviously quite expensive on resources.
But I just had a brainwave (It is more than likely somebody else has thought of this and I am way down the field but I've googled it and found nothing)....so here goes....
Would it possible to use/harness the "globalCompositeOperation" feature of canvas. My initial thoughts were to set its method to "xor" and then check the all pixels on the canvas for transparency, if a pixel is found there must be a collision. Right? Obviously at this point you need to work out which objects the pixel in question is occupied by and how to react but you would have to do this for other other techniques.
Saying that is the canvas already doing this collision detection behind the scenes in order to work out when shapes are overlapping? Would it be possible to extend upon this?
Any ideas?
Gary
The canvas doesn't do this automatically (probably b/c it is still in its infancy). easeljs takes this approach for mouse enter/leave events, and it is extremely inefficient. I am using an algorithmic approach to determining bounds. I then use that to see if the mouse is inside or outside of the shape. In theory, to implement hit detection this way, all you have to do is take all the points of both shapes, and see if they are ever in the other shape. If you want to see some of my code, just let me know
However, I will say that, although your way is very inefficient, it is globally applicable to any shape.
I made a demo on codepen which does the collision detection using an off screen canvas with globalCompositeOperation set to xor as you mentioned. The code is short and simple, and should have OK performance with smallish "collision canvases".
http://codepen.io/sakri/pen/nIiBq
if you are using a Xor mode fullscreen ,the second step is to getImageData of the screen, which is a high cost step, and next step is to find out which objects were involved in the collision.
No need to benchmark : it will be too slow.
I'd suggest rather you use the 'classical' bounding box test, then a test on the inner BBOxes of objects, and only after you'd go for pixels, locally.
By inner bounding box, i mean a rectangle for which you're sure to be completely inside your object, the reddish part in this example :
So use this mixed strategy :
- do a test on the bounding boxes of your objects.
- if there's a collision in between 2 BBoxes, perform an inner bounding box test : we are sure there's a collision if the sprite's inner bboxes overlaps.
- then you keep the pixel-perfect test only for the really problematic cases, and you need only to draw both sprites on a temporary canvas that has the size of the bigger sprite. You'll be able to perform a much much faster getImageData. At this step, you know which objects are involved in the collision.
Notice that you can draw the sprites with a scale, on a smaller canvas, to get faster getImageData at the cost of a lower resolution.
Be sure to disable smoothing, and i think that already a 8X8 canvas should be enough (it depends on average sprite speed in fact. If your sprites are slow, increase the resolution).
That way the data is 8 X 8 X 4 = 256 bytes big and you can keep a good frame-rate.
Rq also that, when deciding how you compute the inner BBox, you can allow a given number of empty pixels to get into that inner BBox, trading accuracy for speed.
I'm finishing up a drawing application that uses OpenGL ES 2.0 (WebGL) and JS. Things work pretty well unless I draw with very quick movements. See the image below:
This loop was drawn with a smooth motion, but because JS was only able to get mouse readings at specific locations, the result is faceted. This happens to a certain degree in Photoshop if you have mouse smoothing turned off, though obviously much less because PS has the ability to poll at a much higher rate.
So, I would like to implement some mouse smoothing, but I'm concerned about making sure it's very efficient so that it doesn't bog down the actual pixel drawing operations. I was originally thinking about using the mouse locations that JS is able to grab to generate splines and interpolate between readings to give a smoother result. I'm not sure if this is the best approach, though. If it is, how do I make sure I sample the correct locations on the intermediate spline? Most of the spline equations I've found don't have uniformly-distributed values for t = [0, 1].
Any help/guidance/advice would be very appreciated. Thanks!
Catmull-Rom might be a good one to try, if you haven't already.
http://www.mvps.org/directx/articles/catmull/
I'd pick a minimum segment length and divide up segments that are over that into 1+segmentLength/minSegmentLength sub-segments.