我仍然在图表上,我需要默认关闭2级和3级节点,并在单击时保持展开/折叠功能。
根据单击的节点及其级别,运行特定的操作(例如,更改颜色)。正如您可以看到的那样,我的链接必须是我的数据对象(代码笔中的var pubs)的值(下面是0级没有链接,在我的示例中为“ TOOLS”):
{
"name": "TOOLS",
"children":
[
{
"name": "Localization",
"url": "http://#",
"children":
[
{"name": "FRANCE", "url": "http://france.fr"}
...
最后在“ mouseover”上使用另一个事件侦听器在节点上(关闭或打开)进行一些样式设置,等等...
答案 0 :(得分:1)
如果要默认关闭第2级和第3级,则可以将children
对象中的每个_children
属性重命名为pubs
。就像您已经在点击处理程序中所做的一样,仅从带有下划线的子项开始就可以。对于您的其他问题,我还没有答案。
赞:
{
"name": "TOOLS",
"_children":
[
{
"name": "Localization",
"url": "http://#",
"_children":
[
{"name": "FRANCE", "url": "http://france.fr"}
...
答案 1 :(得分:1)
如果要折叠除根节点和第一组子节点以外的所有节点,可以运行以下代码:
root.children.forEach(collapse);
这将collapse
函数递归应用于根的所有子代。
您的节点上已经有一个单击事件侦听器,您可以根据计划进行更改。为mouseover和mouseout事件添加侦听器非常简单:
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.on("click", click)
.on('mouseover', mouseover) // mouseover!
.on('mouseout', mouseout) // mouseout!
然后,您需要添加一些函数来定义发生的动作。这是几个示例函数:
// `d` is the data item attached to the DOM node;
// `this` is the node that triggered the event (`g.node`)
function mouseover(d) {
// select the `rect` node that is the child of the DOM node that triggered the event
d3.select(this).select('rect').style('fill', function(d){
// depending on the level of the node, give it one of these tacky colours
if (d.depth === 0) {
return 'deepskyblue'
} else if (d.depth === 1) {
return 'deeppink'
} else if (d.depth === 2) {
return 'goldenrod'
}
return 'papayawhip' // default
})
}
function mouseout(d) {
// select the rect element
d3.select(this).select('rect')
// if the node has collapsed children, turn it light blue; otherwise turn it red
.style('fill', d => d._children ? "lightsteelblue" : "red")
}
您还可以通过类似的方式向click
函数添加其他功能。
以下是活动中的事件侦听器:
var pubs = {
"name": "TOOLS",
"children": [{
"name": "Localization",
"children": [{
"name": "FRANCE"
},
{
"name": "SUISSE"
},
{
"name": "USA"
},
{
"name": "UK"
}
]
},
{
"name": "Test",
"children": [{
"name": "FRANCE"
},
{
"name": "SUISSE"
},
{
"name": "USA"
},
{
"name": "UK"
}
]
},
{
"name": "Oh My God",
"children": [{
"name": "FRANCE"
},
{
"name": "SUISSE"
},
{
"name": "USA"
},
{
"name": "UK"
}
]
},
{
"name": "Another Tool",
"children": [{
"name": "FRANCE"
},
{
"name": "SUISSE"
},
{
"name": "USA"
},
{
"name": "UK"
}
]
},
{
"name": "And Again",
"children": [{
"name": "FRANCE"
},
{
"name": "SUISSE"
},
{
"name": "USA"
},
{
"name": "UK"
}
]
},
{
"name": "And Again",
"children": [{
"name": "FRANCE"
},
{
"name": "SUISSE"
},
{
"name": "USA"
},
{
"name": "UK"
}
]
},
{
"name": "Production",
"children": [{
"name": "FRANCE"
},
{
"name": "SUISSE"
},
{
"name": "USA"
},
{
"name": "UK"
}
]
},
{
"name": "Audio",
"children": [{
"name": "AUT-11"
},
{
"name": "AUT-12"
}
]
},
{
"name": "Animation",
"children": [{
"name": "AUT-11"
},
{
"name": "AUT-12"
}
]
},
{
"name": "Tags",
"children": [{
"name": "AUT-11"
},
{
"name": "AUT-12"
}
]
}
]
};
var diameter = 800;
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = diameter,
height = diameter;
var i = 0,
duration = 350,
root;
var tree = d3.layout.tree()
.size([360, diameter / 2 - 80])
.separation(function(a, b) {
return (a.parent == b.parent ? 1 : 1) / a.depth;
});
var diagonal_extras = {
path: {
// diagonal line
direct: function(p) {
return [p.source, p.target];
}
// this is also the default path in radial trees
,
l_shape: function(p) {
return [p.source, {
x: p.target.x,
y: p.source.y
}, p.target];
}
,
l_shape_2: function(p) {
return [p.source, {
x: p.source.x,
y: p.target.y
}, p.target];
}
,
dogleg: function(p) {
return [p.source,
{
x: p.source.x,
y: (p.source.y + p.target.y) / 2
},
{
x: (p.source.x + p.target.x) / 2,
y: (p.source.y + p.target.y) / 2
},
{
x: p.target.x,
y: (p.source.y + p.target.y) / 2
},
p.target
];
}
,
dogleg_2: function(p) {
return [p.source,
{
x: (p.source.x + p.target.x) / 2,
y: p.source.y
},
{
x: (p.source.x + p.target.x) / 2,
y: (p.source.y + p.target.y) / 2
},
{
x: (p.source.x + p.target.x) / 2,
y: p.target.y
},
p.target
];
}
}
,
polar_obj_to_cart: function(pt) {
var angle = pt.x / 180 * Math.PI;
return [pt.y * Math.cos(angle), pt.y * Math.sin(angle)];
}
,
polar_coords_to_cart: function(xy) {
var angle = xy[0] / 180 * Math.PI;
return [xy[1] * Math.cos(angle), xy[1] * Math.sin(angle)];
}
}
diagonal_extras.right_angle = function() {
var projection = d3.svg.diagonal().projection(),
path_type = 'dogleg';
function diagonal(d) {
return diagonal.path_maker(diagonal_extras.path[diagonal.path_type()](d));
}
diagonal.path_maker = function(pathData) {
return "M" + pathData.map(projection).join(' ');
};
diagonal.valid_path_types = function() {
return Object.keys(diagonal_extras.path);
};
diagonal.path_type = function(x) {
if (!arguments.length) {
return path_type;
}
if (diagonal_extras.path[x]) {
path_type = x;
return diagonal;
}
throw new Error(x + ' is not a valid path type');
};
diagonal.projection = function(x) {
if (!arguments.length) {
return projection;
}
projection = x;
return diagonal;
};
diagonal.path = function(x) {
if (!arguments.length) {
return path;
}
path = x;
return diagonal;
};
diagonal.draw = function(d) {
return diagonal(d);
};
return diagonal;
}
diagonal_extras.radial = function() {
var diagonal = diagonal_extras.right_angle(),
projection = function(pt) {
return [pt.x, pt.y];
};
diagonal.path_type('direct');
diagonal.projection = function(x) {
if (!arguments.length) {
return projection;
}
projection = x;
return diagonal;
};
diagonal.path_maker = function(pathData) {
var projected = pathData.map(function(x) {
return projection(x);
}),
pl = projected.length,
points, prev_angle;
// direct link:
if (2 === pl) {
return 'M' + projected.map(function(x) {
return diagonal_extras.polar_coords_to_cart(x);
}).join(' ');
}
points = projected.map(function(obj) {
return {
angle: obj[0] / 180 * Math.PI,
radius: obj[1]
};
});
return "M" + points.map(function(pt) {
var str = '';
if (prev_angle) {
if (prev_angle === pt.angle) {
// draw a straight line
str = 'L';
} else {
// draw an arc to the new radius and angle
str = 'A' + pt.radius + ',' + pt.radius
// x axis rotation
+
" 0 "
// large arc flag
+
" 0,"
// sweep
+
(pt.angle > prev_angle ? 1 : 0) + " ";
}
}
prev_angle = pt.angle;
return str + pt.radius * Math.cos(pt.angle) + "," + pt.radius * Math.sin(pt.angle);
}).join(' ');
};
return diagonal;
}
var diagonal = diagonal_extras.radial()
.path_type('dogleg')
.projection(function(d) {
return [d.x - 90, d.y];
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
var rect = {
l: 95,
w: 20
}
root = pubs;
root.x0 = height / 2;
root.y0 = 0;
root.children.forEach(collapse); // start with all children collapsed
update(root);
d3.select(self.frameElement).style("height", "800px");
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root),
links = tree.links(nodes),
offset = nodes[0].x;
// Normalize for fixed-depth.
nodes.forEach(function(d) {
d.y = d.depth * 150;
});
// Normalise angles so that the root is horizontal
if (nodes[0].x > 180) {
nodes[0].x = nodes[0].x - 90
} else {
nodes[0].x = nodes[0].x + 90
}
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
});
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
//.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
.on("click", click)
.on('mouseover', mouseover)
.on('mouseout', mouseout)
nodeEnter.append("rect")
.attr("width", rect.l)
.attr("height", rect.w)
.attr("x", -rect.l / 2)
.attr("y", -rect.w / 2)
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "red";
});
nodeEnter.append("text")
.attr("x", 0)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
//.attr("transform", function(d) { return d.x < 180 ? "translate(0)" : "rotate(180)translate(-" + (d.name.length * 8.5) + ")"; })
.text(function(d) {
return d.name;
})
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")";
})
// nodeUpdate.select("circle")
// .attr("r", 4.5)
// .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeUpdate.select("text")
.style("fill-opacity", 1)
.attr("transform", function(d) {
return d.x < 180 ? "translate(0)" : "rotate(180)";
});
// TODO: appropriate transform
var nodeExit = node.exit().transition()
.duration(duration)
//.attr("transform", function(d) { return "diagonal(" + source.y + "," + source.x + ")"; })
.remove();
// nodeExit.select("circle")
// .attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) {
return d.target.id;
});
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", function(d) {
return diagonal({
source: {
x: d.source.x,
y: d.source.y + rect.l / 2
},
target: {
x: d.target.x,
y: d.target.y - rect.l / 2
}
})
});
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {
x: source.x,
y: source.y
};
return diagonal({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
function mouseover(d) {
d3.select(this).select('rect').style('fill', function(d){
if (d.depth === 0) {
return 'deepskyblue'
} else if (d.depth === 1) {
return 'deeppink'
} else if (d.depth === 2) {
return 'goldenrod'
}
return 'papayawhip'
})
}
function mouseout(d) {
d3.select(this).select('rect').style('fill', d => d._children ? "lightsteelblue" : "red")
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
// Collapse nodes
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
.node {
cursor: pointer;
}
.node text {
font: 10px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
<script type="text/javascript" src="//d3js.org/d3.v3.min.js"></script>