I am experimenting with HTML5 Canvases in an attempt to create some animation. My ultimate goal is to be able to animate a box to a particular location at whim, for now im just animating it across the screen. When I move it across the screen I geta black trail left behind, how do I clear this "dirty" section without removing the background grid?
A jsFiddle of the code is here
Two solutions
Redraw the background on the top of animation before moving it to the new location. This so called dirty sprite technique - faster - more complex.
Redraw the whole canvas between frames
If drawing the background is a complex operation just hold a prepared background buffered in another canvas for speed.
You have to clear what you've drawn if you don't want it to be visible. I assume you don't want to clear entire canvas to avoid redrawing grid and spending CPU cycles. You'll have to do this differently.
Possible solutions:
have two same onscreen canvases one over the other. Draw grid on canvas below and don't clear it. Clear part of top canvas and redraw on it.
have one on-screen and one off-screen canvas. Draw grid on off-screen canvas. Each time you animate, clear whole on-screen canvas, copy prepared grid from other one, and draw what you need over it.
Related
I was working on a real time whiteboard.
I want to create an Infinite canvas, which can be zoomed using the mouse wheel and panned using drag, using javascript.During the zoom and pan the items drawn on the canvas must also be affected. Is there a was to achieve this without using any external library?
Yes, but it'll take a bit of work. The general idea of what you'll do is the following:
You will need to keep track of the position of the "camera", as well as how close it is to the content - a zoom factor
You will need to attach event listeners to different mouse actions to cause the camera's state to change
When you drag or zoom, you will need to redraw your canvas with the new positions and sizes of all the content. Some math will have to be done to know what the new canvas content is.
There may or may not be certain performance issues you have to address if there's a lot of content on the canvas.
An alternative, possibly quicker approach, but maybe less powerful, would be to not use canvas, and use some CSS magic instead with plain HTML. The basic concept here is that you'll have a 0x0 div as your plane. That div will contain your content, which may include content such as custom SVGs. Each of its children will break out of the div, and will be positioned relative to it. When you drag, you just move the div (through transform: translate()). When you zoom, you just scale the div (through transform: scale()).
Some useful references if taking the second approach:
CSS transform - to move and scale the whiteboard
CSS position - to position content on the whiteboard, and for the general layout
CSS overflow - to crop the whiteboard
The canvas element itself won't be infinite, I guess that's clear enough. What will change when you drag and zoom is the mapping of the real coordinates of your whiteboard elements to the drawing coordinates on the canvas. There's some work to do with detecting the mouse events and doing the calculations for updating the mapping, so there are too many specifics to really put in an answer. But yes of course this is possible without an external library.
Basically canvas could not be set to infinite sized. All you can do is to draw the portion that should be visible in the canvas.
first of all you should store all the points you have drawn to an array.
whenever you pan your canvas , track the offset that you have panned. this offset values can be used to reposition your stored points in your canvas.
eg. suppose you have drawn a line from (50 , 50) to (100 , 100).
let the offsets be {x:0 , y:0}
x , y offsets shows how much x and y distances you have panned in total
then update the points by adding the offsets and redraw
https://github.com/TomHumphries/InfiniteCanvasWhiteboard
here is a simple html5 whiteboard created by Tom Humphries which has infinite zoom and pan.
I created an animation screen in javascript which is running about 20 frames per second. (I can do it faster, but 20fps is fine and have one eye on battery consumption.)
However, it can rain or get dark in the game, so I want to put a blue or grey hue over the scene.
The obvious idea is to have another canvas with a higher z value with the blue/grey hue on it. I can have that offscreen or onscreen depending on when it rains or gets dark.
Unfortunately, this is not a great solution as I need to capture touch/mouse events on the original canvas. This means the rain/dark/hue canvas would block the original canvas from receiving those events.
So is there any fast way of doing this? Again I want to keep an eye on battery consumption and speed. (I do not want to access and modify the image data of each pixel of the original canvas each frame.)
Is having the rain/dark canvas showing permantently but with transparent, blue or grey drawn once every 10 or so minutes (the typical gap between night/rain events). This could then capture the mouse events and the lower canvas has mouse/touch events turned off.
The only thing I do not like about that is when it is a clear day I would constantly have the gpu calculating colours for the screen when looking through a totally transparent canvas. That does not seem great.
If you really need to use 2 canvas, you can use the pointer-events: none CSS property so the clicks events go through the "filter" canvas.(Click through div to underlying elements)
If you are using a canvas library, there most likely is a layer system so you don't have to manage it by yourself.
I am not sure if it is possible. But let's say there are two images, one over another. Then I will have a circle size 100px around my cursor. So when I move the cursor over the image, it shows part of image that is under the front image. So the back image is hidden and visible only if the circle size 100px is over some part of it.
Unfortunately I have no code as I am not sure if it is possible to create.
However, any idea about it?
I would try actually stacking the hidden image above the visible one, then use HTML5's canvas to track your mouse cursor, clip a circular area underneath your cursor, then draw your image above it. This gives the illusion that you're "revealing" an underlying image, when in fact you're really revealing a small portion of an image stacked on top. Repeat this any time the user moves his/her cursor.
Here are some resources you might find useful in coding this:
HTML5 Canvas Clipping Region Tutorial
HTML5 Canvas Mouse Coordinates
Stack Overflow: clearing circular regions from HTML5 Canvas
This is about WEB development, Canvas, HTML5.
I'm developping a paint application with HTML5 Canvas and JQuery. You can draw several layers, and you got a dynamic zoom with a magnifying glass effect.
The architecture is multiple canvas :
background :
canvas-bg
layers :
layer0
layer1
layer2
...
layerN
tools :
ghost (to display a "ghost" line when the user want to draw a line. Releasing mouse confirm the draw)
magnify-layer
My problem is the zoom. To get the effect I want I redraw ALL LAYERS on the magnify-layer. Of course, when you are drawing a 2000*2000 picture, it is VERY slow. Moreoften, you can move the magnify-glass to zoom everywhere, and the redraw is recall on MouseMoveEvent.
To get it faster I only draw the little area under the glass (instead of entire layer). But it's still slow. How can I speed up know ?
illustration : http://imgur.com/hAtYsZi
You can see in the black circle the area is zoomed.
I used this code to start :
Démo : http://www.script-tutorials.com/demos/167/index.html
Try this...it might help.
I'm guessing you're doing traditional "magnifying": you're displaying at reduced resolution and then "magnifying" at full resolution.
So, when the user selects the magnifier tool, "flatten" all your layers onto another canvas.
Then cache the flat canvas to an image at 1/2 resolution. This becomes your unmagnified background.
Finally do your magnifying trick: Grabbing the appropriate pixels from the flattened canvas and show them in a floating magnifier.
Yes, there is some overhead+time in flattening your image, but that might be offset by the time it takes the user to select and position the magnifier.
I have 2 canvas in a div. I tried to translate one of the canvas, but it didn't work.
http://jsfiddle.net/VkbV5/ shows the case where i commented off the translation line:
this.innerElement2Ctx.translate(100,100);
But when I include the line, the small square disappeared. Why? If you run this page in browser and inspect the innerElement2, you will see that it didn't move at all, but the small square disappeared.
For your information, I need 2 canvas, because I am planning to attach mouse event to innerElement2.
Translating a context adjusts where the 0,0 point is for future drawing commands; scaling a context adjusts how large items draw on the canvas; rotating a context adjusts the direction that items are drawn. None of these context transformations adjust the size or position of the canvas box itself.
Here's an example I made of adjusting canvas transformation so that drawing the same commands allows the user to zoom and pan around a canvas drawing:
http://phrogz.net/tmp/canvas_zoom_to_cursor.html
If you want to move the placement of a canvas within your HTML page, use simple CSS placement as you would with any other element, e.g. a <div>.
If you want complex 2D or 3D transformations you can use cutting edge features of CSS for this (as supported by modern browsers). For example, see:
https://developer.mozilla.org/en/CSS/transform#CSS_transform_functions