Изменить сплошную ссылку на конкретный узел в пунктирный программно в d3

Shan-Desai спросил: 12 мая 2018 в 04:49 в: angular

Тип графика

Радиальное Tidy Tree

Текущий вывод

Сначала я начинаю с ответа JSON с сервера и делаю рекурсия, чтобы сделать JSON плоской и использовать d3.tree для построения рисунка, показанного ниже.

Я запрограммировал узел Legislation таким образом, чтобы при двойном щелчке он отправил некоторую информацию в бэкэнд и получить новый JSON, который требует, чтобы график был повторно зарегистрирован.

При повторной передаче узел изменится на Manufacturer/Legislation, как показано ниже:

Как и на картинке, я хочу сделать эту конкретную ссылку strokedashed, чтобы указать, что конкретный узел был изменен.

code

Для краткости я обрезаю код здесь:

ngAfterViewInit(): void {
        const self = this;
        const svg = d3.select('svg'),
            width = +svg.attr('width'),
            height = +svg.attr('height'),
            g = svg.append('g').attr('transform', 'translate(' + (width / 3 + 240) + ',' + (height / 3 + 140) + ')');        const tree = d3.tree()
            .size([2 * Math.PI, 375])
            .separation(function(a, b) { return (a.parent === b.parent ? 1 : 2) / a.depth; });
        const root = tree(d3.hierarchy(this.parse_node(this.config['viewStructure'])));
        this.root = root; // store this is private variable
        const link = g.selectAll('.link')
            .data(root.links())
            .enter().append('path')
            .attr('class', 'link')
            .attr('d', <any>d3.linkRadial()
                .angle(function(d) { return d['x']; })
                .radius(function(d) { return d['y']; }));        const node = g.selectAll('.node')
            .data(root.descendants())
            .enter().append('g')
            .attr('class', function(d) { return 'node' + (d.children ? ' node--internal' : ' node--leaf'); })
            .attr('transform', function(d) { return 'translate(' + radialPoint(d.x, d.y) + ')'; })
            .on('click', click)
            .on('dblclick', dblclick);        node.append('circle')
            .attr('r', 5)
            .style('fill', (d) => {
                if (d.data['color'] === 'green') {
                    return '#0f0';
                } else {
                    if (d.depth === 0) {
                        return '#999';
                    }
                    return '#f00';
                }
            });        node.append('text')
            .attr('dy', '0.31em')
            .attr('x', function(d) { return d.x < Math.PI === !d.children ? 6 : -6; })
            .attr('text-anchor', function(d) { return d.x < Math.PI === !d.children ? 'start' : 'end'; })
            .attr('transform', function(d) {
                return 'rotate(' + (d.x < Math.PI ? d.x - Math.PI / 2 : d.x + Math.PI / 2) * 180 / Math.PI + ')'; })
            .text(function(d) { return d.data['name']; });        function radialPoint(x, y) {
            return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)];
        }     // For brevity removed the click and double click logic..
    }

Функция ретрансляции

getProperties() {
  // .... Some logic
  const self = this;
  function askExtension() {
            // call the backend, get the json response
            // rerender with some latency here..
            setTimeout(() => {
                d3.selectAll('svg > *').remove();
                self.ngAfterViewInit();
                console.log(nodeInfo.parent.data.name + '/' + nodeInfo.data.name); // `Manufacturer/Legislation`               // I can use self.root here to find the node 
               // how do I get the link information here and change            }, 1000);
        }
}

Я попытался использовать .forEach() для циклического перехода через self.root.descendants(), найти и используйте функцию Manufacturer/Legislation, но это не соответствует моей цели.

Как я могу программно сделать конкретную ссылку пунктирной, пост-рендеринга?


1 ответ

Есть решение
farlee2121 ответил: 22 мая 2018 в 09:06

Если я правильно понимаю вашу проблему, вы можете использовать функцию стиля, которую вы используете для цвета узла.

По существу, когда вы объединяете узлы, задайте класс или некоторый атрибут, который позволяет вам его дифференцировать , Затем вы можете установить стиль условно.

link.style('stroke-dasharray', function(d){ if(d.data['someprop'] === 'valueForMerged'){
  return ("10,3");
}
else{
  return undefined;
}

В этой статье далее описывается.

Кроме того, это сайт объясняет инсульт-дашарай. По существу, формат dasharray "# пикселей вкл., # Пикселей выключен".

Shan-Desai ответил: 22 мая 2018 в 08:22
Ого! фантастика. В качестве тестового примера я попытался: link.style('stroke-dasharray', function(d) {if (d['target']['data']['name'] === 'Manufacturer/Legislation' {return ('10,3');} else {return undefined;}}, и он отлично работает. Я ищу некоторый параметр, который мог бы сделать этот процесс автоматическим.
farlee2121 ответил: 22 мая 2018 в 09:09
Чтобы уточнить, вы имеете в виду, что ищете обобщенный тест для поиска измененных филиалов?
Shan-Desai ответил: 22 мая 2018 в 09:26
Да. Это то, что я ищу. В настоящее время я использую имя текущего узла + имя ближайшего родительского узла в качестве проверки, чтобы увидеть, есть ли объединенныйNode на графике