2016-12-09 3 views
2

Я пытаюсь реализовать версию вращающегося глобуса Майка Бостока и наложить наклейки на страну. Это было успешно достигнуто здесь: http://bl.ocks.org/dwtkns/4686432Невозможно скрыть этикетки «за спинкой» D3 Globe

К сожалению, я не могу скрыть ярлыки, которые должны падать «позади земного шара». Метод, который я попытался, заключается в вычислении расстояния между центроидами пути и центральным положением земного шара. Но по какой-то причине код, кажется, непоследовательным и скрывается неправильные ярлыки ...

Это бит кода, который скрывает метки:

function position_labels() { 
    var centerPos = projection.invert([width/2, height/2]); 

    var arc = d3.geo.greatArc(); 

    // update: update path projection before applying it to labels position 
    path.projection(projection); 
    svg.selectAll(".label") 
    .attr("transform", function(d) { 

     return "translate(" + path.centroid(d) + ")"; 
    }) 
    .style("display", function(d) { 
     var d = arc.distance({ 
     source: path.centroid(d), 
     target: centerPos 
     }); 
     return (d > 1.57) ? 'inline' : 'none'; 
    }) 
} 

Я спас свою работу в следующем jsfiddle -Пожалуйста, дайте мне знать, что я делаю неправильно: http://jsfiddle.net/Guill84/kh3kegsy/

UPDATE:

ниже представляет собой снимок вопроса в котором названия стран до сих пор, кажется, плавают вокруг карты. Пожалуйста, смотрите мой комментарий ниже для дальнейшего объяснения:

Russia problem

+0

В скрипке вы используете path.centroid(), которая возвращает координаты в координатном пространстве svg. Это работает для размещения меток, однако вам нужны географические координаты центроида, чтобы определить, должна ли надпись быть видимой. Проблема, как мне представляется, заключается в том, что projection.invert (path.centroid (d)) при использовании этого подхода вернет видимую географическую координату при заданной координате svg, что означает, что все метки будут считаться видимыми. Кроме того, вы измеряете расстояние от [190,190] на svg, а не на [400,400], так как ваша ширина и высота составляют 800 пикселей на основе скрипки. –

ответ

2

я отметил потенциальный барьер с использованием координат для определения видимости метки в моем комментарии выше. Тем не менее, существует еще один способ определить, должна ли надпись быть видимой: определение того, имеет ли путь svg страны атрибут 'd', который не является нулевым.

Во-первых, идентификаторы должны быть установлены надлежащим образом, в настоящее время d.properties.name содержит пробелы, поэтому установка идентификаторами с:

.attr("id", function(d) { return d.properties.name.split(' ').join('_'); }) 

позволит более четко идентифицировать такие места, как Соединенное Королевство и Соединенные Штаты ,

Выбрав каждый путь на основе id, мы можем увидеть, есть ли у него какие-либо данные, определяющие его форму. Если это не показано, свойство 'd' пути будет null.

if (d3.select("#"+d.properties.name.split(' ').join('_')).attr('d') != null) { 
     return 'inline'; 
    } 
    else { 
     return 'none'; 
    } 

Обновлено скрипку: here

Использование другого текста якорь может центрировать текст лучше, как хорошо:

.style("text-anchor","middle"); 

Fiddle с текстом якорь посередине: here

--- Обновление --- Хотя приведенный выше код скроет ярлыки для стран, не привлеченных (полностью позади земного шара), если любая часть страны будет нарисована, тогда будет создан ярлык. Множество проблем вокруг этого можно решить, не нарисовав метки, которые находятся на некотором расстоянии от центра: fiddle, as mentioned in comment below.

Однако, для некоторых крупных стран, таких как Россия, географический центр (и, следовательно, расположение этикеток) может находиться в пределах указанного радиуса и будет нарисован, если будет отображена крошечная лента страны. Когда это произойдет, географический центроид, а не центроид svg, будет использоваться для обозначения страны. В этих случаях географический центроид находится на дальнем конце Земли, но выглядит так, как если бы он был на видимой стороне.

Кроме того, в случае Франции, SVG медианы и географический центр тяжести будут проблематичны: France

А методов паров может быть использована для оказания помощи в переключени этикеток, такие как вычисления и записи географических центроиды в географические данные и использование углового расстояния от центра проекции карты, чтобы показать/скрыть метки. В случае с Францией расщепление Гвианы было бы полезно.

Без изменения данных другой критерий может быть использован для выбора того, какие метки должны быть видимыми: видя, находится ли центр ограничивающей рамки страны, как рисованный, рядом с краем карты. Это добавляет дополнительный уровень вычислений, но если каждый критерий проверяется только при необходимости, оно должно быть в порядке: http://jsfiddle.net/0ptcy7f3/1/

var country = d3.select("#"+d.properties.name.split(' ').join('_')); 
// Exclude labels this far from center: 
var r = 350; 

// Check to see if the country has a path visible as before 
if (country.attr('d') != null) { 

    // Then check to see if the bounding box 
    // for the country as drawn is far from center 
    var BB = country.node().getBBox(); 
    var x = (BB.x + (BB.x + BB.width))/2; 
    var y = (BB.y + (BB.y + BB.height))/2; 

    if (((width-x)*(width-x) + (height-y)*(height-y)) < (r * r)) { 
     // And ensure the geographic centroid is also not on the edge: 
     center = path.centroid(d); 
     x = center[0]; 
     y = center[1]; 
    if (((width-x)*(width-x) + (height-y)*(height-y)) < (r * r)) { 
      return 'inline'; 
    } 
    else { 
      return 'none'; 
    } 
    } 
else { return 'none'; } 
else { return 'none'; } 

Случай Франции не рассматриваются, так как это географический путь включает в Гвиану. В код может быть встроен особый случай, чтобы заставить ярлык в определенном месте и оценить это местоположение как допустимое местоположение. В противном случае данные необходимо отредактировать. Это обновление должно заботиться о России или других крупных/длинных странах.

Настройка, которая может быть выполнена, изменяет радиус исключения, поскольку карта увеличена (или вообще не выполняет эту проверку, если карта заполняет весь кадр).

+1

От просмотра, похоже, если страна частично видима, центроид также включает скрытую секцию, поэтому размещение меток может быть немного по краям. Чтобы удалить эти ярлыки, вы можете попробовать что-то вроде этой скрипки : http://jsfiddle.net/6pwcrasf/ –

+0

Ваше решение чрезвычайно элегантно и именно то, что я искал. Я, однако, заметил ошибку ... поскольку некоторые названия стран, похоже, всплывают вокруг карты, независимо от того, видна страна или нет. Франция и Россия - два хороших примера, и мне интересно, не связано ли это с тем, что (а) размер страны и (б) сложность полигона вокруг заморских территорий и т. д.? Я добавил фотографию в OP, чтобы показать, что я имею в виду. – Noobster

+0

Я думаю, что это две причины для беспокойства, и я думаю, что это может быть сочетание обоих, например, полигон Франции включает французскую Гвиану в Южной Америке (и, вероятно, десятки других территорий). В случае России я считаю, что на краю карты может быть крошечная страна, и поскольку страна настолько велика, географический центр может легко попасть в основной радиус исключения, который я установил в комментарии выше , Хм, мне придется подумать об этом немного подробнее. –

Смежные вопросы