Basic SVG+CSS Downloading Animation

Since finding out about SVG graphics years ago, I have been a fan. I love how they look on high resolution screens compared to raster graphics. Until now, I have not had the chance to try out using them for animations. One of my projects required an animation to show an item that is in the process of being downloaded. Rather then using an animated GIF, I opted to go with an animated SVG.

I wanted something that would look familiar to users as a loading icon. So I started with a basic completing circle animation. I also wanted to add a bit more context to the animation so I added a downward arrow and a horizontal line. My hope is that users will connect this symbol with the action of downloading something. I have shown the icon to a few people they had no trouble understanding that it indicated a downloading item. A wider audience may disagree, but feel free to judge for yourself.

Now on to the technical aspect. SVG animations require that the SVG XML be embedded in the document not added as a linked file from an image tag. For a simple image, like mine, this is easy to do without half the document being image code. For a more complex drawing this won’t be the case and I won’t get into that here.

I created the SVG elements in Inkscape and coped the raw image instruction for the elements out of the file using a text editor. I then placed the SVG instructions within a G tag to group the separate objects and make it possible to easily transform my new icon.

The next piece is the CSS. I started by creating three selectors that allow me set three states of my icon: not downloaded, downloading and downloaded. They each set the icon’s color and play state.

#download {
   stroke:#000;
   fill: #000;
}

#downloaded {
   stroke:#00bbe0;
   fill: #00bbe0;
   -webkit-animation-play-state: paused;
   animation-play-state: paused;
}

#downloading {
   stroke:#00bbe0;
   fill: #00bbe0;
}

Next we create a selector for circle outline that gives instructions for hiding part of the the completed circle. To create the completing circle animation we will use a transparent dash stroke and change it’s offset to show a varied completeness of the circle.

The stroke-dasharray value has to be longer than the circumference of the outer circle. I chose a value of 500 so if the whole animation was made a bit larger, the animation would still work as designed. The animation value is how long the transition between empty to full will take to complete. I chose two seconds as it seems to be a comfortable speed.

Since this is an animation a keyframe selector must be specified. In this example the keyframe selector has two sub-selectors: to and from. These specify the starting and ending states of the animation. Combined with the stroke-dashoffset declaration we specify the starting position of our transparent dash. For this I am transitioning from a larger value to a smaller one, to make the circle fill clockwise. Swapping the values makes the animation go in reverse. For the current size of the drawing a difference of about 100 is required.

Below you can see the final product

See the Pen Basic SVG+CSS Downloading Animation by Alec Dhuse (@alecdhuse) on CodePen.


A Few More Notes:

Compatibility of the CSS declarations for animations is mixed, which leads to many duplicate declarations in order to make animations cross browser compatible.

Second, is that if the CSS specifies specific animation declarations and the general animation declaration, the more specific must be placed after the general. Like this:

...
 animation: show 2s;
 animation-iteration-count: infinite;
...

Folding Map goes open source!

Screenshot of the Folding Map application.

Screenshot of the Folding Map application.

Folding Map is a project that I have been working on for several years.  I’ve used it to create maps of villages in Cameroon, trail maps in the Pacific NorthWest and most recently for climbing maps on my new site TopoHawk.

It’s come a long ways since its humble beginnings and now it’s time to share my work with the world.  While it doesn’t have the features of QGIS it works well to create simple maps, visualizations or to export for use on the web.

The source code is available from GitHub so check it out.  Issue tracking will also be handled there so feel free to request features or report problems or contribute to the project.

Leaflet Climbing Maps

Screen Capture of my Leaflet Smith Rock climbing map.I have recently started a project to test out Leaflet.  For those of you not familiar with Leaflet; It’s a Javascript framework for creating interactive maps using a variety of data.  It’s open source and extendable through plugins.

For this project I created an interactive map of one of my favorite climbing areas Smith Rock.  The map’s focus is to show the locations of various climbing areas and routes in those areas.  While the information on this map is by no means complete, it serves for my goal of learning to use Leaflet.  You can check out the full page map here.

The map itself contains two layers:  the base tile layer and a vector layer containing the routes and climbing areas.  I created the tile layer using Folding Map, another one of my projects that I hope to release soon.  The tile layer uses vector data from OpenStreetMaps.org as well as traces from public domain aerial photos and data gathered from my handheld GPS unit.  The vector layer contains the various climbing areas, routes and other interactive features.  These were also collected from my GPS unit and some filled in from my memory.

The vector point data is stored in a js file with the each of the point types (sport routes, trad routes, etc) as a different variable.  This works well because of the small about of points I have.  If I were to scale up this project I would store the points in a database and write a script to output that information to GeoJSON so it can easily be imported into Leaflet.

I started with the basic leaflet map but I quickly decided that I wanted more functionality.  So I added a few customizations:  The climbing areas, marked in orange, automatically zoom in to the area’s routes when clicked, vector object have a viewable range based off of the map’s zoom level and the climbing areas have static labels to easily locate them.

The auto zooming feature was pretty simple to implement.  Each of the climbing areas’ GeoJSON features has a property I added called clickZoomTo.  This property holds an integer specifying the zoom level the map should be set to when that feature is clicked.  The actual code to change to zoom is a function that overrides the CircleMarkers on click function with code to set the map’s view to the desired zoom and center on the CircleMarker’s coordinates.

To implement the the objects’ viewable range I created a function to add all of the GeoJSON generated points to a LayerGroup dependant on the current zoom level.  Each of the GeoJSON features has a property maxZoom and minZoom that get compared against the map’s current zoom.  If the current zoom is within the feature’s visible range it gets added to the LayerGroup.  To keep objects from stacking up the LayerGroup is cleared every time the zoom changes.

Finally I wanted the various walls and climbing areas to have static labels.  Because this feature does not exist by default in Leaflet I used the Leaflet.label plugin.  After adding this plugin, I ran into a great deal of trouble trying to get static labels to show up for the map’s CircleMarkers.  It turns out that Leaflet.label does not support labels for CircleMarkers.  After searching for an alternative plugin and not finding one; I decided to fork the Leaflet.label plugin and add the functionality I was looking for.  I have submitted a pull request, but as of the posting of this blog post it has not been accepted.  Anyone can view my changed on my github.

All and all I am quite pleased with the Leaflet framework; it’s easy to use and well documented.  I was able to get a basic map up an running in about 20 minutes and further customized in a few hours.

Update:

I have continued this project, making a more elaborate map that can be found here: http://topohawk.com/destination/Smith-Rock.

Java GeoJSON Reader

I have recently started working on a Java based GeoJSON reader.  It has the ability to read plain JSON, but this version creates Java objects for the various GeoJSON objects defined in the GeoJSON specification: coordinate, point, line, polygon, etc.  This makes importing and using GeoJSON in a Java program much easier.

I’ve just committed an initial working version and I’m planning to update it in the near future.  I would like to eventually add an easy way to build the GeoJSON objects and output them to a file as well.

Check out the project on GitHub.