How to animate shapes on top of a leaflet map - javascript

I'm new to leaflet, looking for some advice.
I'd like to create an animation of a marker of some sort (for example, an html5 filled arc or shape) to replay GPS tracks on a map. I may want several animated markers and I want to stay flexible with the behavior and performance. Can anyone recommend a good way to go about creating this type of animation?
It looks like I could create a canvas layer (L.TileLayer.Canvas) and draw on it using a technique for linear animation (e.g. http://www.html5canvastutorials.com/advanced/html5-canvas-linear-motion-animation/), but I'm not yet sure if this works, or if I need to call redraw() and how the performance would be. Or I could try and make customer markers and move them by setting the lat/lon on them at some interval.
Has anyone come across this and can recommend a solution (above ideas or other)? Ideally as I change zoom levels, the animation will "scale" and have good performance. Thanks!

The RaphaelLayer plugin lets you create some pretty fancy animations:
http://dynmeth.github.com/RaphaelLayer/

yes there are a couple of ways to approach the problem...
drawing onto an interactive map is challenging because you need to recalculate your position on pan and zoom events; in addition to managing your actual animation.
This is an excellent example using the D3 library to manage the animation in a continuous loop, you may be a able to modify the code for multiple animations.
http://zevross.com/blog/2014/09/30/use-the-amazing-d3-library-to-animate-a-path-on-a-leaflet-map/
If you want a little more of the knuts and bolts of how the drawing process works then this project might be a better starting point
http://bl.ocks.org/Sumbera/11114288#L.CanvasOverlay.js
This grabs the overlay pane (a leaflet canvas which you can draw on) and... draws on it...
and you will absolutely want to check out this link which describes the drawing process for an interactive map

Related

Change layer z-index in leaflet

I'm using leaflet to trace underground pipes which I create using the polyline methods.
Since the pipes/lines can sometimes overlap I need to be able to highlight the selected line which requires switching the z-index of the line.
Now it seems that leaflet does offer a setZIndex method, but it's not available for individual layers - so I can change it over an entire featureGroup, but that is less helfpul - and making every line into its own separate featureGroup feels like an overkill.
Any suggestions?
You could create another layer with a superior z-index that would be empty at start. When the mouse is going over a feature, copy the feature into that layer. When the mouse is going out, just remove it from the layer.
It might be a little bit cpu demanding, so I suggest you to debounce the mouseover function in order to make the mouse to wait 1-2 seconds over a feature before copying it into the top layer.
As IvanSanchez noted in a comment, the correct answer seems to be a method called bringToFront.

Can I do a 1000% zoom with JavaScript vector art?

I'm planning to commission a developer to help me create a simple mathematical art piece. I'm wondering if the following can be accomplished with JavaScript vector art, and if not, what approach you would recommend.
The image will start off with some intersecting lines forming a shape. This is essentially an image zoomed in 1000% or more, and the user can scroll to zoom out until the full image fits the width of the screen.
Naturally, an actual image of this size would be huge, so I'm thinking it would be better to draw it programmatically, which might also enable the line thickness to scale up a bit as you zoom out, so that they're not nearly invisible when zoomed all the way out. The image can not look pixellated when zoomed all the way in, but achieving this with some “trickery” like swapping out images is also ok.
Example:
Basically the reverse of zoom.it but at a significantly larger scale.
http://zoom.it/
Some libraries I've looked at are:
paper.js
fabric.js
leaflet.js
raphael.js
How can an extreme zoomout like this be accomplished?
You are definitely on the right track. I think what you want is very possible on the web using HTML5. You are correct in that the easiest/best performing implementation of this would be using vector graphics. You can use image tiles, however the preprocessing and bandwidth requirements for tiling get large very quickly.
Here are some of my thoughts from working with some of the libraries you listed:
Leaflet.js - Leaflet supports both drawing SVG elements as well as image tiling (if you wanted to go that approach). Leaflet is also "mobile first" in that it supports things such as pinch zooming and double tap to zoom out of the box. Scroll zooming is also supported out of the box. Getting something up and going with Leaflet is simple. As far as I know Leaflet is writing SVG to the DOM; which is something to keep in mind.
Raphael - Raphael is capable of what you want, however you may need to implement zooming aspects yourself. This is definitely possible to do and shouldn't be too difficult, but something to keep in mind. Raphael will write SVG elements to the DOM; which can get a bit unruly if you have many many SVG elements. However, you may be able to optimize this and create/destroy elements as you are zooming.
Paper and Fabric - These both appear to render SVG to Canvas (different than writing SVG to the DOM). These both look really powerful, and seem to have good APIs for zooming. You would likely still need to hook up scroll/touch gestures to get zooming to work the way you want. These both should perform very well as they are using lower level APIs which should bypass many issues you might have with doing this in the DOM.

OpenLayers as a large (changing and growing) image viewer

Basically, what I'm trying to do is use a map viewer as an image viewer with the same sort of efficient tile-loading, zoom/pan awesomeness without having to build it myself.
Specifically, I need an image viewer that will allow the image to grow and change while not altering the coordinates of any older (unchanged) tiles. This means that the center point (0,0), where the image started growing from, must always remain (0,0). So I'm looking for a library that will allow me to use a very basic Cartesian coordinate system (no map projection!), which will ask for tiles infinitely in all directions with no repetition (as opposed to how map libraries just ignore y-axis above and below the map, but the x axis repeats).
There's another catch. I need zoom level 0 to be zoomed in all the way. Since the image is constantly growing, there's no way to tell what the max zoom level will be, and the coordinates need to be based on the base image layer tiles so that every tile in zoom level z contains 2^z base layer tiles.
I am wondering if this is possible with OpenLayers and how to do it. If it's not, any suggestions of other (open-source javascript) libraries that can do this would be very appreciated! I've tried playing around with Polymaps, but the documentation is lacking too much for me to be able to tell if it will work. So far no luck.
Please let me know if none of this made sense, and I'll try to include some images or better explanations. Thanks!
I ended up using Polymaps after all, since I like it more than OpenLayers, because it's faster and has much smoother scrolling and panning. I wasn't able to do exactly what I wanted, but what I did was close enough.
I ended up writing my own layer (based on the po.image() layer), which disabled infinite horizontal looping of the map. I then wrote my own version of po.url() that modified the requests going to the server for tiles so that zooming was reversed (I just arbitrarily picked a 'max' zoom of 20, then when making a request subtract the zoom level from 20) and the x and y coordinates were converted to cartesian coordinates from the standard row, column coordinates Polymaps uses, based on the zoom level and the map centered at (0,0).
If anyone is interested in the code I can post it here. Let me know!
EDIT: I've posted the code on github at https://github.com/camupod/polymaps
The relevant files are src/Backwards* and examples/backwards (though it actually doesn't work, you might be able to clean some information about how it should work).

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

Alternatives to AREA tag when creating Javascript map

I have an extremely large picture of a map. Now I want to create a Map UI where the user can click to highlight regions and also have the functionality to zoom into the map.
Is the AREA tag the only way to go at this problem? My only problem is when I zoom in the map, the will be enlarged and so will the image that it contains, but how would I expand the AREA coordinates according to my zoom level? Is there a good approach for going at this problem?
AREA is the only way to represent polygons, unfortunately. You can read your coordinates from the AREA tag, scale them, and write them back. Rounding overlaps are a pain to deal with though.
One alternative is to use the BING maps API, which allows custom overlays. You need to create an overlay for each zoom level though.
Apply css to AREA MAP
I suggest SVG there, which would also solve your zoom problem. The only complication is that IE8 and below won't support it, and IE9 isn't being pushed through Windows Update to non-beta users yet.
Simple option: ImageMapster figures out most image area map things for you on the fly. IE6+, needs jQuery.
More complex, more powerful option: Raphael.js enables you to create fully controllable fully scalable SVG vector graphics in everything from IE6+ (doesn't need Flash). Bit of a steep learning curve, but it's very powerful.

Categories

Resources