D3 x和y坐标应用于最后出现的元素而不是组 [英] D3 x and y coordinates applied to last appened element instead of the group

查看:78
本文介绍了D3 x和y坐标应用于最后出现的元素而不是组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个力导向图,其中每个节点都是一个组,并在其中包含一个ForeignObject和一个img。 x和y coordiantes应用于img标签,但我希望将它们放在foreignObject或g上。我不确定如何实现。

I have a force directed graph where each node is a group and contains a foreignObject and an img inside it. x and y coordiantes are applied to the img tag but I would like to have them on the foreignObject or g. I am not sure how this can be achieved.

我尝试将x和y坐标设置为foreignObject,但是它们始终以NaN的形式返回。

I tried setting x and y coordinates to the foreignObject but they are always returned as NaN.

const plot = (data) => {
  data.nodes = data.nodes.map((d, index) => {
    d['id'] = index;
    return d;
  });
  const margin = {
    top: 20,
    right: 20,
    bottom: 10,
    left: 100
  };
  const width = Math.max((((window.innerWidth / 100) * 80) - margin.right - margin.left), 700);
  const height = ((window.innerHeight / 100) * 80) - margin.bottom - margin.top;
  const svg = d3.select('svg')
    .attr('width', width + margin.left + margin.right + 100)
    .attr('height', height + margin.top + margin.bottom + 100)
    .append('g')
    .attr('transform',
      `translate(${margin.left}, ${margin.top})`);

  const simulation = d3.forceSimulation()
    .force('link', d3.forceLink().id(function (d) { return d.id; }).distance(100).strength(1))
    .force('charge', d3.forceManyBody())
    .force('center', d3.forceCenter(width / 2, height / 2));

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

  const dragged = d => {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
  }

  const dragended = d => {
    if (!d3.event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
  }

  const ticked = () => {
    link
      .attr("x1", d => d.source.x)
      .attr("y1", d => d.source.y)
      .attr("x2", d => d.target.x)
      .attr("y2", d => d.target.y);

    node
      .attr("x", function (d) { return d.x = Math.max(5, Math.min(width - 5, d.x)); })
      .attr("y", function (d) { return d.y = Math.max(5, Math.min(height - 5, d.y)); });
  }

  const link = svg.append('g')
    .attr('class', 'links')
    .selectAll('line')
    .data(data.links)
    .enter().append('line')
    .attr('stroke-width', function (d) { return Math.sqrt(d.value); });

  const node = svg.append('g')
    .attr('class', 'nodes')
    .selectAll('.node-group')
    .data(data.nodes)
    .enter()
    .append('g')
    .append('foreignObject')
    .attr('class', 'node-group')
    .attr('width', '10')
    .attr('height', '10')
    .insert('xhtml:img')
    .attr('src', 'flags/blank.png')
    .attr('class', d => `flag flag-${d.code}`)
    .call(d3.drag()
      .on('start', dragstarted)
      .on('drag', dragged)
      .on('end', dragended));

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

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

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

}


推荐答案

如果看看您的节点选择...

If you look at your node selection...

const node = svg.append('g')
    .attr('class', 'nodes')
    .selectAll('.node-group')
    .data(data.nodes)
    .enter()
    .append('g')
    .append('foreignObject')
    .attr('class', 'node-group')
    .attr('width', '10')
    .attr('height', '10')
    .insert('xhtml:img')
    .attr('src', 'flags/blank.png')
    .attr('class', d => `flag flag-${d.code}`)
    .call(d3.drag()
        .on('start', dragstarted)
        .on('drag', dragged)
        .on('end', dragended));

...您会看到它是带有图像的选择 s。由于您要将 x y 属性应用于 foreignObject ,只需将其破坏即可:

... you'll see that it is a selection with the images. Since you want to apply the x and y properties to the foreignObject, just break it:

const node = svg.append('g')
    .attr('class', 'nodes')
    .selectAll('.node-group')
    .data(data.nodes)
    .enter()
    .append('g')
    .append('foreignObject')
    .attr('class', 'node-group')
    .attr('width', '10')
    .attr('height', '10');

node.insert('xhtml:img')
    .attr('src', 'flags/blank.png')
    .attr('class', d => `flag flag-${d.code}`)
    .call(d3.drag()
        .on('start', dragstarted)
        .on('drag', dragged)
        .on('end', dragended));

这样, node foreignObjects

这篇关于D3 x和y坐标应用于最后出现的元素而不是组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆