gpt4 book ai didi

javascript - D3 Canvas 强制布局 - 脱节组排斥另一组

转载 作者:行者123 更新时间:2023-11-29 23:18:45 25 4
gpt4 key购买 nike

我有一组节点(A、B、C、D、E、F、G、H、I、J、K),但在 2 个不相交的组(A、B、C)和( D、E、F、G、H、I、J、K):

<!DOCTYPE html>
<html>

<body onload="connect1();">
<canvas width="300" height="100"></canvas>
<!--button id="ref" onclick="refresh()">refresh </button-->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height;
var links =[] , nodes = [] ;

var graph={nodes,links}, wsConn;

function connect1(){

addNodeCanvas("A", "1");
addNodeCanvas("B", "6");
addNodeCanvas("C", "4");
addNodeCanvas("D", "2");
addNodeCanvas("E", "3");
addNodeCanvas("F", "1");
addNodeCanvas("G", "1");
addNodeCanvas("H", "1");
addNodeCanvas("I", "1");
addNodeCanvas("J", "1");
addNodeCanvas("K", "1");

addLinkCanvas("A","B");
addLinkCanvas("A","C");


addLinkCanvas("E","D");
addLinkCanvas("F","D");
addLinkCanvas("G","D");
addLinkCanvas("H","D");
addLinkCanvas("I","D");
addLinkCanvas("J","D");
addLinkCanvas("K","D");

refresh();
}


var nodeColors = d3.scaleOrdinal().range(d3.schemeCategory20);

function addNodeCanvas(nodeName,g) {
var node = {
x: 400,
y: 400,
id: nodeName,
grp:g
};
var n = nodes.push(node);
}


function addLinkCanvas(idSrc, idTarget) {

if (idSrc != idTarget) {
var s = {},
t = {};
nodes.forEach(function(curNode) {
if (typeof curNode.id != "undefined") {
if (curNode.id == idSrc) {
s = curNode;
}
if (curNode.id == idTarget) {
t = curNode;
}
}
});

links.push({
source: s,
target: t
});
};

}




function refresh() {

var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));

simulation
.nodes(nodes)
.on("tick", ticked)
.force("link")
.links(links);
d3.select(canvas)
.call(d3.drag()
.container(canvas)
.subject(dragsubject)
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));


function ticked() {
var margin = 20;
nodes.forEach(function(d) {
d.x = Math.max(margin, Math.min(width - margin, d.x))
d.y = Math.max(margin, Math.min(height - margin, d.y))
});

function dblclick() {
nodes.forEach(function(d) {
d.fx = d.fy = null;
})
};
context.clearRect(0, 0, width, height);
context.beginPath();
links.forEach(drawLink);
context.strokeStyle = "#aaa";
context.stroke();
context.beginPath();
nodes.forEach(drawNode);

}

function dragsubject() {
return simulation.find(d3.event.x, d3.event.y);
}
var clickDate = new Date();
var difference_ms;

function dragstarted() {

}

function dragged() {

}


function dragended() {

}


function drawLink(d) {
context.moveTo(d.source.x, d.source.y);
context.lineTo(d.target.x, d.target.y);
}

var nodeColors = d3.scaleOrdinal().range(d3.schemeCategory20),
labelColors = d3.scaleOrdinal().range(['red', 'orange', 'blue', 'green', 'purple']);

function drawNode(d) {
context.beginPath();
context.moveTo(d.x + 10, d.y);
context.arc(d.x, d.y, 10, 0, 2 * Math.PI);
context.strokeStyle = "#fff";
context.stroke();
context.fillStyle = nodeColors(d.grp);
context.closePath();
context.fill();
context.beginPath();
context.font = (d.labelSize ? d.labelSize : 10) + 'px Arial';
context.fillStyle = labelColors(d.grp);
context.fillText(d.id ? d.id : d.grp, d.x, d.y);
context.closePath();
}
}
</script>
</body>

</html>

由于这 2 组在加载页面后脱节,它们开始相互排斥并继续插入直到到达 Canvas 的末端。

如何避免这种情况,使两个组彼此远离但仍保持在 Canvas 中心附近。

Please try it running a few times, and you will see nodes A,B & C getting pushed to the end and remain there in a straight line.

最佳答案

问题在于,一旦施加初始排斥力,就没有其他力起作用来抵消它。因此,运动一直持续到 Canvas 容器的边界,节点撞到墙上(相当于 normal force 并带来平衡)。

要使无限排斥运动停止,你需要一个viscosity force这将逐渐减慢节点组,直到它们达到零速度。

d3 的强制布局为此提供了一个参数:velocityDecay :

var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
.velocityDecay(0.8); // the velocity decay setting

您可以使用 velocityDecay 的值,它可以介于 0 和 1 之间,其中 0 相当于不应用设置(无粘性),1 相当于具有法向力并且没有运动开始。

例如粘度为 0.8:

<!DOCTYPE html>
<html>

<body onload="connect1();">
<canvas width="500" height="350"></canvas>
<!--button id="ref" onclick="refresh()">refresh </button-->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height;
var links =[] , nodes = [] ;

var graph={nodes,links}, wsConn;

function connect1(){

addNodeCanvas("A", "1");
addNodeCanvas("B", "6");
addNodeCanvas("C", "4");
addNodeCanvas("D", "2");
addNodeCanvas("E", "3");
addNodeCanvas("F", "1");
addNodeCanvas("G", "1");
addNodeCanvas("H", "1");
addNodeCanvas("I", "1");
addNodeCanvas("J", "1");
addNodeCanvas("K", "1");

addLinkCanvas("A","B");
addLinkCanvas("A","C");


addLinkCanvas("E","D");
addLinkCanvas("F","D");
addLinkCanvas("G","D");
addLinkCanvas("H","D");
addLinkCanvas("I","D");
addLinkCanvas("J","D");
addLinkCanvas("K","D");

refresh();
}


var nodeColors = d3.scaleOrdinal().range(d3.schemeCategory20);

function addNodeCanvas(nodeName,g) {
var node = {
x: width / 2,
y: height / 2,
id: nodeName,
grp:g
};
var n = nodes.push(node);
}


function addLinkCanvas(idSrc, idTarget) {

if (idSrc != idTarget) {
var s = {},
t = {};
nodes.forEach(function(curNode) {
if (typeof curNode.id != "undefined") {
if (curNode.id == idSrc) {
s = curNode;
}
if (curNode.id == idTarget) {
t = curNode;
}
}
});

links.push({
source: s,
target: t
});
};

}




function refresh() {

var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
.velocityDecay(0.8);

simulation
.nodes(nodes)
.on("tick", ticked)
.force("link")
.links(links);
d3.select(canvas)
.call(d3.drag()
.container(canvas)
.subject(dragsubject)
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));


function ticked() {
var margin = 20;
nodes.forEach(function(d) {
d.x = Math.max(margin, Math.min(width - margin, d.x))
d.y = Math.max(margin, Math.min(height - margin, d.y))
});

function dblclick() {
nodes.forEach(function(d) {
d.fx = d.fy = null;
})
};
context.clearRect(0, 0, width, height);
context.beginPath();
links.forEach(drawLink);
context.strokeStyle = "#aaa";
context.stroke();
context.beginPath();
nodes.forEach(drawNode);

}

function dragsubject() {
return simulation.find(d3.event.x, d3.event.y);
}
var clickDate = new Date();
var difference_ms;

function dragstarted() {

}

function dragged() {

}


function dragended() {

}


function drawLink(d) {
context.moveTo(d.source.x, d.source.y);
context.lineTo(d.target.x, d.target.y);
}

var nodeColors = d3.scaleOrdinal().range(d3.schemeCategory20),
labelColors = d3.scaleOrdinal().range(['red', 'orange', 'blue', 'green', 'purple']);

function drawNode(d) {
context.beginPath();
context.moveTo(d.x + 10, d.y);
context.arc(d.x, d.y, 10, 0, 2 * Math.PI);
context.strokeStyle = "#fff";
context.stroke();
context.fillStyle = nodeColors(d.grp);
context.closePath();
context.fill();
context.beginPath();
context.font = (d.labelSize ? d.labelSize : 10) + 'px Arial';
context.fillStyle = labelColors(d.grp);
context.fillText(d.id ? d.id : d.grp, d.x, d.y);
context.closePath();
}
}
</script>
</body>

</html>

关于javascript - D3 Canvas 强制布局 - 脱节组排斥另一组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51572203/

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