Menighin
Posts: 22
Joined: Tue Feb 20, 2018 11:07 am

Pan map programatically

Hi there,

I'm having a struggle trying to pan the map programatically. Let me explain a bit my situation:

I have a map and on top of it I have another component that displays some information by states. This component on top of the map is draggable so the idea is that I capture the drag event from it and pass it to the map below, so the map moves together with the component.

Checking the documentation I only found the mapZoom and zoomTo function (https://www.highcharts.com/docs/maps/map-navigation) and nothing about panning and I cant find an easy way to either translate the SVG elemnt or change the viewbox to drag with my drag event.

So, is there any easy way to do this? If not, does anyone recommend a way to solve this?

Thanks!!
Menighin
Posts: 22
Joined: Tue Feb 20, 2018 11:07 am

Re: Pan map programatically

So I did indeed manage to accomplish what I wanted by "hard translating" the svg with my drag event. Basically I get my SVG with this selector:

Code: Select all

var svg = document.getElementsByClassName('highcharts-series highcharts-map-series highcharts-series-0')[0];
Then I calculate the amount of transformation to apply. Then I do svg.setAttribute to set the transformation. So, questions:
  • Is this a good way of doing it? Since my user will never directly interact with the map, I couldn't see a problem with it...
  • Is there a better way to select the series that represents my map? I saw that we have an Id attribute for the series and we can use chart.get(id) to retrieve it. But I couldnt get how to go from it to get the SVG and apply the transformation.
Thanks!
ppotaczek
Posts: 751
Joined: Mon Oct 02, 2017 3:12 pm

Re: Pan map programatically

Hi Menighin,

Yes, I think that is a good way to achieve the goal. Alternatively, to select the series you can use:

Code: Select all

Highcharts.charts[0].series[0].group.element
If you have any future questions, just ask.

Live demo: http://jsfiddle.net/BlackLabel/872ythcn/
API Reference: https://api.highcharts.com/class-refere ... ts#.charts

Best regards!
Paweł Potaczek,
Highcharts Developer
Menighin
Posts: 22
Joined: Tue Feb 20, 2018 11:07 am

Re: Pan map programatically

Hi ppotaczek,

I am having another trouble with this same situation now.

I have to zoom in the map and to do so I am again capturing the zoom event from the top div and passing it to map through the mapZoom function, like:

Code: Select all

map.mapZoom(zoom, 
    map.chart.xAxis[0].toValue(z.pointer.x),
    map.chart.yAxis[0].toValue(z.pointer.y),
    z.pointer.x,
    z.pointer.y);
where z.pointer refers to the zoomed position in the map.

This almost works. If I only zoom in and out, it is perfect and smooth. But if I translate the map by dragging and then zoom in or out, the map snaps back to the position it was before, like this gif:

https://makeagif.com/i/7sjkZW
(the dots you see in top of the map is the component above the map I previously referred)

Investigating this, I think this behavior is due to the fact I am "hard translating" my map and not setting some properties highmaps expect to be set correctly (which I believe are the axis extremes) .
The way I am translating the map is like this:

Code: Select all

dragging(e) {
    this.translate.x += e.event.center.x - this.dragCenter.x;
    this.translate.y += e.event.center.y - this.dragCenter.y;
    this.dragCenter = e.event.center;
    this.getSvgMapNode().setAttribute('transform', `translate(${this.translate.x}, ${this.translate.y}) scale(${this.scale})`);
}
The getSvgMapNode is:

Code: Select all

return document.getElementsByClassName('highcharts-series highcharts-map-series highcharts-series-0')[0].childNodes[0];
I though about hardwiring the zooming myself but that wouldn't easy work because I rely on lat/long and if I simply scale my svg as I do with the translation, this lat/long is lost.

Any ideas to help me? Is this really about the axis extremes? If so, how can I set them correctly?

Sorry about not making a fiddle, its because it is a lot of work to extract this to a fiddle :/
Menighin
Posts: 22
Joined: Tue Feb 20, 2018 11:07 am

Re: Pan map programatically

I managed to make a minimum fiddle to help reproduce:

https://jsfiddle.net/w3714hyy/

The idea here is that you click on the translate button on the bottom of the fiddle.
This will translate the map 10px to the right the same way I described I translated above.
Then if you zoom in the map (by using the mousewheel or the navigation buttons) you will see that it snaps back to some previous position.

Any help is much appreciated. Thanks again!
ppotaczek
Posts: 751
Joined: Mon Oct 02, 2017 3:12 pm

Re: Pan map programatically

Hi Menighin,

Thank you for detailed description of the problem. You are definitely right, this issue is related with the axis extremes. I think that you can use setExtremes and getExtremes methods to create all the functionality. I prepared simplified example which can be used for testing. If you have additional questions, just ask.

Live example: http://jsfiddle.net/BlackLabel/hzvkck77/

API:
https://api.highcharts.com/class-refere ... etExtremes
https://api.highcharts.com/class-refere ... etExtremes

Best regards!
Paweł Potaczek,
Highcharts Developer
Menighin
Posts: 22
Joined: Tue Feb 20, 2018 11:07 am

Re: Pan map programatically

Hi Pawel, thank you so much for the answer.

I feel I am really close. For what I understood from your answer, the way to go with this is using setExtremes to translate the map instead of hard translating it through SVG transformations.

The problem I have now is finding out how much I should translate (e.g. setExtremes) my map once I am using dragging events. Trying to explain:

In your fiddle example you are always subtracting 200 units from the extremes and therefore the map moves to the right. Those 200 units represent different "amounts" depending on the map zoom. If I click on translate button with the map at 0 zoom, I can see the SVG is translate roughly 30 units to the right. If I have the map zoomed I see it is translated more than 30 units.

The problem comes when I using the drag event instead of a simple button to drag the map around. Let's say if I dragged from (100, 100) to (120, 100) it means the mouse moved 20px to the right. How can I map those 20px to a value that makes sense using with setExtremes?

I feel like we gonna have to almost re-implement Highmaps panning itself :s

Here is an ugly fiddle that may help you: http://jsfiddle.net/52bdz8ju/

In this fiddle I am still translating my map the old way (using SVG transformations). There's a div on top of the map which captures the drag events and passes it to the map. If you could help me to replace the code on line 29 with a setExtremes I think it will be fine...

Sorry for the trouble, I know it is a lot to ask. Thanks in advance!

Edit:

I tried playing around with the dragged amound and set extremes but the result is always kinda messy: http://jsfiddle.net/5vLarwcs/

The way I see is all about finding out how much to add on the extremes according to the drag event so the dragging becomes "natural" :)

The good news is the zoom seems to work fine indeed when I translate using the setExtremes n_n'
Last edited by Menighin on Wed May 23, 2018 4:08 pm, edited 3 times in total.
Menighin
Posts: 22
Joined: Tue Feb 20, 2018 11:07 am

Re: Pan map programatically

Another option I just tought and don't know if it is possible is:

- Keep the drag event doing SVG transformations so the map moves fluidly with the mouse;
- On dragEnd event, given the transformation done on the SVG, I calculate somehow the axis extremes and set them. After setting them, the map should not move but the zoom would have it's extremes set correctly to work with.

Is that possible?
Menighin
Posts: 22
Joined: Tue Feb 20, 2018 11:07 am

Re: Pan map programatically

I did it! :D

Indeed, looking at Highcharts Pan function (https://github.com/highcharts/highchart ... raction.js) I was able to somehow reproduce the panning. The spills logic on Highcharts code I imagine is used to prevent the user panning forever outside the extremes.

Here is the result:
http://jsfiddle.net/snvem8ey/

I will try now to adapt to my real case now.

Anyway, thank you so much Pawel for pointing me to some direction. If you have anything to add please do!
ppotaczek
Posts: 751
Joined: Mon Oct 02, 2017 3:12 pm

Re: Pan map programatically

Hi Menighin,

Your result works and looks very good. Thank you for sharing the example, it can be useful for other users. This is a custom functionality, so the most important thing is to make it work the way you want.

Best regards!
Paweł Potaczek,
Highcharts Developer

Return to “Highcharts Maps”