D3将文本附加到内圈

gblwokeq  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(163)

原问题:

我想视觉突出显示每个节点的属性。为此,我添加了另一个小圆圈。此外,我想在每个蓝色圆圈中添加一个短字符串。我尝试了不同的方法,最常见的似乎是在初始化过程中直接添加.append(“text”)。不幸的是,我还没有幸运。
我怎么才能做到这一点?

修改,如kikon所述:

我按照建议做了,它有效。但是如何将文本分配给每个节点呢?现在它只出现在第一个子圆上。


的数据

var width = window.innerWidth,
            height = window.innerHeight;

        var svg = d3.select("body").append("svg")
            .attr("width", width)
            .attr("height", height)
            .call(d3.zoom().on("zoom", function(event) {
                svg.attr("transform", event.transform)
            }))
            .append("g")

        ////////////////////////
        // outer force layout

        var data = {
            "nodes":[
                { "id": "A", "shoes": [{"brand": "Nike"}, {"brand": "Adidas"}, {"brand": "Adidas"}]}, 
                { "id": "B", "shoes": [{"brand": "Nike"}, {"brand": "Adidas"}, {"brand": "Adidas"}, {"brand": "Adidas"}]},
                { "id": "C", "shoes": []},
            ],
            "links": [
                { "source": "A", "target": "B"},
                { "source": "B", "target": "C"},
                { "source": "C", "target": "A"}
            ]
        };

        var simulation = d3.forceSimulation()
            .force("size", d3.forceCenter(width / 2, height / 2))
            .force("charge", d3.forceManyBody().strength(-1000))
            .force("link", d3.forceLink().id(function (d) { return d.id }).distance(250))
       
        linksContainer = svg.append("g").attr("class", "linkscontainer")
        nodesContainer = svg.append("g").attr("class", "nodesContainer")
       
        var links = linksContainer.selectAll("g")
            .data(data.links)
            .join("g")
            .attr("fill", "transparent")

        var linkLine = linksContainer.selectAll(".linkPath")
            .data(data.links)
            .join("path")
            .attr("stroke", "red")
            .attr("fill", "transparent")
            .attr("stroke-width", 3)
        
        nodes = nodesContainer.selectAll(".nodes")
            .data(data.nodes, function (d) { return d.id; })
            .join("g")
            .attr("class", "nodes")
            .attr("id", function (d) { return d.id; })
            .call(d3.drag()
                .on("start", dragStarted)
                .on("drag", dragged)
                .on("end", dragEnded)
            )

        nodes.selectAll("circle")
            .data(d => [d])
            .join("circle")
            .style("fill", "lightgrey")
            .style("stroke", "blue")
            .attr("r", 40)

        var eventCircle = nodes.selectAll("g")
            .data(data.nodes)
            .enter()
            .append("g")
            
        eventCircle.append("g")
            .selectAll("circle-small")
            .data(x => x.shoes)
            .enter()
            .append('circle')
            .attr('r', 15)
            .attr("fill", "blue")
            .attr('cx', function (d,i) {
                const factor = (i / 40) * (15 / 2) * 5;
                return 40 * Math.cos(factor - Math.PI * 0.5);
            })
            .attr('cy', function (d,i) { 
                const factor = (i / 40) * (15 / 2) * 5;
                return 40 * Math.sin(factor - Math.PI * 0.5);
            })
            .attr("class", "circle-small")

        eventCircle.append("text")
            .attr("x", function(d) {
                return -4
            })
            .attr("y", function(d) {
                return  -34
            })
            .attr("font-size", 15)
            .attr("fill", "white")
            .attr("pointer-events", "cursor")
            .text(function (d) {
                return "1"
            })

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

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

            
        function tick() {
            linkLine.attr("d", function(d) {
                var dx = (d.target.x - d.source.x),
                    dy = (d.target.y - d.source.y),
                    dr = Math.sqrt(dx * dx + dy * dy)

                return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
            })
                

            nodes
                .attr("transform", d => `translate(${d.x}, ${d.y})`);
        }

        function dragStarted(event, d) {
            if (!event.active) simulation.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) simulation.alphaTarget(0);
            d.fx = null;
            d.fy = null;
        }
body {
        background: whitesmoke,´;
        overflow: hidden;
        margin: 0px;
    }
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>D3v7</title>
    <!-- d3.js framework -->
    <script src="https://d3js.org/d3.v7.js"></script>
</head>


<body>
</body>
</html>
nkoocmlb

nkoocmlb1#

如果你检查你的SVG,你会看到你在彼此的顶部附加了几个圆圈。
只需为每个品牌添加一个<g>,并相应地进行翻译...

var eventCircle = nodes.selectAll(null)
  .data(d => d.shoes)
  .enter()
  .append("g")
  .attr("transform", function(d, i) {
    const factor = (i / 40) * (15 / 2) * 5;
    return `translate(${40 * Math.cos(factor - Math.PI * 0.5)},${40 * Math.sin(factor - Math.PI * 0.5)})`;
  });

字符串
...然后将您的圈子和文本添加到这些组中。
以下是修改后的Demo:

var width = window.innerWidth,
  height = window.innerHeight;

var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height)
  .call(d3.zoom().on("zoom", function(event) {
    svg.attr("transform", event.transform)
  }))
  .append("g")

////////////////////////
// outer force layout

var data = {
  "nodes": [{
      "id": "A",
      "shoes": [{
        "brand": "Nike"
      }, {
        "brand": "Adidas"
      }, {
        "brand": "Adidas"
      }]
    },
    {
      "id": "B",
      "shoes": [{
        "brand": "Nike"
      }, {
        "brand": "Adidas"
      }, {
        "brand": "Adidas"
      }, {
        "brand": "Adidas"
      }]
    },
    {
      "id": "C",
      "shoes": []
    },
  ],
  "links": [{
      "source": "A",
      "target": "B"
    },
    {
      "source": "B",
      "target": "C"
    },
    {
      "source": "C",
      "target": "A"
    }
  ]
};

var simulation = d3.forceSimulation()
  .force("size", d3.forceCenter(width / 2, height / 2))
  .force("charge", d3.forceManyBody().strength(-1000))
  .force("link", d3.forceLink().id(function(d) {
    return d.id
  }).distance(250))

linksContainer = svg.append("g").attr("class", "linkscontainer")
nodesContainer = svg.append("g").attr("class", "nodesContainer")

var links = linksContainer.selectAll("g")
  .data(data.links)
  .join("g")
  .attr("fill", "transparent")

var linkLine = linksContainer.selectAll(".linkPath")
  .data(data.links)
  .join("path")
  .attr("stroke", "red")
  .attr("fill", "transparent")
  .attr("stroke-width", 3)

nodes = nodesContainer.selectAll(".nodes")
  .data(data.nodes, function(d) {
    return d.id;
  })
  .join("g")
  .attr("class", "nodes")
  .attr("id", function(d) {
    return d.id;
  })
  .call(d3.drag()
    .on("start", dragStarted)
    .on("drag", dragged)
    .on("end", dragEnded)
  )

nodes.selectAll("circle")
  .data(d => [d])
  .join("circle")
  .style("fill", "lightgrey")
  .style("stroke", "blue")
  .attr("r", 40)

var eventCircle = nodes.selectAll(null)
  .data(d => d.shoes)
  .enter()
  .append("g")
  .attr("transform", function(d, i) {
    const factor = (i / 40) * (15 / 2) * 5;
    return `translate(${40 * Math.cos(factor - Math.PI * 0.5)},${40 * Math.sin(factor - Math.PI * 0.5)})`;
  });

eventCircle.append('circle')
  .attr('r', 15)
  .attr("fill", "blue")
  .attr("class", "circle-small")

eventCircle.append("text")
  .attr("font-size", 10)
  .attr("fill", "white")
  .style("text-anchor", "middle")
  .attr("pointer-events", "cursor")
  .text(function(d) {
    return d.brand;
  })

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

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


function tick() {
  linkLine.attr("d", function(d) {
    var dx = (d.target.x - d.source.x),
      dy = (d.target.y - d.source.y),
      dr = Math.sqrt(dx * dx + dy * dy)

    return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
  })

  nodes
    .attr("transform", d => `translate(${d.x}, ${d.y})`);
}

function dragStarted(event, d) {
  if (!event.active) simulation.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) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

x

body {
  background: whitesmoke, ´;
  overflow: hidden;
  margin: 0px;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>D3v7</title>
  <!-- d3.js framework -->
  <script src="https://d3js.org/d3.v7.js"></script>
</head>


<body>
</body>

</html>

的字符串

相关问题