Geojson map for web

This article demonstrates use of a Leaflet map with geojson data and how to publish it on a web page.

Newsmap with markers only

newsmap.zip

Newsmap with geojson, links and images

If you want to use any of these features you must use this map.

NewsmapGeojson.zip

Centering and zooming the map.

Setting the map centre and zoom level is how you decide what the user will see. Consider your audience and how well you think they will know the area shown in the map. If an earthquake hit a Indonesia and I was targeting a Norwegian audience I would use a much lower zoom level to show more of the surroundings, I would probably include Australia and India on the map to help the user place the incident in the world. If the audience was in Indonesia I would instead show the affected region assuming they know basic geography about their own country. The following code is on line 73 in the file. Alter the lat & long values to what you want. You can use google maps to get some coordinates, or you can activate the function at line 128 by disabling the block comments.

 let map = L.map('mapid').setView([59.924657, 10.728278], 14);

Add an initial title and a description.

The title should be very specific for the map. If this map is part of an article beware of potentially repeating information in the map and th earticle. Try to make the map have its own unique information that relates to geography and movements within an area. The initial title and description in this map are visible when the user first enters the map, but when the user clicks a feature in the map that text will be replaced. You can use the initial title and description as a guide for the user. Alter the title on line 58 and the description on line 59.

<h3 id="mapTitle">Map title</h3>
<p id="mapDescription">Initial map description. This textbox is dynamic and will change when the user click features in the map</p>

Create a marker

Markers are a very common feature of interactive maps. You can add as many as you want and place them around your map. Add the following code around line 85

let myMarker = L.marker([59.920443, 10.733508]).addTo(map);

This will add a standard marker to your leaflet map. Lets see what we can do with this marker.

Add a custom icon to your marker

Custom icons for markers can really make your map stand out. In order to use a custom icon you need a png file. PNG is a bitmap file format that supports transparency. This is good for icons because we can use any shape, rather being stuck with a jpeg rectangle. Technically a png is still a rectangle but because we can have transparent bits it can visually look like anything. In order to use a png as an icon we have to place the png image file in a location where the webpage can load it. In this case the image is in a sub folder named ‘img’. If we publish this map in wordpress we will have to upload the png file to the wordpress Media library and then get the url to the image from the Media library. Simply click on the file in media library and you should see the url. For now we will keep the png file in the ‘img’ sub folder. Here is the code for making an icon object containing information about the custom icon.

let myIcon = L.icon({
                iconUrl: 'img/explosion128.png',
                //shadowUrl: 'leaf-shadow.png',

                iconSize:     [45, 37], // size of the icon
                //shadowSize:   [50, 64], // size of the shadow
                //iconAnchor:   [22, 45], // point of the icon which will correspond to marker's location
                tooltipAnchor:   [22, -5], // point of the icon which will correspond to marker's location
                //shadowAnchor: [4, 62],  // the same for the shadow
                popupAnchor:  [-3, -36] // point from which the popup should open relative to the iconAnchor
            });

Notice that some lines are commented out. These lines are refering to a shadow for the icon but in this example that is not used. You can see an example with shadows on the leaflet.js page. In order to activate the icon you need to alter the code the made the marker in the first place. That code on line 85ish needs an additional reference to the icon object we just made.

 let myMarker = L.marker([59.920443, 10.733508], {icon: myIcon}).addTo(map);

Add a tooltip to your marker

Adding a tooltip will make your map more user friendly. A tooltip that becomes visible on mouseover is a very easy way for the user to get additional information about the data. It also serves to conceal the quantity of data and keep the map nice and clean. Here is an example of how to make a tooltip with just a plain text string.

myMarker.bindTooltip("Someone ordered a hot kebab here!");

If you want to display data dynamically from your geojson you can replace the string in the example above with a constructed sentence and include the data you want. You can read more about constructing human readable strings from data here. The way of doing it mentioned above is ok if you only have a few markers in your map. If you have more than 3-4 markers you should let leaflet generate them from a geojson file. This article will be updated with information about that.

Alter title and description when the user clicks the marker

First you need to add some properties to your marker. The marker requires a specific object structure for it to work in the same way as features in a geojson file.

//The followin two emtpy objects are necessary for the marker to work just like a geojson feature.
myMarker.feature = {}; 
//this adds 'properties'as an empty object to put imgurl in
myMarker.feature.properties = {};
myMarker.bindTooltip("Someone ordered a hot kebab here!");
myMarker.feature.properties.title = "Bislett Kebab";
//myMarker.feature.properties.linkUrl = "https://oslomet.no/";
//myMarker.feature.properties.linkTitle = "OsloMet";
myMarker.feature.properties.imgurl = "Michael_Jordan_1.jpg";
myMarker.descr = "This is the place where the hot kebab was eaten.";

You can add link and images to a marker by activating the commented out lines above (linkUrl & linkTitle). These lines don’t exist in the example project so just copy paste from above.

For anything to happen when a marker is clicked you have to add a eventlistener to listen for when the marker is clicked. This event listener will trigger a function that alters the displayed text.

 myMarker.on({
        click: markerClicked
 });

The markerClicked function alters the information in the title and description.

NOTE: There should only be one markerClicked function.

There should only be one function for each purpose. The following function will take the clicks from all the markers then change the text on two text elements. If you want to get a better grip on how this function works I suggest you try the following:

Add the console.log code line from below and place it in the same function in your own project. After you have added this code you can navigate through evt.targets object too see the data properties of the marker you click on in the map. Open up developer tools (Win: F12 / Mac : Ctrl Option J) with your own map in the browser. When you log only an object to the console you can navigate through that objects tree structure in the console. Click on markers and navigate through the objects tree structure to get a better understanding of what is happening.

Each function should have a clear purpose and take data from all relevant objects.

function markerClicked(evt) {
       console.log(evt.target);
       document.getElementById("mapTitle").innerText = evt.target.name;
       document.getElementById("mapDescription").innerText = evt.target.descr;
}

The function above changes the text on two text elements. The functions name is markerClicked so I think the purpose of the function is to do or initiate anything that should happen when a marker is clicked. The function is also logging event.target to the console. That is not really its purpose though. It is a code added so we can see what is happening when we click on stuff. The console.log code should be removed before the map is published.

Copy pasting markers

If you need to put many markers or other objects in the map, geojson.io is probably a better way to create this content. There might be cases where simply copy pasting markers is ok though, but ideally only for a few markers. The one use case I can think of that might be simplified with this is publishing a map with several custom markers. If you need to copy paste markers do it like this:

let myMarker = L.marker([59.920443, 10.733508], {icon: myIcon}).addTo(map);         
            
            myMarker.feature = {}; 
            //this adds 'properties'as an empty object to put imgurl in
            //The reason for these extra objects is to emulate the structure of a geojson.features object. 
            //Same data strcture means more streamlined functions downstream.
            myMarker.feature.properties = {};
            myMarker.bindTooltip("Someone ordered a hot kebab here!");
            myMarker.feature.properties.title = "Bislett Kebab";
            myMarker.feature.properties.imgurl = "https://gauteheggen.com/wp-content/uploads/Michael_Jordan_1.jpg";
            myMarker.feature.properties.descr = "This is the place where the hot kebab was eaten.";

Emulating a data structure and testing that structure.

The code above makes an instance of a Leaflet marker object. It then gives this instance its properties. The object gets a specific structure to emulate the structure of a geojson feature. Having the same structure on these different objects allows for more streamlined functions later. In the code above you can see the structure being made when myMarker.feature and myMarker.feature.properties is added in the hierarchy of the object. The console log code we added in the function further up allows us to see and navigate the structure we just made. The main purpose of logging to the console is to see what is happening and to debug faulty code. If something doesn’t work a good start is to log the data and to navigate through it in the console. Also check for errors (RED) in the console.

Geojson, links and images.

First some information about a fix for links not working when the map is published in WordPress.

If you are well on your way with your project you don’t want to start over with the fresh zip file above, so here is how to fix this issue in your own project. You need to add just one line of code fix this. Here is the one line of code:

myLink.setAttribute('target', '_blank');

Now we have to make sure this code ends up in the right place.Here is the right context for this code line. In my project this is on line 252 but that might vary depending on many things such as how long you geojson data is. Just make sure you paste the line above the last line within those curly brackets. That is the line that ends with appendChild(myLink)

if (document.getElementById("markerlink") == null){
                        let myLink = document.createElement('A');
                        myLink.setAttribute("id", "markerlink");
                        //myLink.setAttribute("margin-left", "12px");
                        let linkText = document.createTextNode(evt.target.feature.properties.linkTitle);
                        myLink.appendChild(linkText);
                        //myLink.setAttribute("href", evt.target.feature.properties.linkUrl);
                        myLink.href = evt.target.feature.properties.linkUrl;
                        
                        myLink.setAttribute('target', '_blank');
                        
                        document.getElementById("txtcontainer").appendChild(myLink);
                    }

This map supports geojson as well as the standard marker above. The easiest way to get some data into the map is probably to head over to geojson.io, and create some content. It also supports images and links in the text box and the way to add images and links is to add some data to the properties object of each geojson feature. Here is a complete properties object with all properties for link, link-title and image-url.

"properties": {
                "marker-color": "#7e7e7e",
                "marker-size": "medium",
                "marker-symbol": "",
                "imgurl": "peppa-pig.png",
                "title": "Peppa-pig",
                "descr": "All the kids around here love Peppa-pig, and most of the adults love Peppa-pig too!",
                "shortDescr": "Who loves Peppa-pig?",
                "linkUrl": "https://www.peppapig.com/?new=peppapig.com",
                "linkTitle": "peppapig.com"

So the nice thing about the properties object in each feature is that we can add whatever data we like there. If you want links to work you must add linkUrl and linkTitle to the properties object. The map application will check if these properties exist and add a link to the textbox. The image suppoert is similiar. The map application will check for a linkUrl property and if it exists it will load the picture. If you publish your map in wordpress you have to upload all the images to the media library, get the url for the images and use those urls as imgurl.

Consider the precision of your source information before you click publish.

If time is of the essence you might want to publish your map already. Take a few moments before you pull the trigger to reconsider some aspects of what you have made. First you should consider the precision of the source information you have about the geographical location. If a bomb has gone of somewhere and you are making a map about it you don’t want to scare the audience for no reason. If for example you only have a city name you should limit the max zoom level the user can see. Leaflet maps can zoom very far in, but if your source information precision is not down to street level, I don’t think the user should be able to zoom to street level either. This is known as false precision because the map technology allows a much higher level of precision than what is provided in the real information about the event.

Leave a comment