When you hover on the provences on the map below, you'll see the name of the provence. How to imitate this behavior with amCharts on mobile? It would be nice if the label appears on mobile when you tap once. Only one label can be visible at the same time.
I've been looking endlessly to find the answer. I couldn't find the answer in the docs either, for example at https://www.amcharts.com/docs/v4/concepts/touch/
Eventually I would like to be able to link to another page when you tap the same province again. So if you tab a provence, and if a label is visible in that provence, then you'll go to another page. The biggest provence on the left (xinjiang) already links to google.com. But I haven't even got a clue on how to listen for the first tap event.
Does anybody, maybe someone with a bit AmCharts experience, have an idea on how to solve this problem?
var chart = am4core.create("mapchina", am4maps.MapChart);
chart.geodata = am4geodata_chinaHigh;
chart.seriesContainer.draggable = false;
chart.seriesContainer.resizable = false;
chart.maxZoomLevel = 1;
chart.chartContainer.wheelable = false;
var polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
polygonSeries.useGeodata = true;
polygonSeries.calculateVisualCenter = true;
polygonSeries.tooltip.getFillFromObject = false;
polygonSeries.tooltip.background.fill = am4core.color("#30302F");
polygonSeries.tooltip.background.stroke = am4core.color("#30302F");
polygonSeries.tooltip.fontSize = 14;
polygonSeries.tooltip.fontFamily = "Open sans";
polygonSeries.data = [
{
id: "CN-XJ",
name: "Xinjiang",
url: "www.google.com",
urlTarget: "_blank"
},
{
id: "CN-NM",
name: "Neimenggu"
},
{
id: "CN-GX",
name: "Guangxi"
},
{
id: "CN-NX",
name: "Ningxia"
}
];
var polygonTemplate = polygonSeries.mapPolygons.template;
polygonTemplate.fill = am4core.color("#F26964");
polygonTemplate.stroke = am4core.color("#fff");
polygonTemplate.strokeWidth = 1;
polygonTemplate.hoverOnFocus = true;
polygonTemplate.nonScalingStroke = true;
polygonTemplate.tooltipText = "[text-transform: uppercase; font-weight: 600; font-size: 14px]{name}";
polygonTemplate.propertyFields.url = "url";
polygonTemplate.propertyFields.urlTarget = "urlTarget";
polygonTemplate.events.on("over", function(event) {
event.target.zIndex = Number.MAX_VALUE;
event.target.toFront();
});
var hoverState = polygonTemplate.states.create("hover");
hoverState.properties.fill = am4core.color("#FFD464");
hoverState.properties.stroke = am4core.color("#FFD464");
hoverState.properties.strokeWidth = 1;
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
#mapchina {
width: 100%;
height: 350px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/maps.js"></script>
<script src="https://www.amcharts.com/lib/4/geodata/chinaHigh.js"></script>
<div id="mapchina"></div>
The hover state of each province can be toggled by setting event.target.isHover
to true
/false
(this works best when polygonTemplate.hoverOnFocus
is set to false
). The over
event is triggered for each tap, so the hover state can be enabled there (staying that way until the user interacts again). Checking event.touch
allows the behaviour of mouse events on non-touch screens to be unaffected.
The tricky part is that the corresponding out
event does not seem to trigger for touch events. Without this, it's difficult to know whether a tap is the first or second tap on a given province. To work around this, a document.ontouchend
event can be used instead. In this function, check to see if the target
is the last province tapped, so that it can behave as an out
event (this is better, as it will even trigger for a tap outside the chart).
By keeping track of the last tapped province (tapProvince
), this can be compared in subsequent over
events to check for an initial or repeat tap. Finally, by setting event.target.url
to an empty string or the intended URL, it is possible to control navigation.
var chart = am4core.create("mapchina", am4maps.MapChart);
chart.geodata = am4geodata_chinaHigh;
chart.seriesContainer.draggable = false;
chart.seriesContainer.resizable = false;
chart.maxZoomLevel = 1;
chart.chartContainer.wheelable = false;
var polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
polygonSeries.useGeodata = true;
polygonSeries.calculateVisualCenter = true;
polygonSeries.tooltip.getFillFromObject = false;
polygonSeries.tooltip.background.fill = am4core.color("#30302F");
polygonSeries.tooltip.background.stroke = am4core.color("#30302F");
polygonSeries.tooltip.fontSize = 14;
polygonSeries.tooltip.fontFamily = "Open sans";
polygonSeries.data = [{
id: "CN-XJ",
name: "Xinjiang",
url: "www.google.com",
urlTarget: "_blank"
},
{
id: "CN-NM",
name: "Neimenggu"
},
{
id: "CN-GX",
name: "Guangxi"
},
{
id: "CN-NX",
name: "Ningxia"
}
];
var tapProvince;
var tapURL;
var polygonTemplate = polygonSeries.mapPolygons.template;
polygonTemplate.fill = am4core.color("#F26964");
polygonTemplate.stroke = am4core.color("#fff");
polygonTemplate.strokeWidth = 1;
polygonTemplate.hoverOnFocus = false;
polygonTemplate.nonScalingStroke = true;
polygonTemplate.tooltipText = "[text-transform: uppercase; font-weight: 600; font-size: 14px]{name}";
polygonTemplate.propertyFields.url = "url";
polygonTemplate.propertyFields.urlTarget = "urlTarget";
polygonSeries.calculateVisualCenter = true;
polygonTemplate.tooltipPosition = "fixed";
document.ontouchend = function(event) {
if (tapProvince && !tapProvince.dom.contains(event.target)) {
tapProvince.isHover = false;
tapProvince.url = tapURL;
tapProvince = undefined;
};
};
polygonTemplate.events.on("over", function(event) {
event.target.zIndex = Number.MAX_VALUE;
event.target.toFront();
if (event.touch) {
event.target.isHover = true;
if (tapProvince && tapProvince.dom === event.target.dom) {
//after first tap
event.target.url = tapURL;
} else {
//first tap
tapProvince = event.target;
tapURL = event.target.url;
event.target.url = "";
};
};
});
var hoverState = polygonTemplate.states.create("hover");
hoverState.properties.fill = am4core.color("#FFD464");
hoverState.properties.stroke = am4core.color("#FFD464");
hoverState.properties.strokeWidth = 1;
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
#mapchina {
width: 100%;
height: 350px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/maps.js"></script>
<script src="https://www.amcharts.com/lib/4/geodata/chinaHigh.js"></script>
<div id="mapchina"></div>