In our main Map Chart article we have touched the topic of creating an image series, feeding them data, and positioning them. However, we were operating using plain, same shapes. This tutorial will show how we can use actual images as markers on the map.
Using same image
Explaining MapImageSeries
in our Map Chart article, we've used simple Circle
shape. E.g.:
let imageSeriesTemplate = imageSeries.mapImages.template;
let circle = imageSeriesTemplate.createChild(am4core.Circle);
circle.radius = 4;
circle.fill = am4core.color("#B27799");
circle.stroke = am4core.color("#FFFFFF");
circle.strokeWidth = 2;
circle.nonScaling = true;
circle.tooltipText = "{title}";
var imageSeriesTemplate = imageSeries.mapImages.template;
var circle = imageSeriesTemplate.createChild(am4core.Circle);
circle.radius = 4;
circle.fill = am4core.color("#B27799");
circle.stroke = am4core.color("#FFFFFF");
circle.strokeWidth = 2;
circle.nonScaling = true;
circle.tooltipText = "{title}";
{
// ...
"series": [{
"type": "MapPolygonSeries",
// ...
}, {
"type": "MapImageSeries",
"mapImages": {
"children": [{
"type": "Circle",
"radius": 4,
"stroke" : "#B27799",
"strokeWidth": 2,
"nonScaling": true,
"tooltipText": "{title}"
}]
}
}]
}
Using real image is not that different: we just replace Circle
with an Image
, as well as set its appropriate properties, like href
.
let imageSeriesTemplate = imageSeries.mapImages.template;
let marker = imageSeriesTemplate.createChild(am4core.Image);
marker.href = "path/to/marker.svg";
marker.width = 20;
marker.height = 20;
marker.nonScaling = true;
marker.tooltipText = "{title}";
marker.horizontalCenter = "middle";
marker.verticalCenter = "bottom";
var imageSeriesTemplate = imageSeries.mapImages.template;
var marker = imageSeriesTemplate.createChild(am4core.Image);
marker.href = "path/to/marker.svg";
marker.width = 20;
marker.height = 20;
marker.nonScaling = true;
marker.tooltipText = "{title}";
marker.horizontalCenter = "middle";
marker.verticalCenter = "bottom";
{
// ...
"series": [{
"type": "MapPolygonSeries",
// ...
}, {
"type": "MapImageSeries",
"mapImages": {
"children": [{
"type": "Image",
"href": "path/to/marker.svg",
"width": 20,
"height": 20,
"nonScaling": true,
"tooltipText": "{title}",
"horizontalCenter": "middle",
"verticalCenter": "bottom"
}]
}
}]
}
NOTE Take note about horizontalCenter
and verticalCenter
settings. They are important, as they will determine which part of the image is placed at the latitude/longitude coordinates. Since we are using a map pin image, we need it to be centered to bottom/middle.
See the Pen amCharts 4: Map image series with actual images by amCharts team (@amcharts) on CodePen.0
Using different images
Previous section was "stamping out" the same image for all items in our image series.
Now, let's see how we can use different image for each individual item.
Since we are going to be feeding images via data, let's add update our data:
[{
"latitude": 48.856614,
"longitude": 2.352222,
"title": "Paris",
"flag": "path/to/pin_france.png"
}, {
"latitude": 40.712775,
"longitude": -74.005973,
"title": "New York",
"flag": "path/to/pin_usa.png"
}, {
"latitude": 49.282729,
"longitude": -123.120738,
"title": "Vancouver",
"flag": "path/to/pin_canada.png"
}]
Now, all we need to do is to bind our image's href
property to flag
field in data, instead of hard-coding it.
For that, we are going to be using "property fields". It's a way to bind any property of any object to a field in data.
So, instead of setting marker.href
we are going to be doing this:
marker.propertyFields.href = "flag";
marker.propertyFields.href = "flag";
{
// ...
"series": [{
"type": "MapPolygonSeries",
// ...
}, {
"type": "MapImageSeries",
"mapImages": {
"children": [{
// ...
"propertyFields": {
"href": "flag"
}
}]
}
}]
}
That's it!
See the Pen amCharts 4: Map image series with actual images by amCharts team (@amcharts) on CodePen.0
Using SVG paths
Up until now we have been using actual external image files.
We can use an SVG path as well. An SVG path is a list of special geometrical instructions, that define a vector shape.
When comparing it to conventional images - vector (SVG) and bitmap (PNG, JPEG) alike - it has two distinctive advantages:
- They are completely in-line. No reliance on external files. Now potential CORS issues.
- They can styled using properties like
fill
,stroke
, and evenfilters
. This means that you can either set colors directly, or even via data and/or heat rules.
Below is an SVG path of a star shape:
M9 9l-5 1v1l4 3a2286 2286 0 0 0-1 6l5-3a14908 14908 0 0 0 5 2l-1-5 4-3v-1l-5-1-3-5-3 5z
To use it as a map image, we need to do make following modifications to our map image definition:
- Use regular
Sprite
(instead ofImage
). - Use its
path
attribute to set SVG path (instead ofhref
).
let marker = imageSeriesTemplate.createChild(am4core.Sprite);
marker.path = "M9 9l-5 1v1l4 3a2286 2286 0 0 0-1 6l5-3a14908 14908 0 0 0 5 2l-1-5 4-3v-1l-5-1-3-5-3 5z";
marker.fill = am4core.color("#f55");
var marker = imageSeriesTemplate.createChild(am4core.Sprite);
marker.path = "M9 9l-5 1v1l4 3a2286 2286 0 0 0-1 6l5-3a14908 14908 0 0 0 5 2l-1-5 4-3v-1l-5-1-3-5-3 5z";
marker.fill = am4core.color("#f55");
{
// ...
"series": [{
"type": "MapPolygonSeries",
// ...
}, {
"type": "MapImageSeries",
"mapImages": {
"children": [{
"type": "Sprite",
"path": "M9 9l-5 1v1l4 3a2286 2286 0 0 0-1 6l5-3a14908 14908 0 0 0 5 2l-1-5 4-3v-1l-5-1-3-5-3 5z",
"fill": "#f55"
// ...
}]
}
}]
}
NOTE The above example sets path
directly to the image template, however it would work just as well with propertyFields.path
if you would rather add different shapes for different images.
See the Pen amCharts 4: Map image series with actual images by amCharts team (@amcharts) on CodePen.0