Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

By default, snap back to "w=0" world after panning operation (i.e. "worldCopyJump") #2071

Closed
drewbo opened this issue Feb 5, 2016 · 16 comments

Comments

@drewbo
Copy link
Contributor

drewbo commented Feb 5, 2016

Because certain methods like flyTo send the user on to world copies, it would be great if there were an option to duplicate data/overlays to the other world copies as well.

@1ec5
Copy link
Contributor

1ec5 commented Feb 5, 2016

Only flyTo goes to a world copy at the moment (#1857). It probably should go back to the original world on the last frame, though.

@drewbo
Copy link
Contributor Author

drewbo commented Feb 5, 2016

I think the only issue with that would be that it precludes setting maxBounds to prevent people from scrolling off the data as well (it interrupts the flyTo animation)

@jfirebaugh
Copy link
Contributor

I think worldCopyJump behavior should be the only behavior (no option), and flyTo should wrap on the first frame that crosses the antimeridian.

@lucaswoj
Copy link
Contributor

Duplicate of #2879

@lucaswoj lucaswoj reopened this Aug 12, 2016
@lucaswoj lucaswoj changed the title Create Leaflet-like worldCopyJump option Add option to copy markers and popups when panning across dateline Aug 12, 2016
@jfirebaugh
Copy link
Contributor

I preferred the old implementation proposal, "Create Leaflet-like worldCopyJump option". That seems much more tractable than duplicating arbitrary DOM elements, which is what "Add option to copy markers and popups when panning across dateline" would require.

@lucaswoj
Copy link
Contributor

lucaswoj commented Aug 22, 2016

Ah! I misunderstood the behaviour of worldCopyJump. Changing the title now.

http://leafletjs.com/reference.html#map-worldcopyjump

@lucaswoj lucaswoj changed the title Add option to copy markers and popups when panning across dateline Add option to snap back to "w=0" world after panning operation (i.e. "worldCopyJump") Aug 22, 2016
@lucaswoj
Copy link
Contributor

lucaswoj commented Sep 9, 2016

This feature is easy to implement downstream. Perhaps so easy we need not include it in core.

map.on('moveend', function() {
  map.setCenter(map.getCenter().wrap());
});

cc @geografa

@jfirebaugh jfirebaugh changed the title Add option to snap back to "w=0" world after panning operation (i.e. "worldCopyJump") By default, snap back to "w=0" world after panning operation (i.e. "worldCopyJump") Dec 8, 2016
@joshbutkovic
Copy link

Any ideas with this? I have been striuggling to accomplish the same behavior as described in this thread.

@jfirebaugh
Copy link
Contributor

@jjb867 Did you try the code snippet from #2071 (comment)?

@joshbutkovic
Copy link

Sorry but I'm not sure what you are referring to specifically. I have a 'zoomend' event that I'm using to trigger a popup after flying to a location. The basic idea is displaying fake transactions around the world in a popup. The popup is displayed properly unless I'm displaying one in Hong Kong for example, it appears in Hong Kong, but in one world to the right of where I need it.

I tried

map.setCenter(map.getCenter().wrap());

inside my zoomend function which does work but it creates a flash and a jarring user experience.

Is this what you are referring to?

@jfirebaugh
Copy link
Contributor

Yes. Can you create a JSFiddle that shows the issue you're talking about with that approach?

@joshbutkovic
Copy link

Actually just got it to work to my liking using the above snippet inside of 'zoomend' (no flash, no issue), thanks for pointing out that snippet for a second time!

@joshbutkovic
Copy link

map.setCenter(map.getCenter().wrap());

This line actually does work to bring the map to the world copy which the popup is rendered. Since the map needs to instantly be re-rendered it DOES create a quick flash which is less than desirable. I would create an example but I have too many php datapoints being read onto the page.

This works for now but it would be nice to have an option to either have the popup render on ALL world copies, or only limit the world to one instance.

@andrewharvey
Copy link
Collaborator

map.on('moveend', function() {
 map.setCenter(map.getCenter().wrap());
});

I found this creates an infinite loop and needed something like

map.on('moveend', function(e) {
   if (!e.snapWorldMove) {
      map.setCenter(map.getCenter().wrap(), { snapWorldMove: true });
   }
});

I still notice though that the second world does flash white for a fraction of a second on the moveend when the map.setCenter moves back to world zero.

@magiccccat
Copy link

Hi guys,

Inspired by the code you provided. Newbie here. I think I found a way to address the flyto world zero problem.

I need to fly from locations in Asia to USA, but problem is that the flyto method automatically select the shortest route, in my case it is through pacific ocean to world +1 or -1, instead of sticking with original copy of world zero and going through Europe.

So the solution is to add a mechanism to calculate if the 2 locations are in different semi-sphere. If yes, then that will be the longer rough, which flyto will not select by itself. So you need to add a middle point, so that flyto can select the longer route and keep in world map zero by flying from start location to middle point, then from middle point to final destination.

Here is my code, hope it is useful to you guys:D

//Prevent find the closet route and miss the markers
        var currentLocation = map.getCenter();
        var nextLocation = locationObjectArray[index].geometry.coordinates; //load the next location from geojson
        var productLng = currentLocation.lng * nextLocation[0]; 
        var productLat = currentLocation.lat * nextLocation[1];
        var midLocationCam;

// check if current location and next location are on different semi-spheres, east and west. if yes, then one of  currentLocation.lng and nextLocation[0] should be negative, so their product should be negative.

        if(productLng<0){
            var midLng = currentLocation.lng + nextLocation[0];
            var midLat;
            var currentZoom = map.getZoom();
            var currentPitch = map.getPitch();
            var currentBearing = map.getBearing();
// calculate a middle point between those locations which is in the original cope, in my case of flying from asia to USA, roughly the middle point will be in Europe.
            if (productLat <0){
                midLat = currentLocation.lat + nextLocation[1]
            }else{
                midLat = (currentLocation.lat + nextLocation[1])/2
            }
//prepare the camera object for flyto method
            midLocationCam = {
                center: [midLng,midLat],
                zoom: 1,
                pitch: currentPitch,
                bearing: currentBearing
            }
            
        };

// if the location in the middle exists, then ... 
        if(midLocationCam){
// go to the location in the middle
            map.flyTo(midLocationCam);
            midLocationCam = "";
// once movement ended then go to the final destination.
            map.once('moveend', function() {
                map.flyTo(locationObjectArray[index].properties.camera);//this is a destination loaded from geojson
            });
        }else{
//if the location in the middle does not exist, then go to the final destination directly.
               map.flyTo(locationObjectArray[index].properties.camera);

        };

A bump of this solution is the animation is not as smooth as directly flyto since the camera needs to stop at the middle point with ease and then start to fly to the final destination.

Let me know where I can improve:D

@andrewharvey
Copy link
Collaborator

andrewharvey commented Mar 20, 2017

I've submitted #4451 which will ensure a flyTo always stays in world 0. Are there any cases where you wouldn't want this to happen? Since I haven't implemented an option for it.

easeTo, panTo and jumpTo don't cross worlds.

This still leaves:

  • while panning manually
  • after panning manually but moving with inertia (panTo -> easeTo)
  • double click zoom (zoomTo -> easeTo)
  • box zoom (fitBounds -> easeTo,flyTo)
  • if a user passes a non-wrapped coordinate pair to easeTo, panTo or jumpTo should it be wrapped as part of those functions to ensure the map never leaves world 0?
  • easeTo can still end up in non world 0 when using the offset option even when the coordinate pair is wrapped. The keyboard handler is a good example of this. So easeTo should also jump back to world 0 immediately upon leaving.
  • fix the render flash others have reported (I can replicate this too)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants