Древовидная диаграмма - предотвращение перекрытия узлов метками - PullRequest
1 голос
/ 22 апреля 2019

Я сделал разборную древовидную диаграмму в d3 (v5), упрощенную версию которой можно найти здесь: https://jsfiddle.net/philipnye/cwj9nkhr/.

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

requiredSpacing используется для приблизительного определения необходимого пространства, а minSpacing проверяет минимальный существующий интервалмежду узлами на каждой глубине.

Следующие строки располагают узлы и метки с эффектом перехода:

var nodeUpdate=nodeEnter.merge(node)
    .transition()
    .duration(function() {
        if (loaded==0) {
            return 0;
        }
        else {
            return duration;
        }
    })
    .attr("transform", function(d) {
        return "translate(" + d.x + "," + d.y + ")";
    });

nodeUpdate.select("circle")
    .attr("r", function(d) {
        return radiuses[d.depth];
    })
    .attr("class", function(d) {
        if (d._children) {
            return "filled";
        } else {
            return "unfilled";
        }
    });

nodeUpdate.select("text")
    .style("fill-opacity", function(d) {
        if (minSpacing[d.depth]<requiredSpacing[d.depth]*2 || (d.data.position=='left' && Math.ceil(d.x/5)*5-radiuses[d.depth]-requiredSpacing[d.depth]<margin.left) || (d.data.position=='right' && Math.ceil(d.x/5)*5+radiuses[d.depth]+requiredSpacing[d.depth]>width)) {
            return 1e-6;
        }
        else {
            return 1;
        }
    })
    .attr("class", function(d) {
        if (minSpacing[d.depth]<requiredSpacing[d.depth]*2 || (d.data.position=='left' && Math.ceil(d.x/5)*5-radiuses[d.depth]-requiredSpacing[d.depth]<margin.left) || (d.data.position=='right' && Math.ceil(d.x/5)*5+radiuses[d.depth]+requiredSpacing[d.depth]>width)) {
            return "nodeLabel nonselectable";
        }
        else {
            return "nodeLabel";
        }
    })

Я устанавливаю непрозрачность меток, для которых нет места для показа1e-6 (для включения перехода) и присвойте им класс nonselectable, что означает, что метки не могут быть выбраны.Но я на самом деле не удаляю их - и у меня возникает проблема, заключающаяся в том, что в некоторых случаях они перекрывают узлы и означают, что нельзя щелкать узлы, чтобы развернуть / свернуть дерево ниже этой точки.Посмотрите на узлы на два или три уровня глубже, чем те, которые обозначены как мужской и женский - только на расстоянии от трети до половины узлов можно щелкнуть.(Обратите внимание, что узлы в слое bottom нельзя развернуть / свернуть, так как у них нет дочерних узлов.)

Как мне лучше удалить эти метки или, по крайней мере, остановить их, чтобы предотвратить васот щелчка по узлам?

Вещи, которые я рассмотрел:

  • Изменение порядка прорисовки может предположительно поставить метки «позади» узлов - но я думаю, что это потребует существенной переделкикода, и я не знаю, как
  • Предположительно, было бы возможно впоследствии пройти и удалить узлы с классом nonselectable, но это не самый эффективный подход, и яУ меня были некоторые проблемы при попытке реализовать это
  • Я думаю, что смещение меток куда-то за пределы размеров SVG может работать - хотя я не уверен, как бы я справился с этим с переходом, так чтопользователи не видят
  • Установка font-size близко к нулю.Я попытался прикрепить что-то вроде приведенного ниже кода к своему nodeUpdate коду, но, похоже, это вызвало проблемы с переходом
.attr("font-size", function(d) {
    if (minSpacing[d.depth]<requiredSpacing[d.depth]*2 || (d.data.position=='left' && Math.ceil(d.x/5)*5-radiuses[d.depth]-requiredSpacing[d.depth]<margin.left) || (d.data.position=='right' && Math.ceil(d.x/5)*5+radiuses[d.depth]+requiredSpacing[d.depth]>width)) {
        return '0.1em';
    }
})

Или может быть другой, лучший способ решения этой проблемы.

Как мне это сделать?

1 Ответ

1 голос
/ 22 апреля 2019

Просто установите pointer-events: none; для этих ярлыков:

.nonselectable {
    pointer-events: none;
    etc...
}

На самом деле, поскольку я вижу, что ярлыки не активируются, вы можете установить pointer-events: none; на все из них.

Вот обновленный JSFidle: https://jsfiddle.net/e3j7ta4y/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...