Javascript 使用DOM元素作为coords引用的ForceX
由于D3v4可以定义Javascript 使用DOM元素作为coords引用的ForceX,javascript,d3.js,Javascript,D3.js,由于D3v4可以定义.forceCenter或.forceX和.forceY,而不是D3v3中的.size var force = d3.forceSimulation() .force("center", d3.forceCenter(width/2, heigth/2)) 或 所以可以设置坐标,然后还可以使用另一个DOM元素的x和y值作为引用。一个合适的用例是直观地组合d3力图问题是如何使用DOM元素作为引用,因为获取那些DOM元素.x和元素.y
.forceCenter
或.forceX
和.forceY
,而不是D3v3中的.size
var force = d3.forceSimulation()
.force("center", d3.forceCenter(width/2, heigth/2))
或
所以可以设置坐标,然后还可以使用另一个DOM元素的x和y值作为引用。一个合适的用例是直观地组合d3力图问题是如何使用DOM元素作为引用,因为获取那些DOM元素.x和元素.y值似乎是一门科学
- .getBBox()返回错误的坐标
- d3.转换已被API删除
- .attr(“x”)返回null
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))
var innerLayout=d3.forceSimulation()
.force(“link”,d3.forceLink().id(函数(d){
返回d.id;
}).距离(50))
.力(“电荷”,d3.力人体().力(-50))
.force(“x”,d3.forceX(870))//###您可以尝试这种方法,或者您可以在已由外部力转换的组中创建内部力:
var innerLinkContainer = outerNodes.filter((_, i) => i)
.append("g").attr("class", "innerLinkContainer");
var innerNodeContainer = outerNodes.filter((_, i) => i)
.append("g").attr("class", "innerNodeContainer");
以下是仅包含该更改的代码:
D3v6组件
身体{
背景色:#e6e7ee;
}
圈{
填充:白烟;
笔画:黑色;
笔画宽度:1px;
}
var svg=d3.选择(“正文”).追加(“svg”)
.attr(“宽度”,窗口.innerWidth)
.attr(“高度”,窗口内部高度)
.attr(“类”、“svg”)
.call(d3.zoom().on(“zoom”),函数(事件){
attr(“transform”,event.transform)
}))
.附加(“g”)
var outerLinkContainer=svg.append(“g”).attr(“class”,“outerLinkContainer”)
var outerNodeContainer=svg.append(“g”).attr(“class”,“outerNodeContainer”)
////////////////////////
//外力布局
var outerData={
“节点”:[{
“id”:“A”
},
{
“id”:“B”
},
],
“链接”:[{
“来源”:“B”,
“目标”:“A”
}, ]
}
var outerLayout=d3.forceSimulation()
.force(“link”,d3.forceLink().id(函数(d){
返回d.id;
}).距离(200))
.力(“电荷”,d3.力人体().力(-650))
.力(“中心”,d3.力中心(窗内宽度/2,窗内高度/2))
.力(“碰撞”,d3.力碰撞().半径(50))
var outerLinks=outerLinkContainer.selectAll(“.link”)
.data(outerData.links)
.加入(“行”)
.attr(“类”、“链接”)
.style(“笔划”、“黑色”)
.style(“不透明度”,0.2)
var outerNodes=outerNodeContainer.selectAll(“g.outer”)
.data(outerData.nodes,函数(d){
返回d.id;
})
.输入()
.附加(“g”)
.attr(“类”、“外部”)
.attr(“id”,函数(d){
返回d.id;
})
.call(d3.drag()
.on(“开始”,拖动开始)
.打开(“拖动”,拖动)
.开启(“结束”,绘图)
)
外节点
.附加(“圆圈”)
.attr(“r”,40)
外部节点。选择全部(“文本”)
.数据(d=>[d])
.join(“文本”)
.attr(“主要基线”、“中心”)
.attr(“文本锚定”、“中间”)
.attr(“id”,函数(d){
返回“文本”+d.id
})
.文本(功能(d){
返回d.id
})
外部布局
.nodes(outerData.nodes)
.on(“勾号”,外层标记)
外部布局
.force(“链接”)
.links(outerData.links)
////////////////////////
//内力布局
var innerLinkContainer=outerNodes.filter((_,i)=>i)
.append(“g”).attr(“类”、“innerLinkContainer”);
var innerNodeContainer=outerNodes.filter(((u,i)=>i)
.append(“g”).attr(“类”、“内部节点容器”);
变量innerAdata={
“节点”:[{
“id”:“B1”
},
{
“id”:“B2”
},
{
“id”:“B3”
},
],
“链接”:[{
“来源”:“B1”,
“目标”:“B2”
},
{
“来源”:“B2”,
“目标”:“B3”
},
{
“来源”:“B3”,
“目标”:“B1”
}
]
}
var innerLayout=d3.forceSimulation()
.force(“link”,d3.forceLink().id(函数(d){
返回d.id;
}).距离(50))
.力(“电荷”,d3.力人体().力(-50))
.力(“碰撞”,d3.力碰撞().半径(6))
var innerLinks=innerLinkContainer.selectAll(“.link”)
.data(innerAdata.links)
.加入(“行”)
.attr(“类”、“链接”)
.style(“笔划”、“黑色”)
.样式(“不透明度”,0.5)
var innerNodes=innerNodeContainer.selectAll(“g.inner”)
.data(innerAdata.nodes,函数(d){
返回d.id;
})
.输入()
.附加(“g”)
.attr(“类”、“内部”)
.attr(“id”,函数(d){
返回d.id;
})
.call(d3.drag()
.on(“开始”,拖动开始)
.打开(“拖动”,拖动)
.开启(“结束”,绘图)
)
内部节点
.附加(“圆圈”)
.style(“填充”、“橙色”)
.style(“笔划”、“蓝色”)
.attr(“r”,6);
内部布局
.nodes(innerAdata.nodes)
.on(“勾号”,innerAtick)
内部布局
.force(“链接”)
.links(innerAdata.links)
函数outerTick(){
外链
.attr(“x1”,函数(d){
返回d.source.x;
})
.attr(“y1”,函数(d){
返回d.source.y;
})
.attr(“x2”,函数(d){
返回d.target.x;
})
.attr(“y2”,功能(d){
返回d.target.y;
});
属性(“转换”,函数(d){
返回“translate”(“+d.x+”,“+d.y+”);
});
}
函数innerAtick(){
内部链接
.attr(“x1”,函数(d){
var innerLinkContainer = outerNodes.filter((_, i) => i)
.append("g").attr("class", "innerLinkContainer");
var innerNodeContainer = outerNodes.filter((_, i) => i)
.append("g").attr("class", "innerNodeContainer");
{
"id": "A",
"index": 0,
"x": 409.28298494419124,
"y": 321.93152757995455,
"vy": -0.0005382622043197348,
"vx": 0.0006924019130575043
}
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));
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")
// ...
});
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);
});
}
const parent = graph.outer.nodes.find(n => n.id === set.parent);
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;
}