当我将鼠标悬停在家谱中的 child 上时,如何突出显示 parents 名称和连接线
How Can I highlight the parents names and the connection lines when I hover on their child in family tree
我正在使用 d3.js 创建家谱,我想做两件事
- 当我将鼠标悬停在 child 上时,如何突出显示 parents 名称和连接线
当我将鼠标悬停在 axelenter image description here
上时喜欢这张图片
- 如何确定每个分支中的最后一个 child,以便为其赋予独特的样式或添加图标
在它之后,例如:像这张图片这样的树叶 enter image description here
这是我的代码片段:
const familyData = [
{
_id: '60da7d37b8ca2d2590f0b713',
child: 'William',
parent: '',
parentId: null
},
{
_id: '60da7d7f6a89ad1fecc905e9',
child: 'James',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7d9619156a6d90874aa1',
child: 'Henry',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7db3c1f2f27368395212',
child: 'Michael',
parent: 'James',
parentId: '60da7d7f6a89ad1fecc905e9'
},
{
_id: '60da7dd32796ae5cbc0e1810',
child: 'Ethan',
parent: 'James',
parentId: '60da7d7f6a89ad1fecc905e9'
},
{
_id: '60da7df79f58c4028cb21d06',
child: 'Jacob',
parent: 'Henry',
parentId: '60da7d9619156a6d90874aa1'
},
{
_id: '60da7e149cf24f1d20167c14',
child: 'Jack',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7e2add5413458427c4b2',
child: 'Joseph',
parent: 'Jack',
parentId: '60da7e149cf24f1d20167c14'
},
{
_id: '60da7e48fec03d0b1c2d10d3',
child: 'Asher',
parent: 'Joseph',
parentId: '60da7e2add5413458427c4b2'
},
{
_id: '60da7e5c8cc6f66264b23e70',
child: 'Leo',
parent: 'Ethan',
parentId: '60da7dd32796ae5cbc0e1810'
},
{
_id: '60da7e89cefbdd785cec5ada',
child: 'Isaac',
parent: 'Leo',
parentId: '60da7e5c8cc6f66264b23e70'
},
{
_id: '60da7e93ed9bd0402487e5c8',
child: 'Charles',
parent: 'Leo',
parentId: '60da7e5c8cc6f66264b23e70'
},
{
_id: '60da7ea006b3694914c99ee0',
child: 'Caleb',
parent: 'Michael',
parentId: '60da7db3c1f2f27368395212'
},
{
_id: '60da7eab6a06e223e42b5d65',
child: 'Ryan',
parent: 'Michael',
parentId: '60da7db3c1f2f27368395212'
},
{
_id: '60da7e6b05ff5f0468d8e835',
child: 'Thomas',
parent: 'Jacob',
parentId: '60da7df79f58c4028cb21d06'
},
{
_id: '60da7eb5b7a93714303ef471',
child: 'Aaron',
parent: 'Thomas',
parentId: '60da7e6b05ff5f0468d8e835'
},
{
_id: '60da7ebcf21a2a44503b7596',
child: 'Axel',
parent: 'Thomas',
parentId: '60da7e6b05ff5f0468d8e835'
}
]
const dataStructure = d3.stratify()
.id(d => d._id)
.parentId(d => d.parentId)(familyData)
const treeStructure = d3.tree()
.size([500,300])
let root = treeStructure(dataStructure)
console.log(root.descendants());
console.log(root.links());
const svg = d3.select('svg')
.attr('width',600)
.attr('height',600)
const nodes = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('circle')
.data(root.descendants())
.enter()
.append('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.attr('r', 3)
.attr('fill', function(d){
if(d.depth === 0) return 'black'
else if (d.depth === 1) return 'red'
else if (d.depth === 2) return 'green'
else if (d.depth === 3) return 'magenta'
else return 'brown'
})
const connections = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('path')
.data(root.links())
.enter()
.append('path')
.attr('d', d => `M ${d.source.x} ${d.source.y} C ${d.source.x} ${(d.source.y + d.target.y) / 2},
${d.target.x} ${(d.source.y + d.target.y) / 2}, ${d.target.x} ${d.target.y}`)
const names = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('text')
.data(root.descendants())
.enter()
.append('text')
.text(d => d.data.child)
.attr('x', d => d.x + 8)
.attr('y', d => d.y + 2)
.style('font-size', '1rem')
.on('mouseover', function(e,d){
d3.select(this)
.transition()
.duration('100')
.attr('opacity', 1)
.style('font-size','2rem')
d3.selectAll('text').attr('opacity', '0.3')
d3.selectAll('circle').attr('opacity', '0.3')
})
.on('mouseout', function(d){
d3.select(this)
.style('font-size','1rem')
d3.selectAll('text').attr('opacity', '1')
d3.selectAll('circle').attr('opacity', '1')
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://unpkg.com/d3@7.0.0/dist/d3.min.js"></script>
<script src='try.js' defer></script>
<style>
path {
fill:transparent;
stroke:teal;
}
text {
cursor: pointer;
}
</style>
<title>Document</title>
</head>
<body>
<svg></svg>
</body>
</html>
要突出显示祖先路径,您需要将 id
属性添加到 connections
:
.attr('id', d => "link_" + d.target.data._id)
和 names
:
.attr('id', d => d.data.child)
然后在 mouseover
和 mouseout
事件中调用函数来突出显示和 un-highlight 路径。您需要在 highlightPath
函数中引用 id
s:
function unhighlightPath(event, d) {
//reset all nodes color
d3.selectAll("path").style("stroke", "teal");
}
function highlightPath(event, d) {
// select link from hovered label to immediate parent
d3.select("#link_" + d.data._id).style("stroke", "red");
// keep going up until no more parents
while (d.parent) {
if (d.parent != "null") {
d3.selectAll("#link_"+d.parent.data._id).style("stroke", "red")
}
d = d.parent;
}
}
要确定节点是否为叶节点,请测试 .children
是否存在。我将您的代码调整为 parents 红色和 children 蓝色。您可以使用此测试并根据您的要求添加图标和样式。
.attr('fill', function(d){
//if(d.depth === 0) return 'black'
//else if (d.depth === 1) return 'red'
//else if (d.depth === 2) return 'green'
//else if (d.depth === 3) return 'magenta'
//else return 'brown'
if (d.children) {
// not leaf nodes
return "red";
} else {
// leaf nodes
// do some stuff like icons, extra styling
return "blue"; // for the node colour
}
您的代码改编:
const familyData = [
{
_id: '60da7d37b8ca2d2590f0b713',
child: 'William',
parent: '',
parentId: null
},
{
_id: '60da7d7f6a89ad1fecc905e9',
child: 'James',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7d9619156a6d90874aa1',
child: 'Henry',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7db3c1f2f27368395212',
child: 'Michael',
parent: 'James',
parentId: '60da7d7f6a89ad1fecc905e9'
},
{
_id: '60da7dd32796ae5cbc0e1810',
child: 'Ethan',
parent: 'James',
parentId: '60da7d7f6a89ad1fecc905e9'
},
{
_id: '60da7df79f58c4028cb21d06',
child: 'Jacob',
parent: 'Henry',
parentId: '60da7d9619156a6d90874aa1'
},
{
_id: '60da7e149cf24f1d20167c14',
child: 'Jack',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7e2add5413458427c4b2',
child: 'Joseph',
parent: 'Jack',
parentId: '60da7e149cf24f1d20167c14'
},
{
_id: '60da7e48fec03d0b1c2d10d3',
child: 'Asher',
parent: 'Joseph',
parentId: '60da7e2add5413458427c4b2'
},
{
_id: '60da7e5c8cc6f66264b23e70',
child: 'Leo',
parent: 'Ethan',
parentId: '60da7dd32796ae5cbc0e1810'
},
{
_id: '60da7e89cefbdd785cec5ada',
child: 'Isaac',
parent: 'Leo',
parentId: '60da7e5c8cc6f66264b23e70'
},
{
_id: '60da7e93ed9bd0402487e5c8',
child: 'Charles',
parent: 'Leo',
parentId: '60da7e5c8cc6f66264b23e70'
},
{
_id: '60da7ea006b3694914c99ee0',
child: 'Caleb',
parent: 'Michael',
parentId: '60da7db3c1f2f27368395212'
},
{
_id: '60da7eab6a06e223e42b5d65',
child: 'Ryan',
parent: 'Michael',
parentId: '60da7db3c1f2f27368395212'
},
{
_id: '60da7e6b05ff5f0468d8e835',
child: 'Thomas',
parent: 'Jacob',
parentId: '60da7df79f58c4028cb21d06'
},
{
_id: '60da7eb5b7a93714303ef471',
child: 'Aaron',
parent: 'Thomas',
parentId: '60da7e6b05ff5f0468d8e835'
},
{
_id: '60da7ebcf21a2a44503b7596',
child: 'Axel',
parent: 'Thomas',
parentId: '60da7e6b05ff5f0468d8e835'
}
]
const dataStructure = d3.stratify()
.id(d => d._id)
.parentId(d => d.parentId)(familyData)
const treeStructure = d3.tree().size([500,300])
let root = treeStructure(dataStructure)
//console.log(root.descendants());
//console.log(root.links());
const svg = d3.select('svg')
.attr('width',600)
.attr('height',600)
const nodes = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('circle')
.data(root.descendants())
.enter()
.append('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.attr('r', 3)
.attr('fill', function(d){
//if(d.depth === 0) return 'black'
//else if (d.depth === 1) return 'red'
//else if (d.depth === 2) return 'green'
//else if (d.depth === 3) return 'magenta'
//else return 'brown'
if (d.children) {
// not leaf nodes
return "red";
} else {
// leaf nodes
// do some stuff like icons, extra styling
return "blue"; // for the node colour
}
})
const connections = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('path')
.data(root.links())
.enter()
.append('path')
.attr('id', d => "link_" + d.target.data._id)
.attr('d', d => `M ${d.source.x} ${d.source.y} C ${d.source.x} ${(d.source.y + d.target.y) / 2},
${d.target.x} ${(d.source.y + d.target.y) / 2}, ${d.target.x} ${d.target.y}`)
const names = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('text')
.data(root.descendants())
.enter()
.append('text')
.attr('id', d => d.data.child)
.text(d => d.data.child)
.attr('x', d => d.x + 8)
.attr('y', d => d.y + 2)
.style('font-size', '1rem')
.on('mouseover', function(e,d){
d3.select(this)
.transition()
.duration('100')
.attr('opacity', 1)
.style('font-size','2rem')
d3.selectAll('text').attr('opacity', '0.3')
d3.selectAll('circle').attr('opacity', '0.3');
highlightPath(e, d);
})
.on('mouseout', function(e, d){
d3.select(this)
.style('font-size','1rem')
d3.selectAll('text').attr('opacity', '1')
d3.selectAll('circle').attr('opacity', '1');
unhighlightPath(e, d)
});
// ancestor paths
function unhighlightPath(event, d) {
//reset all nodes color
d3.selectAll("path").style("stroke", "teal");
}
function highlightPath(event, d) {
// select link from hovered label to immediate parent
d3.select("#link_" + d.data._id).style("stroke", "red");
// keep going up until no more parents
while (d.parent) {
if (d.parent != "null") {
d3.selectAll("#link_"+d.parent.data._id).style("stroke", "red")
}
d = d.parent;
}
}
path {
fill:transparent;
stroke:teal;
}
text {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.0/d3.min.js"></script>
<svg></svg>
我正在使用 d3.js 创建家谱,我想做两件事
- 当我将鼠标悬停在 child 上时,如何突出显示 parents 名称和连接线 当我将鼠标悬停在 axelenter image description here 上时喜欢这张图片
- 如何确定每个分支中的最后一个 child,以便为其赋予独特的样式或添加图标 在它之后,例如:像这张图片这样的树叶 enter image description here
这是我的代码片段:
const familyData = [
{
_id: '60da7d37b8ca2d2590f0b713',
child: 'William',
parent: '',
parentId: null
},
{
_id: '60da7d7f6a89ad1fecc905e9',
child: 'James',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7d9619156a6d90874aa1',
child: 'Henry',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7db3c1f2f27368395212',
child: 'Michael',
parent: 'James',
parentId: '60da7d7f6a89ad1fecc905e9'
},
{
_id: '60da7dd32796ae5cbc0e1810',
child: 'Ethan',
parent: 'James',
parentId: '60da7d7f6a89ad1fecc905e9'
},
{
_id: '60da7df79f58c4028cb21d06',
child: 'Jacob',
parent: 'Henry',
parentId: '60da7d9619156a6d90874aa1'
},
{
_id: '60da7e149cf24f1d20167c14',
child: 'Jack',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7e2add5413458427c4b2',
child: 'Joseph',
parent: 'Jack',
parentId: '60da7e149cf24f1d20167c14'
},
{
_id: '60da7e48fec03d0b1c2d10d3',
child: 'Asher',
parent: 'Joseph',
parentId: '60da7e2add5413458427c4b2'
},
{
_id: '60da7e5c8cc6f66264b23e70',
child: 'Leo',
parent: 'Ethan',
parentId: '60da7dd32796ae5cbc0e1810'
},
{
_id: '60da7e89cefbdd785cec5ada',
child: 'Isaac',
parent: 'Leo',
parentId: '60da7e5c8cc6f66264b23e70'
},
{
_id: '60da7e93ed9bd0402487e5c8',
child: 'Charles',
parent: 'Leo',
parentId: '60da7e5c8cc6f66264b23e70'
},
{
_id: '60da7ea006b3694914c99ee0',
child: 'Caleb',
parent: 'Michael',
parentId: '60da7db3c1f2f27368395212'
},
{
_id: '60da7eab6a06e223e42b5d65',
child: 'Ryan',
parent: 'Michael',
parentId: '60da7db3c1f2f27368395212'
},
{
_id: '60da7e6b05ff5f0468d8e835',
child: 'Thomas',
parent: 'Jacob',
parentId: '60da7df79f58c4028cb21d06'
},
{
_id: '60da7eb5b7a93714303ef471',
child: 'Aaron',
parent: 'Thomas',
parentId: '60da7e6b05ff5f0468d8e835'
},
{
_id: '60da7ebcf21a2a44503b7596',
child: 'Axel',
parent: 'Thomas',
parentId: '60da7e6b05ff5f0468d8e835'
}
]
const dataStructure = d3.stratify()
.id(d => d._id)
.parentId(d => d.parentId)(familyData)
const treeStructure = d3.tree()
.size([500,300])
let root = treeStructure(dataStructure)
console.log(root.descendants());
console.log(root.links());
const svg = d3.select('svg')
.attr('width',600)
.attr('height',600)
const nodes = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('circle')
.data(root.descendants())
.enter()
.append('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.attr('r', 3)
.attr('fill', function(d){
if(d.depth === 0) return 'black'
else if (d.depth === 1) return 'red'
else if (d.depth === 2) return 'green'
else if (d.depth === 3) return 'magenta'
else return 'brown'
})
const connections = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('path')
.data(root.links())
.enter()
.append('path')
.attr('d', d => `M ${d.source.x} ${d.source.y} C ${d.source.x} ${(d.source.y + d.target.y) / 2},
${d.target.x} ${(d.source.y + d.target.y) / 2}, ${d.target.x} ${d.target.y}`)
const names = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('text')
.data(root.descendants())
.enter()
.append('text')
.text(d => d.data.child)
.attr('x', d => d.x + 8)
.attr('y', d => d.y + 2)
.style('font-size', '1rem')
.on('mouseover', function(e,d){
d3.select(this)
.transition()
.duration('100')
.attr('opacity', 1)
.style('font-size','2rem')
d3.selectAll('text').attr('opacity', '0.3')
d3.selectAll('circle').attr('opacity', '0.3')
})
.on('mouseout', function(d){
d3.select(this)
.style('font-size','1rem')
d3.selectAll('text').attr('opacity', '1')
d3.selectAll('circle').attr('opacity', '1')
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://unpkg.com/d3@7.0.0/dist/d3.min.js"></script>
<script src='try.js' defer></script>
<style>
path {
fill:transparent;
stroke:teal;
}
text {
cursor: pointer;
}
</style>
<title>Document</title>
</head>
<body>
<svg></svg>
</body>
</html>
要突出显示祖先路径,您需要将 id
属性添加到 connections
:
.attr('id', d => "link_" + d.target.data._id)
和 names
:
.attr('id', d => d.data.child)
然后在 mouseover
和 mouseout
事件中调用函数来突出显示和 un-highlight 路径。您需要在 highlightPath
函数中引用 id
s:
function unhighlightPath(event, d) {
//reset all nodes color
d3.selectAll("path").style("stroke", "teal");
}
function highlightPath(event, d) {
// select link from hovered label to immediate parent
d3.select("#link_" + d.data._id).style("stroke", "red");
// keep going up until no more parents
while (d.parent) {
if (d.parent != "null") {
d3.selectAll("#link_"+d.parent.data._id).style("stroke", "red")
}
d = d.parent;
}
}
要确定节点是否为叶节点,请测试 .children
是否存在。我将您的代码调整为 parents 红色和 children 蓝色。您可以使用此测试并根据您的要求添加图标和样式。
.attr('fill', function(d){
//if(d.depth === 0) return 'black'
//else if (d.depth === 1) return 'red'
//else if (d.depth === 2) return 'green'
//else if (d.depth === 3) return 'magenta'
//else return 'brown'
if (d.children) {
// not leaf nodes
return "red";
} else {
// leaf nodes
// do some stuff like icons, extra styling
return "blue"; // for the node colour
}
您的代码改编:
const familyData = [
{
_id: '60da7d37b8ca2d2590f0b713',
child: 'William',
parent: '',
parentId: null
},
{
_id: '60da7d7f6a89ad1fecc905e9',
child: 'James',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7d9619156a6d90874aa1',
child: 'Henry',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7db3c1f2f27368395212',
child: 'Michael',
parent: 'James',
parentId: '60da7d7f6a89ad1fecc905e9'
},
{
_id: '60da7dd32796ae5cbc0e1810',
child: 'Ethan',
parent: 'James',
parentId: '60da7d7f6a89ad1fecc905e9'
},
{
_id: '60da7df79f58c4028cb21d06',
child: 'Jacob',
parent: 'Henry',
parentId: '60da7d9619156a6d90874aa1'
},
{
_id: '60da7e149cf24f1d20167c14',
child: 'Jack',
parent: 'William',
parentId: '60da7d37b8ca2d2590f0b713'
},
{
_id: '60da7e2add5413458427c4b2',
child: 'Joseph',
parent: 'Jack',
parentId: '60da7e149cf24f1d20167c14'
},
{
_id: '60da7e48fec03d0b1c2d10d3',
child: 'Asher',
parent: 'Joseph',
parentId: '60da7e2add5413458427c4b2'
},
{
_id: '60da7e5c8cc6f66264b23e70',
child: 'Leo',
parent: 'Ethan',
parentId: '60da7dd32796ae5cbc0e1810'
},
{
_id: '60da7e89cefbdd785cec5ada',
child: 'Isaac',
parent: 'Leo',
parentId: '60da7e5c8cc6f66264b23e70'
},
{
_id: '60da7e93ed9bd0402487e5c8',
child: 'Charles',
parent: 'Leo',
parentId: '60da7e5c8cc6f66264b23e70'
},
{
_id: '60da7ea006b3694914c99ee0',
child: 'Caleb',
parent: 'Michael',
parentId: '60da7db3c1f2f27368395212'
},
{
_id: '60da7eab6a06e223e42b5d65',
child: 'Ryan',
parent: 'Michael',
parentId: '60da7db3c1f2f27368395212'
},
{
_id: '60da7e6b05ff5f0468d8e835',
child: 'Thomas',
parent: 'Jacob',
parentId: '60da7df79f58c4028cb21d06'
},
{
_id: '60da7eb5b7a93714303ef471',
child: 'Aaron',
parent: 'Thomas',
parentId: '60da7e6b05ff5f0468d8e835'
},
{
_id: '60da7ebcf21a2a44503b7596',
child: 'Axel',
parent: 'Thomas',
parentId: '60da7e6b05ff5f0468d8e835'
}
]
const dataStructure = d3.stratify()
.id(d => d._id)
.parentId(d => d.parentId)(familyData)
const treeStructure = d3.tree().size([500,300])
let root = treeStructure(dataStructure)
//console.log(root.descendants());
//console.log(root.links());
const svg = d3.select('svg')
.attr('width',600)
.attr('height',600)
const nodes = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('circle')
.data(root.descendants())
.enter()
.append('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.attr('r', 3)
.attr('fill', function(d){
//if(d.depth === 0) return 'black'
//else if (d.depth === 1) return 'red'
//else if (d.depth === 2) return 'green'
//else if (d.depth === 3) return 'magenta'
//else return 'brown'
if (d.children) {
// not leaf nodes
return "red";
} else {
// leaf nodes
// do some stuff like icons, extra styling
return "blue"; // for the node colour
}
})
const connections = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('path')
.data(root.links())
.enter()
.append('path')
.attr('id', d => "link_" + d.target.data._id)
.attr('d', d => `M ${d.source.x} ${d.source.y} C ${d.source.x} ${(d.source.y + d.target.y) / 2},
${d.target.x} ${(d.source.y + d.target.y) / 2}, ${d.target.x} ${d.target.y}`)
const names = svg.append('g')
.attr('transform','translate(50,50)')
.selectAll('text')
.data(root.descendants())
.enter()
.append('text')
.attr('id', d => d.data.child)
.text(d => d.data.child)
.attr('x', d => d.x + 8)
.attr('y', d => d.y + 2)
.style('font-size', '1rem')
.on('mouseover', function(e,d){
d3.select(this)
.transition()
.duration('100')
.attr('opacity', 1)
.style('font-size','2rem')
d3.selectAll('text').attr('opacity', '0.3')
d3.selectAll('circle').attr('opacity', '0.3');
highlightPath(e, d);
})
.on('mouseout', function(e, d){
d3.select(this)
.style('font-size','1rem')
d3.selectAll('text').attr('opacity', '1')
d3.selectAll('circle').attr('opacity', '1');
unhighlightPath(e, d)
});
// ancestor paths
function unhighlightPath(event, d) {
//reset all nodes color
d3.selectAll("path").style("stroke", "teal");
}
function highlightPath(event, d) {
// select link from hovered label to immediate parent
d3.select("#link_" + d.data._id).style("stroke", "red");
// keep going up until no more parents
while (d.parent) {
if (d.parent != "null") {
d3.selectAll("#link_"+d.parent.data._id).style("stroke", "red")
}
d = d.parent;
}
}
path {
fill:transparent;
stroke:teal;
}
text {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.0/d3.min.js"></script>
<svg></svg>