1

背景:

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) 很陌生,所以我试着理解我的错误在哪里。

  • 我的向量中的对象可能不是同一个实例,所以删除它不会影响地图上的标记吗?
  • 或者在尝试对向量中的对象执行副作用方法时,我是否必须采取不同的方法?
  • 还是我完全错过了其他东西?
4

1 回答 1

2

只是一个快速的猜测,尝试在这里map替换doseq

(defn clear-markers []
  (doseq [marker @markers]
    (.remove marker)))

map函数是惰性的,直到它必须运行时才会运行。既然看起来你是在消除标记的副作用之后,doseq是正确的选择。它适用于副作用,并始终立即运行。它总是返回nil

此外,您需要 derefmarkers来获取一个向量,然后在doseq. 不要使用array-seq,因为 atom 存储的是普通的 Clojure/Script 向量,而不是 JS 数组。

另一个提示:总是喜欢mapv. map它是急切的,并消除了许多与时间和惰性相关的问题。请务必学习Clojure CheatSheetCLJS 版本

另外,请注意 Reagent 在 Clojure 列表和向量之间有很大的不同。您有时需要通过 将(渴望的)向量结果强制转换为seqwith(seq ...)或列表(apply list ...)。你也可以使用简单的->list函数来强调你在做什么:

(s/defn ->list :- [s/Any]
  "Coerce any sequential argument into a List."
  [arg :- [s/Any]]
  (apply list arg))
于 2020-04-05T17:35:22.713 回答