Javascript 使用DOM元素作为coords引用的ForceX

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

由于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值似乎是一门科学

  • .getBBox()返回错误的坐标
  • d3.转换已被API删除
  • .attr(“x”)返回null
目标是从外节点A获取x和y位置,并将这些值用于.force(“x”)和.force(“y”)。这些值当然可以在自己的函数帮助下在tick函数中更新,但现在我甚至很难获得这些坐标

 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;
}