Skip to content

Add zooming when layer is added using <map-a> #387

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

Merged
merged 12 commits into from
Apr 13, 2021

Conversation

ahmadayubi
Copy link
Member

Zooms map to a link url fragment, if that doesn't exist then zoom to the layer extent.
If inplace attribute is present then it doesn't zoom.

Closes #378

@ahmadayubi ahmadayubi marked this pull request as ready for review April 9, 2021 13:55
@prushforth
Copy link
Member

I don't see the zoomTo functionality that I was expecting with non-fragment text/mapml links (actually haven't tested fragments yet)?

For example, this link:<map-a href="http://localhost:8081/geoserver/mapml/spearfish/cbmtile/"> , which matches the _self spec below, is not zooming to the spearfish layer extent when link is activated

_self: (Default if no target attribute) replace the current layer - not zooming afaict
_blank: add a new layer on top of map - not zooming to layer extent afaict
_parent: replace all layers in the map with the linked layer. If no other layers, behaves as _self. - not zooming afaict
_top: the topmost browsing context (the page) should navigate to the map resource, synthesize an HTML document
around it, and load the map resource into the synthesized map and process any URL fragments to control the
initial location of the map view. If no fragment, set zoom to lowest value, centered on extent of map doc.
(the "highest" context that’s an ancestor of the current one).
If no ancestors, behaves as _self. - not zooming afaict

@ahmadayubi
Copy link
Member Author

That's odd, I got the behavior on my end:
https://user-images.githubusercontent.com/55214462/114193446-87b74100-991c-11eb-84cf-425307b5f440.mp4

Could you try using the featureLink.html file and see if it works there? Run the test server node test/server.js and go to http://localhost:30001/featurelinks.html

@prushforth
Copy link
Member

Hard to tell if it's working for me cause I don't know what the links are supposed to do, but here's a recording:

Media1.mp4

@ahmadayubi
Copy link
Member Author

ahmadayubi commented Apr 9, 2021

There was an error with inplace but it should be focusing spearfish when you add it, I'll try using geoserver and see if I can recreate the issue.

@prushforth
Copy link
Member

prushforth commented Apr 9, 2021

There's this error in the console actually, sorry I didn't look before:
image

This is the spearfish mapml file:

<mapml xmlns="http://www.w3.org/1999/xhtml/">
    <head xmlns:html="http://www.w3.org/1999/xhtml/">
        <title>spearfish</title>
        <base href="http://localhost:8081/geoserver/mapml/" />
        <meta charset="utf-8" />
        <meta content="text/mapml;projection=CBMTILE" http-equiv="Content-Type" />
        <link href="http://localhost:8081/geoserver/mapml/spearfish/OSMTILE?style=" rel="alternate" projection="OSMTILE" />
        <link href="http://localhost:8081/geoserver/mapml/spearfish/APSTILE?style=" rel="alternate" projection="APSTILE" />
        <link href="http://localhost:8081/geoserver/mapml/spearfish/WGS84?style=" rel="alternate" projection="WGS84" />
    </head>
    <body xmlns:html="http://www.w3.org/1999/xhtml/">
        <extent units="CBMTILE">
            <input name="z" type="zoom" value="25" min="0" max="25" />
            <input name="xmin" type="location" rel="map" position="top-left" axis="easting" units="pcrs" min="-719733.3635460486" max="-697273.6409915054" />
            <input name="ymin" type="location" rel="map" position="bottom-left" axis="northing" units="pcrs" min="-471973.189323381" max="-454606.40783139697" />
            <input name="xmax" type="location" rel="map" position="top-right" axis="easting" units="pcrs" min="-719733.3635460486" max="-697273.6409915054" />
            <input name="ymax" type="location" rel="map" position="top-left" axis="northing" units="pcrs" min="-471973.189323381" max="-454606.40783139697" />
            <input name="w" type="width" min="1" max="10000" />
            <input name="h" type="height" min="1" max="10000" />
            <link tref="http://localhost:8081/geoserver/wms?request=GetMap&amp;crs=urn:x-ogc:def:crs:EPSG:3978&amp;service=WMS&amp;bbox={xmin},{ymin},{xmax},{ymax}&amp;layers=spearfish&amp;format=image/png&amp;width={w}&amp;styles=&amp;version=1.3.0&amp;transparent=true&amp;height={h}" rel="image" />
            <input name="i" type="location" axis="i" units="map" />
            <input name="j" type="location" axis="j" units="map" />
            <link tref="http://localhost:8081/geoserver/wms?request=GetFeatureInfo&amp;query_layers=spearfish&amp;crs=urn:x-ogc:def:crs:EPSG:3978&amp;bbox={xmin},{ymin},{xmax},{ymax}&amp;version=1.3.0&amp;transparent=true&amp;service=WMS&amp;layers=spearfish&amp;width={w}&amp;x={i}&amp;feature_count=50&amp;y={j}&amp;styles=&amp;info_format=text/mapml&amp;height={h}" rel="query" />
        </extent>
    </body>
</mapml>

@ahmadayubi
Copy link
Member Author

Seems to be an issue with timing, the focus() function is called on a layer before the layer's extent is fully processed, although it's strange that the geogratis ones loaded in but geoserver ones didn't.

@prushforth
Copy link
Member

prushforth commented Apr 9, 2021

Seems to be an issue with timing, the focus() function is called on a layer before the layer's extent is fully processed, although

This was a problem in early iterations. It may have been affected by this PR, perhaps: #366

it's strange that the geogratis ones loaded in but geoserver ones didn't.

possibly threading issues on the same computer cause that delay.

@ahmadayubi
Copy link
Member Author

ahmadayubi commented Apr 9, 2021

Maybe there should be an event that fires when a layers extent is set, I don't believe there's an event fired from the map that lets you know the layer is fully added, do you know of any? Leaflet has layeradd but I believe that fires too early also.

@prushforth
Copy link
Member

I used to have the extentloaded event, not sure if that still happens.

@prushforth
Copy link
Member

I also remember hacking with a labelchanged event. tbh I have not fully grasped asyn programming techniques, which is probably a major issue in this space.

@prushforth
Copy link
Member

Seems to be working better now. One thing I did notice is that a link that points to a projection-negotiable layer will work (it eventually negotiates the correct projection), but it doesn't zoom to the extent of the resulting layer extent.

@ahmadayubi
Copy link
Member Author

ahmadayubi commented Apr 9, 2021

Probably has to do with the extentload event being fired on the first request rather than on when it eventually negotiates the correct projection. I'll have a look.

@prushforth
Copy link
Member

prushforth commented Apr 9, 2021

First check of a fragment url such as:

<map-a href="http://localhost:8081/geoserver/mapml/topp:states/cbmtile/#7,-98,38.5" type="text/mapml" target="_self">

It seems to zoom to 7, lon=98, lat=38.5, but it doesn't load the states layer.

EDIT: it only pans at the current zoom, does not load the states layer.

@prushforth
Copy link
Member

The latest seems to work better for waiting on projection changes, but still getting the error below for url fragments:

<map-a href="http://localhost:8081/geoserver/mapml/topp:states/cbmtile/#6,-96.36158755253881,39.668588667742846">

image

@prushforth
Copy link
Member

Seems like this link doesn't work like I was expecting, although it does something (zoom/pan to the specified location):

<map-a href="#10,-76.474059,45.345151">

would correspond to the _self, below, I think, with the URL defaulting to the "URL" of the current layer, whether or not it is an actual document is another matter, I guess, since the content could be inline. We should be able to use fragments like the above with each of the target types below, I think.

_self: (Default if no target attribute) replace the current layer
_blank: add a new layer on top of map
_parent: replace all layers in the map with the linked layer. If no other layers, behaves as _self.
_top: the topmost browsing context (the page) should navigate to the map resource, synthesize an HTML document
around it, and load the map resource into the synthesized map and process any URL fragments to control the
initial location of the map view. If no fragment, set zoom to lowest value, centered on extent of map doc.
(the "highest" context that’s an ancestor of the current one).
If no ancestors, behaves as _self.

@ahmadayubi
Copy link
Member Author

ahmadayubi commented Apr 12, 2021

I think in a conversion we had I believe you mentioned that if the type=text/mapml and target=_self it should "simply reposition the viewer with zoomTo()". It was decided that the fragments would only work with type=text/mapml, in which case using the URL of the layer in the case of inline features doesn't work since the URL of the layer is pointing to an html page. In the case of templated features, what value do you get from replacing the layer with itself vs just repositioning? As for the other target types (other than _self) I can implement those behaviors, I wonder if they're consistent behaviors with how fragments work in html though.

@prushforth
Copy link
Member

prushforth commented Apr 12, 2021

It was decided that the fragments would only work with type=text/mapml

Right, but the default is text/mapml, correct?

the URL of the layer is pointing to an html page

That's true, but I don't think it affects the use of that URL as the context for zoom/pan to operations? I may be missing something though. I believe the intent was "simply reposition the viewer with zoomTo()". The current behaviour as I mentioned does move the map but not to the coordinates specified. There's a console error as well:

image

In the case of templated features, what value do you get from replacing the layer with itself vs just repositioning?

I would not replace the layer with itself - for urls that begin with #, I would not try to resolve against a base url, I would just invoke zoomTo and hope for the correct result. In a browser if you put a fragment that doesn't have a corresponding id, the browser doesn't complain, it does nothing, which seems to be the appropriate response in case of error here too.

@prushforth
Copy link
Member

<map-a href="#z,lon,lat"> could be considered a declarative API that exposes zoomTo(zoom, longitude, latitude).

@ahmadayubi
Copy link
Member Author

ahmadayubi commented Apr 13, 2021

So in the case of <map-a href="#3,12,43">, the viewer should consider that localhost:3000/mypage.html#3, 12, 34 (for example), try to follow the link according to the target type rules (and assume its text/mapml), and even in the case of a failed loading of the layer the fragment should be honored? Is that correct?

Side note, the issue with zoomTo() seemed to be that it only accepted numbers for zoom (lat, lng could be both numbers and strings), if you gave it a string for zoom ("12" instead of 12) it wouldn't work.

@ahmadayubi
Copy link
Member Author

Another note is that the zoomTo(lat, lon, zoom), accepts parameters in the order of lat, lon, zoom, and not zoom, lon, lat. There's probably a reason why, but that's how it's currently implemented.

@prushforth
Copy link
Member

So in the case of , the viewer should consider that localhost:3000/mypage.html#3, 12, 34 (for example), try to follow the link according to the target type rules (and assume its text/mapml),

In the case of href="#..." I think it would be ok to just assume the current document, be it an HTML page or a MapML document is the search environment, and if the fragment can be understood (parsed), invoke zoomTo on it, end of story.

and even in the case of a failed loading of the layer the fragment should be honored? Is that correct?

I would not try to load anything in this case. Could it be treated as a shortcut? The idea behind fragment identifiers is that they don't identify anything on a server at all, they are simply processed client side. So when there is a URL with a fragment, the URL parsing and resolution and loading takes place and ** then ** the fragment is processed. So if there is no url, I think it might be safe to assume / perform a zoomTo without otherwise attempting to process the url.

Another note is that the zoomTo(lat, lon, zoom), accepts parameters in the order of lat, lon, zoom, and not zoom, lon, lat. There's probably a reason why, but that's how it's currently implemented.

OK, that's important to remember and document especially when documenting <map-a href="...">

I think I might have had the idea that you might not know the zoom, but you wanted to position the map over a location, but it does look a little funny.

@ahmadayubi
Copy link
Member Author

During a discussion it was decided that <map-a href="#..."> would behave as target="_self" for all target values (_blank, _top, etc.).

If the href="#..." then simply zoomTo() the location
If the herf="../#..." (relative URL with fragment) then resolve the URL, replace the current layer with the resolved URL and finally zoomTo() the location

@prushforth
Copy link
Member

LGTM - great work @ahmadayubi, let's go!

@prushforth prushforth merged commit 2914fd0 into Maps4HTML:master Apr 13, 2021
@prushforth
Copy link
Member

I can't get this URL to load properly, it replaces the whole page:

<map-a href="https://geogratis.gc.ca/mapml/en/cbmtile/bedrockgeology/#4,-97.4376874,54.2737257" target="_self" type="text/mapml">

prushforth pushed a commit to prushforth/MapML.js that referenced this pull request Apr 16, 2021
* Add zooming when layer is added

* Add inplace attribute to <map-a>

* Inplace fix

* Allow for async layer adding

* Add comments to event handling

* Add functionality for keypress

* Focus new layer added on projection changes

* Fix link autofocus behavior

* Add test for projection negotiation and hash link

* Fix zoomTo + _self behavior

* Treat all sole fragments, of any target type as target=_self

* Add longer time to test
@ahmadayubi ahmadayubi deleted the zoomToLink branch April 23, 2021 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Zoom to fragment of <map-a href> else zoom to extent of linked resource
2 participants