I'm currently implementing a HTML canvas based webapp that features panning. Is there a way to use an auxiliary buffer to hold the presently visible area so when I pan I don't have to redraw the whole canvas and only have to draw the newly visible areas?
See my previous response to a related question: What is the fastest way to move a rectangular (pixel) region inside a HTML5 canvas element
Just draw the entire canvas in a div that has overflow:hidden and implement panning as re-positioning the top and left of the canvas within that div. It is much faster. And don't worry about drawing canvases tens of thousands of pixels wide/tall, I've successfully used this on very-very large and complex HTML and SVG elements.
Take a look at the pixel manipulation API.
http://dev.w3.org/html5/2dcontext/#pixel-manipulation
Related
i'm a beginner in Javascript so please bear with me.
Basically I'm making a sandbox drawing facility for a website using Javascript. And this is done using the canvas. What I need to do is to be able to resize the canvas dynamically but at the same time keep everything on the canvas to scale.
I don't think this question has been asked before. It seems trivial but I currently have all my objects on the canvas defined in absolute coordinates. I also have mouse events to use to draw things. And when I want to enlarge the canvas (by doubling the size say). All the objects inside won't be enlarged properly to scale and the mouse coordinate system would be messed up too.
Only solution i can think of is add a scale factor to ALL my drawing parts, but this is very tricky with a lot of code. Is there a better way?
If you don't mind jaggies on your double-sized canvas drawings then you can simply use CSS to double-size your canvas. Then divide every incoming mouseEvent coordinate by 2.
If you don't want jaggies on your double-sized canvas then:
Double-size the canvas element: canvas.width*=2 and canvas.height*=2 This automatically erases all canvas content.
Scale up the canvas: context.scale(2,2)
Redraw all your drawing parts using the unchanged original coordinates. A happy note: you do not have to scale any of your drawing coordinates -- context.scale automatically does that for you.
Divide every incoming mouseEvent coordinate by 2.
What I'm trying to do is include what is under my canvas object in the page as part of the image when I saved what is inside the canvas.
I have an application that creates a canvas and lets you draw with the mouse on it. This drawing functionality is in place so you could draw on a page as if they were notes, so after I can save the image or page with the "notes" I draw on it.
So far I'm able to save what is drown in the canvas but because the background is not part of the canvas I can't get to save it together. I tried experimenting with html2canvas.js but it doesn't work in my case because it takes the DOM object an redraw them into the canvas, it doesn't take just what is under the canvas to be part if the final image.
I would like to know if there is a way to do this, or somehow capture the pixels in that area and redraw them as part of the canvas when I'm creating it.
Thanks a lot in advance!
Possibly a duplicate, but I'll give you a very short answer; you can't (unless you do something like html2canvas, where it transposes the DOM onto a canvas element)
This is by design. If you could it would be a security flaw. Scripts are not allowed to create images out of arbitrary stuff on a person's screen. If you search for "html canvas security rules" you'll find more information on why this is disallowed.
Unfortunately, HTML2Canvas (or something like it) is the only option, but it's only part of the puzzle. To get the effect you want, you need to create another canvas to composite the output from HTML2Canvas and the drawing canvas. You'll need to offset the output of HTML2Canvas to the position of your drawing canvas, and then draw the imagedata from your drawing canvas on top of it. Then you can use the imagedata from the compositing canvas as your output.
I made a speedtest to compare Snap.svg (SVG) to FabricJS (CANVAS):
http://jsbin.com/tadec/7 function dummy().
In Chrome SVG renders in 120 ms, while CANVAS renders in 1100 ms. SVG is 9x faster than CANVAS.
Fabricjs.com page says in this example that Raphael takes 225 ms and Fabric takes 97 ms (parsing: 80, rendering: 17).
I have had an impression (after reading fabricjs.com and paperjs.org) that FabricJS and more generally Canvas is faster than SVG.
My speed test claims that SVG is significantly faster than Canvas (at least Snap.svg seems to be significantly faster than FabricJS).
Why FabricJS is so slow in my test? Have I made some mistake in comparison, because I'm surprised that SVG seems to be faster than Canvas in my speed test.
EDIT: My question is two-parted: Why rendering speed is so much slower in FabricJS and why dragging speed as well?
Your benchmark is broken in my opinion, because beside measuring drawing to canvas you are measuring parsing of a huge string containing a path, over and over again. Separate this code out of the loop and you should get more reliable results.
Measurements that are provided for canvas libraries are provided for drawing, not for parsing or other pre-processing work. If you use canvas like you use SVG, then yes, it will be slower. It is not intended to be used like SVG. FabricJS provides a way to do that, but it is not optimal. One solution would be to parse path once, and then use same path over and over instead of parsing it every time.
Also, measurements are given probably for drawing a canvas, not for interaction with parts. As you say in comments, rendering may be improved, but why does dragging a shape take so much longer? Because:
maybe path is being reparsed on each redraw (not sure how FabricJS works)
because SVG can redraw only certain parts of image that you are moving, and canvas is usually redrawn completely. Why? Because you can't "erase" part of canvas where a shape used to be. So entire canvas is erased, and new positions are redrawn.
Why do then people say canvas is faster than SVG for such scenarios? Because it is if you use it properly. It will be more work, but it will work much faster.
Don't use SVG paths for drawing shapes, or use simple paths and cache them
Cache shapes which you use often into off-screen (hidden canvas) and then copy from that canvas onto visible canvas when needed
If you have multiple independant layers of an image (for example 3 layers in a game, if you have background sky which is moving, background mountains which are moving slower and a character), use multiple canvases. Put canvases one over another, draw sky on the bottom canvas, draw mountains on second canvas and draw character on top canvas. That way, when character on top canvas moves, you don't have to redraw entire background.
I hope my answer is useful for you :)
If I change the cursor of a page into a 'flashlight' (say, a circle), and I want to reveal an image only when passing the light (the circle) over it, what would be the best way to go about this? Using css clip? But then it can only do rectangles, so I'd have to use canvas? Perhaps there's an easy way to intersect the two images?
You can do this with a canvas easily.
Here's an example:
http://jsfiddle.net/gfZ5C/
On every mouse move, we clear the canvas, redraw the image, make a clipping region that is a circle cut out of a rectangle, and draw black on the entire canvas (which will draw only on the clipping region)
Make sense?
There are a lot of ways to achieve this effect and similar effects. You can also make much fancier light sources with a bit of canvas sorcery. See for instance my answer here: Canvas - Fill a rectangle in all areas that are fully transparent
I know you can layer canvases on top of each other just as if you were making an image in Photoshop but are you able put canvas objects above and below each other or side-by-side?
I'm looking to draw a graph which allows you to choose a space and depending on what color choice you have it'll change the block based on that choice.
Here's my thought:
Canvas #1 - Draw Graph Paper
Canvas #2 - Right side of Canvas #1 - Tab that has 4 color choices. I'd figure out the x-y of these to grab the color based on the color image. Canvas 1 block color would reflect this choice.
Is this a good way of going about this implementation?
Yes you can place canvases above, below and side-by-side each other. A canvas is an HTML element and can be positioned like any other using CSS.
I'd probably try to avoid using a canvas for your color choice tab unless it's absolutely necessary for some reason you haven't mentioned. If you use standard DOM elements instead you'll be able to bind to the click event directly rather than having to figure out the mouse position relative to graphics in your canvas.
Here are some good reasons not to use canvas to create UI components.