I am using Leaflet with scalajs-leaflet facade on Binding.scala, and the map initializes/appears incorrectly.
In order to reproduce the issue, i have prepared a lihaoyi/workbench
page similar to that in scalajs-leaflet.
First, download the forked scalajs-leaflet from https://github.com/mcku/scalajs-leaflet
Run sbt
in scalajs-leaflet
directory.
Enter ~ example/fastOptJS
in sbt. Now, a web server started at port 12345.
Open http://localhost:12345/example/target/scala-2.12/classes/leaflet2binding-dev.html in a browser
The problem is the map container appears but the content (tiles, etc) is not correct. Map becomes fine after a small resize on window, which triggers _onResize
handler of leaflet.
The container is in the Leaflet2Binding.scala
file and has its size already specified prior to initialization:
val mapElement = <div id="mapid" style="width: 1000px; height: 600px;
position: relative; outline: currentcolor none medium;"
class="leaflet-container leaflet-touch leaflet-fade-anim
leaflet-grab leaflet-touch-drag leaflet-touch-zoom"
data:tabindex="0"></div>.asInstanceOf[HTMLElement]
It is possible to insert a line lmap.invalidateSize(true)
in the following line before returning the element
https://github.com/mcku/scalajs-leaflet/blob/83b770bc76de450567ababf6c7d2af0700dd58c9/example/src/main/scala/example/Leaflet2Binding.scala#L39, but did not help in this case. Namely here:
@dom def renderMap = {
val mapElement = ... (same element as above)
.. some other initializations ..
lmap.invalidateSize(true) // true means, use animation
println("mapElement._leaflet_id " +mapElement.asInstanceOf[js.Dynamic]._leaflet_id) // prints non-null value, makes me think the container is initialized
mapElement
}
Any ideas? This is binding.scala specific, but it may be a leaflet issue as well.
EDIT Possible workaround
It looks like, the map element has its clientWidth
property not available during the process. Which is understandable as the document is not "ready" yet. However, the css style.width
is available and could be defined in px. In that case it is possible to patch leaflet to take css style width into account during computation.
it works if the style width is specified in px.
diff --git a/src/map/Map.js b/src/map/Map.js
index b94dd443..6544d7b7 100644
--- a/src/map/Map.js
+++ b/src/map/Map.js
@@ -903,8 +903,9 @@ export var Map = Evented.extend({
getSize: function () {
if (!this._size || this._sizeChanged) {
this._size = new Point(
- this._container.clientWidth || 0,
- this._container.clientHeight || 0);
+
+ this._container.clientWidth || parseInt(this._container.style.width.replace("px",""),10) || 0,^M
+ this._container.clientHeight || parseInt(this._container.style.height.replace("px",""),10) || 0);;^M
this._sizeChanged = false;
}
div
doesn't have a defined size at the point that the map initialises, the tiles don't load. If it's not possible to give the map container a size on page load due to something dynamic in your config, you can work round it by callingmap.invalidateSize()
after the container is initialised. – SinatrainvalidateSize()
, notinvalidateResize()
. – SinatrainvalidateSize()
does not help. – SearleinvalidateSize()
executes, is the map container fully initialised in the DOM? – Sinatra_leaflet_id
from the container. See theprintln
in the edit. – Searle