- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
自 D3v4 起,可以定义 .forceCenter
或 .forceX
和 .forceY
,而不是 .size
在 D3v3 中。
var force = d3.forceSimulation()
.force("center", d3.forceCenter(width/2, heigth/2))
或
var force = d3.forceSimulation()
.force("x", d3.forceX(500))
.force("y", d3.forceY(500))
所以可以设置坐标,那么也一定可以使用另一个 DOM 元素的 x 和 y 值作为引用。一个正确的用例是直观地组合 d3 力图。 问题是如何使用 DOM 元素作为引用,因为获取这些 DOM element.x 和 element.y 值似乎非常科学。
目标是从outerNode A获取x和y位置,并将这些值用于.force("x")和.force("y”)。这些值肯定可以在自己的函数的帮助下在刻度函数中更新,但现在我正在努力获取这些坐标。
var innerLayout = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) {
return d.id;
}).distance(50))
.force("charge", d3.forceManyBody().strength(-50))
.force("x", d3.forceX(870)) //## <--- DOM element.x reference
.force("y", d3.forceY(370)) //## <--- DOM element.y reference
.force("collision", d3.forceCollide().radius(6))
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D3v6 Pack</title>
<script src="https://d3js.org/d3.v6.min.js"></script>
</head>
<style>
body {
background-color: #e6e7ee;
}
circle {
fill: whitesmoke;
stroke: black;
stroke-width: 1px;
}
</style>
<body>
<script>
var svg = d3.select("body").append("svg")
.attr("width", window.innerWidth)
.attr("height", window.innerHeight)
.attr("class", "svg")
.call(d3.zoom().on("zoom", function (event) {
svg.attr("transform", event.transform)
}))
.append("g")
var outerLinkContainer = svg.append("g").attr("class", "outerLinkContainer")
var outerNodeContainer = svg.append("g").attr("class", "outerNodeContainer")
var innerLinkContainer = svg.append("g").attr("class", "innerLinkContainer")
var innerNodeContainer = svg.append("g").attr("class", "innerNodeContainer")
////////////////////////
// outer force layout
var outerData = {
"nodes": [
{ "id": "A" },
{ "id": "B" },
],
"links": [
{ "source": "B", "target": "A" },
]
}
var outerLayout = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) {
return d.id;
}).distance(200))
.force("charge", d3.forceManyBody().strength(-650))
.force("center", d3.forceCenter(window.innerWidth / 2, window.innerHeight / 2))
.force("collision", d3.forceCollide().radius(50))
var outerLinks = outerLinkContainer.selectAll(".link")
.data(outerData.links)
.join("line")
.attr("class", "link")
.style("stroke", "black")
.style("opacity", 0.2)
var outerNodes = outerNodeContainer.selectAll("g.outer")
.data(outerData.nodes, function (d) { return d.id; })
.enter()
.append("g")
.attr("class", "outer")
.attr("id", function (d) { return d.id; })
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragged)
.on("end", dragEnded)
)
outerNodes
.append("circle")
.attr("r", 40)
outerNodes.selectAll("text")
.data(d => [d])
.join("text")
.attr("dominant-baseline", "central")
.attr("text-anchor", "middle")
.attr("id", function(d) { return "text" + d.id })
.text(function (d) {
return d.id
})
outerLayout
.nodes(outerData.nodes)
.on("tick", outerTick)
outerLayout
.force("link")
.links(outerData.links)
////////////////////////
// inner force layouts
var innerAdata = {
"nodes": [
{ "id": "B1" },
{ "id": "B2" },
{ "id": "B3" },
],
"links": [
{ "source": "B1", "target": "B2" },
{ "source": "B2", "target": "B3" },
{ "source": "B3", "target": "B1" }
]
}
var innerLayout = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) {
return d.id;
}).distance(50))
.force("charge", d3.forceManyBody().strength(-50))
.force("x", d3.forceX(250)) //## <--- DOM element.x reference
.force("y", d3.forceY(250)) //## <--- DOM element.y reference
.force("collision", d3.forceCollide().radius(6))
var innerLinks = innerLinkContainer.selectAll(".link")
.data(innerAdata.links)
.join("line")
.attr("class", "link")
.style("stroke", "black")
.style("opacity", 0.5)
var innerNodes = innerNodeContainer.selectAll("g.inner")
.data(innerAdata.nodes, function (d) { return d.id; })
.enter()
.append("g")
.attr("class", "inner")
.attr("id", function (d) { return d.id; })
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragged)
.on("end", dragEnded)
)
innerNodes
.append("circle")
.style("fill", "orange")
.style("stroke", "blue")
.attr("r", 6);
innerLayout
.nodes(innerAdata.nodes)
.on("tick", innerAtick)
innerLayout
.force("link")
.links(innerAdata.links)
function outerTick() {
outerLinks
.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return d.target.x;
})
.attr("y2", function (d) {
return d.target.y;
});
outerNodes.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
function innerAtick() {
innerLinks
.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return d.target.x;
})
.attr("y2", function (d) {
return d.target.y;
});
innerNodes.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
function dragStarted(event, d) {
if (!event.active)
outerLayout.alphaTarget(0.3).restart();
innerLayout.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(event, d) {
d.fx = event.x;
d.fy = event.y;
}
function dragEnded(event, d) {
if (!event.active)
outerLayout.alphaTarget(0);
innerLayout.alphaTarget(0);
d.fx = undefined;
d.fy = undefined;
}
</script>
</body>
</html>
最佳答案
下面代码片段中的方法特定于您的示例(并且与之前的 question 相关)并依赖于以下内容:
... 意味着您始终可以引用数据对象来获取 svg
内的外部节点坐标。所以对于g
包含outerNodes
outerData
包含x
和y
您正在寻找的outerLayout
之后已计算出这些位置,例如:
{
"id": "A",
"index": 0,
"x": 409.28298494419124,
"y": 321.93152757995455,
"vy": -0.0005382622043197348,
"vx": 0.0006924019130575043
}
请注意,这通常不起作用,因为对于嵌套组,x
和y
与其父组相关。外部节点坐标相对于 svg
所以它们就是您要查找的坐标。
...使用 d3.forceRadial
。工作示例有点罕见,但您可以深入了解 this one作者:@GerardoFurtado,我发现它对于提供这个答案很有用。还有这个block还有这个answer .
对于内在力量,我使用以下代码:
const innerForce = d3.forceSimulation(subgraphNodes)
.force("r", d3.forceRadial(outerRadius - outerMargin).strength(1.1))
.force("charge", d3.forceCollide().radius(innerRadius))
.force("link", d3.forceLink().id(d => d.id).distance(outerRadius - outerMargin));
地点:
subgraphNodes
就像你的innerData
(但我已经组合了示例中的数据对象)outerRadius
是外部节点的半径,outerMargin
是一些填充,用于将内部节点保留在外部节点内部。 1.1 看起来相当合理 strength
参数以将内部节点限制在其外部节点内(但请注意,您仍然可以将它们拖到外部)innerRadius
对于 d3.forceCollide
outerRadius - outerMargin
对于distance
上d3.forceLink
因此,虽然您可以将内部节点拖出外部节点,但它会弹回到外部节点内半径上的位置(由 outerRadius - outerMargin
定义)。这似乎对外部节点的布局影响很小,这是有帮助的。
(至少在我使用的示例数据中,这是它的工作原理):
graph.outer.nodes.forEach(outerNode => {
const parent = svg.select(`g.outer#${outerNode.id}`)
const subgraphNodes = graph[`inner${outerNode.id}`].nodes;
const subgraphLinks = graph[`inner${outerNode.id}`].links;
const innerLinks = parent.selectAll("g.inner")
.data(subgraphLinks)
.join("line")
.attr("class", "link")
.style("stroke", "black");
const innerNodes = parent.selectAll("g.inner")
// ...
});
通过将内部节点嵌套在其父节点(外部节点)中,您可以获得 Gerardo 在他的答案中提到的结果:
the inner force in a group already translated by the outer one
对于创建的每个内部布局,我都会在数组中跟踪它们,以便我们可以引用 nodes
, links
, parent
和force
稍后在 ticked
和各种drag
功能:
childSets.push({
force: innerForce,
parent: outerNode.id,
nodes: innerNodes,
links: innerLinks
});
ticked
功能:function ticked() {
outerLinks
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
outerNodes.attr("transform", d => `translate(${d.x},${d.y})`);
childSets.forEach(set => {
const parent = graph.outer.nodes.find(n => n.id === set.parent);
set.nodes.attr("transform", d => `translate(${parent.x + d.x},${parent.y + d.y})`);
set.links
.attr("x1", d => d.source.x + parent.x)
.attr("y1", d => d.source.y + parent.y)
.attr("x2", d => d.target.x + parent.x)
.attr("y2", d => d.target.y + parent.y);
});
}
治疗outerNodes
和outerLinks
与您的代码相同。
对于内部力布局,我迭代为每个 forceSimulation
创建的数组初始化并设置transform
在 translate
所在的节点上指的是内部节点坐标和父节点坐标 - 父节点坐标来自:
const parent = graph.outer.nodes.find(n => n.id === set.parent);
然后我们可以引用parent.x
和parent.y
我们需要的地方。
drag
处理程序,以便处理每个内部布局例如
function dragStarted(event, d) {
if (!event.active) {
outerForce.alphaTarget(0.3).restart();
childSets.forEach(set => set.force.alphaTarget(0.3).restart());
}
d.fx = d.x;
d.fy = d.y;
}
const width = 600;
const height = 400;
const outerRadius = 40;
const outerMargin = 16;
const innerRadius = 6;
const outerLinkDistance = 100;
let childSets = [];
const graph = {
outer: {
nodes: [
{id: "A"},
{id: "B"},
{id: "C"},
{id: "D"},
{id: "E"},
{id: "F"},
{id: "G"},
],
links: [
{source: "A", target: "B"},
{source: "B", target: "E"},
{source: "C", target: "F"},
{source: "C", target: "A"},
{source: "E", target: "A"},
{source: "D", target: "C"},
{source: "D", target: "F"},
{source: "A", target: "F"},
{source: "B", target: "G"},
{source: "G", target: "C"},
]
},
innerA: {
nodes: [
{id: "A1", parent: "A"},
{id: "A2", parent: "A"},
{id: "A3", parent: "A"},
],
links: [
{source: "A1", target: "A2"},
{source: "A2", target: "A3"},
{source: "A3", target: "A1"},
]
},
innerB: {
nodes: [
{id: "B1", parent: "B"},
{id: "B2", parent: "B"},
{id: "B3", parent: "B"},
{id: "B4", parent: "B"},
{id: "B5", parent: "B"},
],
links: [
{source: "B1", target: "B2"},
{source: "B2", target: "B3"},
{source: "B3", target: "B4"},
{source: "B4", target: "B5"},
{source: "B5", target: "B1"},
{source: "B1", target: "B3"},
{source: "B3", target: "B5"},
]
},
innerC: {
nodes: [
{id: "C1", parent: "C"},
{id: "C2", parent: "C"},
],
links: [
{source: "C1", target: "C2"}
]
},
innerD: {
nodes: [
{id: "D1", parent: "D"},
{id: "D2", parent: "D"},
],
links: []
},
innerE: {
nodes: [
{id: "E1", parent: "E"},
{id: "E2", parent: "E"},
{id: "E3", parent: "E"},
],
links: [
{source: "E1", target: "E2"},
{source: "E2", target: "E3"},
{source: "E3", target: "E1"},
]
},
innerF: {
nodes: [
{id: "F1", parent: "F"},
{id: "F2", parent: "F"},
{id: "F3", parent: "F"},
{id: "F4", parent: "F"},
],
links: [
{source: "F1", target: "F2"},
{source: "F1", target: "F3"},
{source: "F3", target: "F4"},
]
},
innerG: {
nodes: [
{id: "G1", parent: "G"}
],
links: []
}
}
const svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
const outerLinkG = svg.append("g")
.attr("class", "outerlinks");
const outerNodeG = svg.append("g")
.attr("class", "outernodes");
const outerForce = d3.forceSimulation()
.force("center", d3.forceCenter(width / 2, height / 2))
.force("charge", d3.forceManyBody().strength(-500))
.force("link", d3.forceLink().id(d => d.id).distance(outerLinkDistance));
const outerLinks = outerLinkG.selectAll(".link")
.data(graph.outer.links)
.join("line")
.attr("class", "link")
.style("stroke", "black")
.style("opacity", 0.2);
const outerNodes = outerNodeG.selectAll("g.outer")
.data(graph.outer.nodes, d => d.id)
.join("g")
.attr("class", "outer")
.attr("id", d => d.id)
.append("circle")
.style("fill", "pink")
.style("stroke", "blue")
.attr("r", outerRadius)
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragged)
.on("end", dragEnded)
);
outerForce
.nodes(graph.outer.nodes)
.on("tick", ticked);
outerForce
.force("link")
.links(graph.outer.links);
graph.outer.nodes.forEach(outerNode => {
const parent = svg.select(`g.outer#${outerNode.id}`)
const subgraphNodes = graph[`inner${outerNode.id}`].nodes;
const subgraphLinks = graph[`inner${outerNode.id}`].links;
const innerLinks = parent.selectAll("g.inner")
.data(subgraphLinks)
.join("line")
.attr("class", "link")
.style("stroke", "black");
const innerNodes = parent.selectAll("g.inner")
.data(subgraphNodes, d=> d.id)
.join("g")
.attr("class", "inner")
.attr("id", d => d.id)
.append("circle")
.attr("r", innerRadius)
.style("fill", "orange")
.style("stroke", "blue")
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragged)
.on("end", dragEnded)
);
// https://gerardofurtado.com/vr/vr.html
const innerForce = d3.forceSimulation(subgraphNodes)
.force("r", d3.forceRadial(outerRadius - outerMargin).strength(1.1))
.force("charge", d3.forceCollide().radius(innerRadius))
.force("link", d3.forceLink().id(d => d.id).distance(outerRadius - outerMargin));
innerForce
.on("tick", ticked);
innerForce
.force("link")
.links(subgraphLinks);
childSets.push({
force: innerForce,
parent: outerNode.id,
nodes: innerNodes,
links: innerLinks
});
});
function ticked() {
outerLinks
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
outerNodes.attr("transform", d => `translate(${d.x},${d.y})`);
childSets.forEach(set => {
const parent = graph.outer.nodes.find(n => n.id === set.parent);
set.nodes.attr("transform", d => `translate(${parent.x + d.x},${parent.y + d.y})`);
set.links
.attr("x1", d => d.source.x + parent.x)
.attr("y1", d => d.source.y + parent.y)
.attr("x2", d => d.target.x + parent.x)
.attr("y2", d => d.target.y + parent.y);
});
}
function dragStarted(event, d) {
if (!event.active) {
outerForce.alphaTarget(0.3).restart();
childSets.forEach(set => set.force.alphaTarget(0.3).restart());
}
d.fx = d.x;
d.fy = d.y;
}
function dragged(event, d) {
d.fx = event.x;
d.fy = event.y;
}
function dragEnded(event, d) {
if (!event.active) {
outerForce.alphaTarget(0);
childSets.forEach(set => set.force.alphaTarget(0));
}
d.fx = undefined;
d.fy = undefined;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.5.0/d3.min.js"></script>
这种方法似乎不可行的是在具有不同外部节点的内部节点之间创建链接。关于外部节点内内部节点的“ block 状”性质,还有一个需要改进的地方。
关于javascript - ForceX 使用 DOM 元素作为坐标引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67125421/
我有一个点(粉色圆圈),它有一个已知的 X 坐标和一个已知的 Y 坐标,但 Y 坐标> 坐标不正确。它当前位于目标贝塞尔曲线(部分位于白色正方形中的曲线)所在的点(如果它是两点之间的一条线)。我需要为
有一个基于QML 和QWT 的代码,一种具有更多可能性的图形生成器。技术要求之一是根据某个 X 坐标获得绘图曲线的 Y 坐标。 有一种不准确的方法 - 获取 QwtPlotCurve 的 QPoint
我目前正在将对象的 3D 坐标转换为 2D 坐标,然后在其上绘制 2D 文本(目前是对象名称): public static int[] getScreenCoords(double x, doubl
首先,我创建一个元组列表(要绘制的点)。每个元组由 3 个数字组成(x - 坐标,y - 坐标,c - 点的颜色) import random import matplotlib.pyplot as
我正在制作一个 2 人 Java 游戏,但我需要确保坐标保留在板上。 addPiece(1, 1, "X"); addPiece(8, 8, "O"); showBoard(); Scanner my
我想检查我是否正确使用了 scipy 的 KD 树,因为它看起来比简单的暴力破解要慢。 关于这个我有三个问题: Q1. 如果我创建以下测试数据: nplen = 1000000 # WGS84 lat
我有一个 GeoJSON 文件,我正在尝试处理它以便在谷歌地图上绘制一些功能。然而,问题在于坐标不是传统的纬度/经度表示法,而是一些大的六位/七位数字。示例: { "type":
我在使用坐标时遇到格式化问题。 public class Coordinate { public int x; public int y; public Coordinate( int x
我正在尝试获取当前位置的经度和纬度坐标。这是到目前为止我的代码: public class MainActivity extends AppCompatActivity { @Override pro
基本上,我需要获取从 OpenGL 中的贝塞尔曲线实现绘制的所有坐标。具体来说,我需要坐标来沿着弯曲的轨迹路径移动场景中的球体对象(棒球)。这是我用来绘制曲线的: GL2 gl = drawable.
现在我用 JAVA 遇到了一些问题,但不记得如何获取坐标系之间的长度。 例如。A 点 (3,7)B点(7,59) 我想知道如何计算a点和b点之间的距离。非常感谢您的回答。 :-) 最佳答案 A = (
我正在用 Pi2Go 机器人制作一个小项目,它将从超声波传感器获取数据,然后如果它看到一个物体,则放置一个 X,并放置 O 它当前所在的位置,我有两个问题:如何在 tkinter 上设置坐标位置?例如
如何在 pygame 中存储对象的先前坐标?我的问题可能有点难以解释,但我会尽力,如果您自己尝试我的代码以理解我的意思可能会有所帮助。 这就是我的游戏的内容。我希望这能让我的问题更容易理解。 我正在创
如何存储用户的当前位置并在 map 上显示该位置? 我能够在 map 上显示预定义的坐标,只是不知道如何从设备接收信息。 此外,我知道我必须将一些项目添加到 Plist 中。我怎样才能做到这一点? 最
我在 android 应用程序开发方面不是很熟练,我正在开发一个测试应用程序。我检测到了脸和眼睛,现在我要根据眼睛的坐标在脸上画一些像粉刺或疤痕的东西(例如脸颊上的眼睛下方)。稍后,我会把眼镜或帽子放
所以我正在使用 API 来检测图像中的人脸,到目前为止它对我来说效果很好。然而,我一直无法弄清楚如何将图像裁剪到脸上。我知道如何裁剪位图,但它需要获取位图中脸部的左上角位置以及宽度和高度。当我使用 查
我有 2 个表。第一个表包含以下列:Start_latitude、start_longitude、end_latitude、end_longitude、sum。 sum 列为空,需要根据第二张表进行填
有没有办法给 Google Maps API 或类似的 API 一个城镇名称,并让它返回城镇内的随机地址?我希望能够将数据作为 JSON 获取,以便我可以在 XCode 中使用 SwiftyJSON
我将坐标保存在 numpy 数组 x 和 y 中。现在我想要的只是获得一个多边形(分别是点数组),它用给定的宽度参数定义周围区域。 我遇到的问题是我需要一个没有(!)交叉点的多边形。但是,当曲线很窄时
我正在开发井字游戏 (3x3),所以我有 9 个按钮,我想做的是获取用户按下的按钮的坐标,并在按钮的位置插入图像。 例子: @IBOutlet weak var button1Outlet: UIBu
我是一名优秀的程序员,十分优秀!