leaflet地图在调整大小之前无法正确显示

8
我正在使用Leaflet和scalajs-leaflet facade在Binding.scala上,但地图初始化/出现不正确。
为了重现此问题,我已准备好类似于scalajs-leaflet中的lihaoyi/workbench页面。
首先,从https://github.com/mcku/scalajs-leaflet下载分叉的scalajs-leaflet。
scalajs-leaflet目录中运行sbt。 在sbt中输入~ example/fastOptJS。现在,一个Web服务器在端口12345启动。
在浏览器中打开http://localhost:12345/example/target/scala-2.12/classes/leaflet2binding-dev.html
问题是地图容器出现,但内容(瓷砖等)不正确。在窗口上进行小调整后,地图变得正常,这会触发leaflet的_onResize处理程序。

容器位于Leaflet2Binding.scala文件中,在初始化之前已经指定了其大小:

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]

在返回元素之前,在以下行中插入一行lmap.invalidateSize(true)是可能的https://github.com/mcku/scalajs-leaflet/blob/83b770bc76de450567ababf6c7d2af0700dd58c9/example/src/main/scala/example/Leaflet2Binding.scala#L39,但在这种情况下没有帮助。即在此处:

@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
}

任何想法?这是binding.scala特定的问题,但也可能是一个leaflet问题。 调整大小前的地图 调整大小后的地图 编辑 可能的解决方法 看起来,地图元素在过程中没有可用的clientWidth属性。这是可以理解的,因为文档还没有“准备好”。然而,css style.width是可用的,并且可以以像素为单位定义。在这种情况下,可以修补leaflet以在计算期间考虑css样式宽度。
如果以像素为单位指定样式宽度,则可以正常工作。
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;
                }

4
Leaflet存在一个已知且有文档记录的问题。如果在地图初始化时,地图容器div没有定义大小,瓦片将不会加载。如果由于配置中的某些动态因素无法在页面加载时为地图容器指定大小,则可以通过在容器初始化后调用 map.invalidateSize() 来解决该问题。 - peeebeee
可能是重复的问题:为什么我的地图没有完全显示? - peeebeee
@peeebeee 感谢您的评论。我已更新问题。是的,它与其他问题相似,但不是重复案例(请参见编辑)。 - mcku
2
invalidateSize(),不是 invalidateResize() - peeebeee
我可以从容器中获取_leaflet_id。请参见编辑中的println - mcku
显示剩余2条评论
2个回答

7

可能 lmap.invalidateSize(true) 被过早地调用了(DOM尚未准备好或重绘)。

确保这种情况不会发生。为了防止这种情况,我将代码包装如下:

setTimeout(function () {
   mapid.invalidateSize(true);
}, 100);

这必须在每次DOM重绘之后完成。


不需要显式等待DOM稳定,元素的ID是可查询的(因为绑定已经为我完成了这个操作)。而且,因为我将元素作为参数传递给L.map()函数,而不是元素的ID。 - mcku

0

对于仍然面临react-leaflet问题的人们,可以使组件仅在缩放和中心被初始化时才进行渲染,并在地图不显示时将其移除:

useEffect(() => {
 setCenter([50.5, 30.5]);
 setZoom(14);
}, []);

然后在JSX中

{zoom && center.length > 0 && (
        <div className={styles.map}>
          <Map center={center} zoom={zoom} />
        </div>
 )}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接