D3js: автоматическое размещение меток, чтобы избежать дублирования? (силы отталкивания)
Как применить силу отталкивания на карте'С надписи так, чтобы они автоматически найти свои места ?
Босток' "Давайте's сделать карту"по
Майк Босток'ы не's сделать на карте](http://bost.ocks.org/mike/map/) (скриншот ниже). По умолчанию, метки ставятся на точки'ы координат и полигоны/мультиполигоны'пути s.центроид(г)
+ простая влево или вправо, выровнять, поэтому они часто вводят в конфликт.
Ручной размещения надписей ## Одно улучшение я встретил требует, чтобы добавить человека в "если" исправления, и добавить столько, сколько нужно, например :
.attr("dy", function(d){ if(d.properties.name==="Berlin") {return ".9em"} })
В целом становятся все более грязными, как количество ярлыков для reajust увеличение :
//places's labels: point objects
svg.selectAll(".place-label")
.data(topojson.object(de, de.objects.places).geometries)
.enter().append("text")
.attr("class", "place-label")
.attr("transform", function(d) { return "translate(" + projection(d.coordinates) + ")"; })
.attr("dy", ".35em")
.text(function(d) { if (d.properties.name!=="Berlin"&&d.properties.name!=="Bremen"){return d.properties.name;} })
.attr("x", function(d) { return d.coordinates[0] > -1 ? 6 : -6; })
.style("text-anchor", function(d) { return d.coordinates[0] > -1 ? "start" : "end"; });
//districts's labels: polygons objects.
svg.selectAll(".subunit-label")
.data(topojson.object(de, de.objects.subunits).geometries)
.enter().append("text")
.attr("class", function(d) { return "subunit-label " + d.properties.name; })
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
.attr("dy", function(d){
//handmade IF
if( d.properties.name==="Sachsen"||d.properties.name==="Thüringen"|| d.properties.name==="Sachsen-Anhalt"||d.properties.name==="Rheinland-Pfalz")
{return ".9em"}
else if(d.properties.name==="Brandenburg"||d.properties.name==="Hamburg")
{return "1.5em"}
else if(d.properties.name==="Berlin"||d.properties.name==="Bremen")
{return "-1em"}else{return ".35em"}}
)
.text(function(d) { return d.properties.name; });
Необходимо для лучшего решения
Что's просто не управляем на больших картах и наборы наклеек. Как добавить отталкивания силу этих обоих классов: .место-этикетка "и".субъединицы-метка
?
Эта проблема вполне себе мозговой штурм, как я не'т срок, но я'я довольно любопытно. Я думал об этом вопрос, как базовая реализация D3js из Migurski/Dymo.py. Дымо.пы's в файле README.МД набор документов большой набор задач, из которых для выбора основных потребностей и функций (20% работы, 80% результата).
- Первичное размещение: Босток дать хороший старт с левым/правым размещением относительно геопоинт.
- Интер-метки отталкивания: иной подход, возможно, Ларс & Navarrc предложил один друг,
- Метки аннигиляции: метка уничтожение функцию, когда одна надпись's общий отталкивания является слишком интенсивным, так как зажатый между другими надписями, с приоритетом на уничтожение либо случайным образом или на основе "население" значение данных, которые мы можем получить через NaturalEarth'ов .файл SHP.
- [Роскошные] ярлык-в-точку отталкивания: с фиксированными точками и мобильных меток. Но это скорее роскошь.
Я игнорирую, если метка отталкивание будет работать через слои и классы метки. Но получать ярлыки странам и городам надписи не перекрываются могут быть класса люкс, а также.
На мой взгляд, раскладка сил непригодна для целей размещения меток на карте. Причина проста -- этикетки должны быть как можно ближе к местам их метки, но раскладка сил не имеет ничего, чтобы осуществить это. Действительно, что касается моделирования, нет никакого вреда в смешение меток, которые явно не желательно на карте.
Там может быть что-то реализовано на верхней части макета силу, что и сами места как основные узлы и силами притяжения между местом и его этикетке, в то время как силы между метками будет отталкивающим. Этого, вероятно, потребуется модифицированная раскладка сил по выполнению (или несколько сил макетов в то же время), поэтому я'м не собираюсь идти по этому пути.
Мое решение основывается только на обнаружение столкновений: для каждой пары меток, проверить, если они пересекаются. Если это так, переместите их в сторону, где направление и величина движения происходит от перекрытия. Таким образом, только метки, которые фактически дублируют друг друга, перемещаются на всех, и ярлыки только отойти немного. Этот процесс повторяется, пока никакого движения не происходит.
Код является немного запутанным, потому что проверка на перекрытие довольно неаккуратно. Я выиграл'т размещать весь код здесь, он может быть найден в демо (заметьте, что я'ве сделал ярлыки гораздо больше преувеличивать эффект). Ключ биты выглядят так:
Все это далеко от совершенства-обратите внимание, что некоторые надписи достаточно далеко от места их метки, но метод универсален и должен, по крайней мере, избежать дублирования меток.
Один вариант заключается в использовании макет силу с множественными очагами. Каждый очаг должен быть расположен в'ы центроид, создать ярлык для того чтобы быть привлечены только соответствующие очаги. Таким образом, каждая метка будет стремиться быть рядом с функцией'ы центроид, но отталкивание с другими надписями могут избежать дублирования вопроса.
Для сравнения:
Соответствующий код:
А ShareMap-dymo.js может работать, он не появляется, чтобы быть очень хорошо документированы. Я нашел библиотеку, которая работает для более общего случая, подтвержден документально, а также использует моделируемый отжиг: Д3-Этикетировочная
Я'вэ собрал образец использования с этим [jsfiddle][2].Д3-Этикетировочная образец страница использует 1000 итераций. Я нашел это довольно ненужным и что 50 итераций, кажется, работает очень хорошо - это очень быстро, даже за несколько сотен точек данных. Я считаю, что есть возможности для совершенствования, как в том, как эта библиотека интегрируется с Д3 и с точки зрения эффективности, но я бы'т быть в состоянии сделать это на мою собственную. Я'будете обновлять этот поток, я должен найти время, чтобы представить себе пиар.
Вот соответствующий код (см. Д3-Этикетировочная ссылке для дальнейшей документации):
Для более глубокий взгляд на то, как Д3-Этикетировочная работ, см. "а Д3 плагин для автоматического размещения надписей с использованием моделирования отжиг на"
Джефф Хитон'ы "и искусственный интеллект для человека, 1 с" объеме; также делает отличную работу, объясняя имитации отжига процесс.
Вы могли бы быть заинтересованы в d3fc-лейбл-макет компонента (для D3v5), которая предназначена именно для этой цели. Компонент обеспечивает механизм для организации дочерние компоненты, основанные на их ящики прямоугольной области. Вы можете применять либо жадные, либо сымитированный отжиг стратегии в целях минимизации дублирования.
Здесь'с фрагментом кода, который демонстрирует, как применить этот макет компонента Майк Босток's карты пример:
И это маленький скриншот результата:
Вы можете увидеть полный пример здесь:
http://bl.ocks.org/ColinEberhardt/389c76c6a544af9f0cab
Дисклеймер: как говорилось в комментарии ниже, я являюсь основным разработчиком этого проекта, поэтому, очевидно, что я несколько предвзята. Полный кредит на другие ответы на этот вопрос, который дал нам вдохновение!
Одним из вариантов является использование макета Вороного, чтобы вычислить, где есть пространство между точками. Там'хороший пример из Майк Босток здесь.
Для 2D случая вот некоторые примеры, которые сделать что-то очень похожее:
один http://bl.ocks.org/1691430 два http://bl.ocks.org/1377729
спасибо Александр Skaburskis, кто принес это здесь
Для случая 1Д Для тех, кто ищет решение аналогичной задачи в 1-d могу поделиться своей песочнице JSfiddle, где я пытаюсь решить. Это'ы далека от совершенства, но он делает дело.
Слева: модель песочницы, справа: пример использования
Вот фрагмент кода, который можно запустить, нажав на кнопку в конце поста, а также сам код. При запуске, щелкните на поле для установки основных узлов.
в
в