MapBox в cl js: удаление маркеров с карты (после сохранения их в атоме) - PullRequest
1 голос
/ 05 апреля 2020

Фон:

В 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), поэтому я пытаюсь понять, где моя ошибка.

  • Может быть, объект в моем векторе не тот же экземпляр, поэтому удаление его не повлияет на маркер на карте?
  • Или я должен использовать другой подход, когда пытаясь выполнить побочные методы на объектах в векторе?
  • Или я что-то совсем упустил?

1 Ответ

2 голосов
/ 05 апреля 2020

Просто быстрое предположение, попробуйте заменить map на doseq здесь:

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

Функция map ленива и не будет работать, пока не понадобится. Поскольку, по-видимому, после побочного эффекта необходимо удалить маркеры, doseq является правильным выбором. Он предназначен для побочных эффектов и всегда запускается немедленно. Он всегда возвращает nil.

Кроме того, вам нужно разыменовать markers, чтобы получить вектор, а затем просто использовать его в doseq. Не используйте array-seq, так как атом хранит простой вектор Clojure / Script, а не массив JS.

Другой совет: всегда предпочитайте mapv map. Он стремится и устраняет многие проблемы, связанные с синхронизацией и ленивостью. Обязательно изучите Шпаргалку Clojure и версию CL JS .

Кроме того, имейте в виду, что реагент имеет большое значение между списком Clojure и вектором. Иногда вам нужно принудительно вывести (нетерпеливый) векторный результат в seq с (seq ...) или в список через (apply list ...). Вы также можете использовать простую функцию -> list , чтобы подчеркнуть, что вы делаете:

(s/defn ->list :- [s/Any]
  "Coerce any sequential argument into a List."
  [arg :- [s/Any]]
  (apply list arg))
...