gpt4 book ai didi

javascript - 如何放大 d3 中的力导向图?

转载 作者:行者123 更新时间:2023-11-30 21:00:37 25 4
gpt4 key购买 nike

当我将鼠标悬停在图形 svg 的任何部分并向上或向下滚动时,我想放大我的力导向图形。我不太确定该怎么做。我能够选择 svg 并增加/减小 svg 的大小,这就像一个伪缩放,但它会改变 svg 的大小和位置,这不是我想要的。当我在 svg 上滚动时,如何选择节点和链接并增加它们的大小?谢谢

var svg = d3.select("svg")
,
width = +svg.attr("width"),
height = +svg.attr("height");

var color = d3.scaleOrdinal(d3.schemeCategory20);

var forceParameter = 30
maxDistanceParameter = 100;

var simulation = d3.forceSimulation()
.force("link", d3.forceLink().distance(forceParameter).strength(.5))
.force("charge", d3.forceManyBody().distanceMax(maxDistanceParameter))
.force("center", d3.forceCenter(width / 2, height / 2));

var linkMap = d3.map();

d3.json("courses.json", function(error, graph) {
if (error) throw error;

var nodes = graph.nodes,
nodeById = d3.map(nodes, function(d) { return d.id; }),
links = graph.links,
bilinks = [];

links.forEach(function(link) {
var s = link.source = nodeById.get(link.source),
t = link.target = nodeById.get(link.target),
i = {}; // intermediate node
nodes.push(i);
links.push({source: s, target: i}, {source: i, target: t});
bilinks.push([s, i, t]);
});

//Populate the map that keeps track of how many links a class node has
links.forEach(function(d){
if(linkMap.has(d.source.id))
linkMap.set(d.source.id, linkMap.get(d.source.id) + .5);
else
linkMap.set(d.source.id, .5);
});

var link = svg.selectAll(".link")
.data(bilinks)
.enter().append("path")
.attr("class", "link");

var node = svg.selectAll(".node")
.data(nodes.filter(function(d) { return d.id; }))
.enter().append("circle")
.attr("class", "node")
//Size the node differently if the node represents a department
.attr("r", function(d){
return (d.group === "Department") ? 15 : (5 * linkMap.get(d.id));
})
//Color the node differently if the node represents a department
.attr("fill", function(d) {
return (d.group === "Department") ? "#3B4656" : color(d.group);
})
//Color the node outline differently if the node represents a department
.style("stroke", function(d){
return (d.group === "Department") ? "black" : "white";
})
//When a node is clicked, all nodes that are more than 1 link away are faded out
.on("click", function(d){
d3.event.stopPropagation();
onNodeClick(this, d, links);
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));


//Unfade all nodes when whitespace is clicked
svg.on("click", function(){
d3.selectAll(".node")
.attr("opacity", "1");
});

//Force parameter buttons
d3.select("#forcesPlus")
.on("click", function(){
updateParameters(1);
});
d3.select("#forcesMinus")
.on("click", function(){
updateParameters(-1);
});

node.append("title")
.text(function(d) { return d.id; });

simulation
.nodes(nodes)
.on("tick", ticked);

simulation.force("link")
.links(links);

function ticked() {
link.attr("d", positionLink);
node.attr("transform", positionNode);
}

/** Updates the force parameters of the graph
*
* @param sign - Determines if we are increasing or decreasing the parameters
*/
function updateParameters(sign){
//Increase the passive jiggle of the nodes so that they visually update (expand/contract)
//when the parameter gets changed
simulation.alphaTarget(.1);

forceParameter += sign * 20;
maxDistanceParameter += sign * 20; //Need to update the max distance so that the
//links can actually get longer

simulation.nodes(nodes);
simulation.force("link", d3.forceLink().distance(forceParameter))
.force("charge", d3.forceManyBody().distanceMax(maxDistanceParameter));

simulation
.nodes(nodes)
.on("tick", ticked);

simulation.force("link")
.links(links);

//Hack so that the buttons don't break when the nodes settle down to a stand-still.
//Not sure why the buttons don't update once they are still, but this solves it.
//Need the nodes to move in order to see the change in force parameter.
setTimeout(function(){
simulation.alphaTarget(.01);
}, 2000);
}

});

//Fades out any nodes that are not connected to the clicked node
function onNodeClick(click, selectedNode, linkList){
var linkedNodes = d3.set();

linkList.forEach(function(v){
//If the node clicked is the link's source, add the link's target
if (selectedNode.id === v.source.id){
linkedNodes.add(v.target.id);
}
//If the node clicked is the link's target, add the link's source
else if (selectedNode.id === v.target.id){
linkedNodes.add(v.source.id);
}
});

d3.selectAll(".node")
.attr("opacity", function(d){
if (linkedNodes.has(d.id))
return "1";
else
return "0.1";
});

d3.select(click)
.attr("opacity", "1");
}

function positionLink(d) {
return "M" + d[0].x + "," + d[0].y
+ "S" + d[1].x + "," + d[1].y
+ " " + d[2].x + "," + d[2].y;
}

function positionNode(d) {
return "translate(" + d.x + "," + d.y + ")";
}

function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x, d.fy = d.y;
}

function dragged(d) {
d.fx = d3.event.x, d.fy = d3.event.y;
}

function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(.01);
d.fx = null, d.fy = null;
}

function linkDistance(d){
console.log(d);
}

最佳答案

可以在此处找到有关如何添加缩放的示例:https://coderwall.com/p/psogia/simplest-way-to-add-zoom-pan-on-d3-js

从技术上讲,您要做的是添加一个 <g> svg 根中的元素,然后告诉 d3 通过平移和缩放该元素来自动处理缩放/平移。因此,所有内容(节点和链接)也必须添加到该元素内(此处:zoomContainer):

var zoomContainer = svg.call(d3.zoom().on("zoom", function () {
zoomContainer.attr("transform", d3.event.transform)
}))
.append("g");

...

var link = zoomContainer.selectAll(".link")
.data(bilinks)
.enter().append("path")
...

var node = zoomContainer.selectAll(".node")
.data(nodes.filter(function(d) { return d.id; }))
.enter().append("circle")
...

https://jsfiddle.net/fseeyphe/

关于javascript - 如何放大 d3 中的力导向图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47172726/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com