cljs 中的 MapBox:从地图中删除标记(将它们存储在原子中之后)
MapBox in cljs: Removing markers from map (after storing them in an atom)
背景:
在 mapbox-gl-js
中,虽然您可以从地图中删除图层和要素(因为存储了引用),但 。相反,必须存储对任何添加的标记的引用,否则以后将无法删除它们。
var marker = new mapboxgl.Marker().addTo(map);
marker.remove();
设置:
我有一个原子,我可以在其中添加我创建的每个标记,以便稍后清理它们。
(defonce markers (r/atom []))
(defn add-marker [map img coordinate]
(let [marker (create-marker img)]
(.setLngLat marker (clj->js coordinate))
(.addTo marker map)
(swap! markers conj marker)))
(defn clear-markers []
(doseq [m (array-seq markers)] (.remove m))
(reset! markers []))
但是,如果我调用 clear-markers
,则什么也不会发生。没有错误,没有警告,标记只是停留在地图上。
如果我在添加后立即删除标记(只是为了尝试一下),它会按照文档中的描述工作:
(defn test-marker [map img coordinate]
(let [marker (create-marker img)]
(.setLngLat marker (clj->js coordinate))
(.addTo marker map)
(.remove marker)))
显然,使用此代码,标记将在添加后立即删除,因此永远不会出现在地图上,这不是预期的行为,只是一个测试。
我也尝试了其他方法来调用向量的元素 .remove
,以下是我的第一次尝试:
(defn clear-markers []
(map #(.remove %) markers))
我是 Clojure(Script) 的新手,所以我试图了解我的错误所在。
- 我的向量中的对象可能不是同一个实例,所以删除它不会影响地图上的标记吗?
- 或者在尝试对向量中的对象执行副作用方法时,我是否必须采用不同的方法?
- 还是我完全错过了其他东西?
只是一个快速的猜测,尝试在此处将 map
替换为 doseq
:
(defn clear-markers []
(doseq [marker @markers]
(.remove marker)))
map
函数是惰性的,除非必须,否则不会 运行。由于您似乎正在寻找去除标记的副作用,因此 doseq
是正确的选择。它是为副作用而设计的,总是 运行s 立即。它总是 returns nil
.
此外,您需要取消引用 markers
以获得向量,然后在 doseq
中使用它。不要使用 array-seq
因为原子存储一个普通的 Clojure/Script 向量,而不是 JS 数组。
另一个提示:总是更喜欢 mapv
而不是 map
。它很急切并消除了许多与计时和惰性相关的问题。一定要好好学习the Clojure CheatSheet and the CLJS version.
另外,请注意 Reagent 在 Clojure 列表和向量之间有很大的不同。您有时需要将(急切的)矢量结果强制转换为 seq
和 (seq ...)
或通过 (apply list ...)
的列表。您还可以使用简单的 ->list 功能来强调您在做什么:
(s/defn ->list :- [s/Any]
"Coerce any sequential argument into a List."
[arg :- [s/Any]]
(apply list arg))
背景:
在 mapbox-gl-js
中,虽然您可以从地图中删除图层和要素(因为存储了引用),但
var marker = new mapboxgl.Marker().addTo(map);
marker.remove();
设置:
我有一个原子,我可以在其中添加我创建的每个标记,以便稍后清理它们。
(defonce markers (r/atom []))
(defn add-marker [map img coordinate]
(let [marker (create-marker img)]
(.setLngLat marker (clj->js coordinate))
(.addTo marker map)
(swap! markers conj marker)))
(defn clear-markers []
(doseq [m (array-seq markers)] (.remove m))
(reset! markers []))
但是,如果我调用 clear-markers
,则什么也不会发生。没有错误,没有警告,标记只是停留在地图上。
如果我在添加后立即删除标记(只是为了尝试一下),它会按照文档中的描述工作:
(defn test-marker [map img coordinate]
(let [marker (create-marker img)]
(.setLngLat marker (clj->js coordinate))
(.addTo marker map)
(.remove marker)))
显然,使用此代码,标记将在添加后立即删除,因此永远不会出现在地图上,这不是预期的行为,只是一个测试。
我也尝试了其他方法来调用向量的元素 .remove
,以下是我的第一次尝试:
(defn clear-markers []
(map #(.remove %) markers))
我是 Clojure(Script) 的新手,所以我试图了解我的错误所在。
- 我的向量中的对象可能不是同一个实例,所以删除它不会影响地图上的标记吗?
- 或者在尝试对向量中的对象执行副作用方法时,我是否必须采用不同的方法?
- 还是我完全错过了其他东西?
只是一个快速的猜测,尝试在此处将 map
替换为 doseq
:
(defn clear-markers []
(doseq [marker @markers]
(.remove marker)))
map
函数是惰性的,除非必须,否则不会 运行。由于您似乎正在寻找去除标记的副作用,因此 doseq
是正确的选择。它是为副作用而设计的,总是 运行s 立即。它总是 returns nil
.
此外,您需要取消引用 markers
以获得向量,然后在 doseq
中使用它。不要使用 array-seq
因为原子存储一个普通的 Clojure/Script 向量,而不是 JS 数组。
另一个提示:总是更喜欢 mapv
而不是 map
。它很急切并消除了许多与计时和惰性相关的问题。一定要好好学习the Clojure CheatSheet and the CLJS version.
另外,请注意 Reagent 在 Clojure 列表和向量之间有很大的不同。您有时需要将(急切的)矢量结果强制转换为 seq
和 (seq ...)
或通过 (apply list ...)
的列表。您还可以使用简单的 ->list 功能来强调您在做什么:
(s/defn ->list :- [s/Any]
"Coerce any sequential argument into a List."
[arg :- [s/Any]]
(apply list arg))