简体   繁体   中英

How can i localizate circles on a specific region in d3.js

I've created a graph in d3 that reads an array and displays the data when the mouse cursor passes over a circle.

My graphic has 3 entities:

  1. a main circle that is located at the center of the page.
  2. a color pie chart that goes inside the main circle.
  3. a small circle corresponding to each record of the array defined in the code.

在此处输入图片说明

I want to be able to locate the small circles on the edge of the main circle as shown in the image below.

在此处输入图片说明

Any idea how to do this? I would appreciate any advice or help.

I leave the complete code of the graphic I created. Thank you very much

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>D3 Test</title>
    <script src="//d3js.org/d3.v3.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    <style>
        .underline {
            text-decoration: underline;
        }
    </style>
</head>
<body style="background-color: rgb(233, 236, 239)">
<br><legend align="center">D3 Test</legend><hr>
  <div class="container">
      <div class="jumbotron">
    <script type="text/javascript">
    var w = 1200;
    var h = 550;
    var padding = 20;
    var radius = Math.min(w, h);


    var dataset = [
          [ 600, 150]
    ];

    var data = [
            [5, 20, "1.- Lorem Ipsum es simplemente el texto de relleno de las imprentas y archivos de texto."],
            [480, 90, "2.- Lorem Ipsum ha sido el texto de relleno estándar de las industrias desde el año 1500"],
            [750, 50, "3.- cuando un impresor (N. del T. persona que se dedica a la imprenta) desconocido usó una galería de textos"],
            [100, 33, "4.- Es un hecho establecido hace demasiado tiempo que un"],
            [330, 95, "5.- Parecerlo un español que se puede leer. Muchos paquetes de autoedición y editores de páginas web usan el Lorem Ipsum como su te"],
            [410, 12, "6- Ingresó como texto de relleno en documentos electrónicos, quedan"],
            [475, 44, "7.- Esencialmente igual al original. Fue popularizado en los 60s "],
            [25, 67, " 8.- Más recientemente con software de autoedición, como por ejemplo Al"],
            [85, 21, "9.- Normal de las letras, al contrario de usar textos como por ejemplo "],
            [220, 88, "10.- Muchas variaciones de los pasajes de Lorem Ipsum disponibles, pero la mayoría sufrió alteraciones en al"]
          ];
    var data_colors = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25, 15, 20, 18, 17, 16, 18, 23, 25 ];

    var data_2 = [
        [122, 72]
    ];

      var xScale_data = d3.scale.linear()
                .domain([0, d3.max(data, function(d) { return d[0]; })])
                .range([padding, w - padding * 2]);

      var yScale_data = d3.scale.linear()
                .domain([0, d3.max(data, function(d) { return d[1]; })])
                .range([h - padding, padding * 4]);

      var rScale = d3.scale.linear()
                .domain([0, d3.max(dataset, function(d) { return d[1]; })])
                .range([2, 5]);

      var rScale_data = d3.scale.linear()
                .domain([0, d3.max(data, function(d) { return d[1]; })])
                .range([2, 5]);

      //Crear un elemento SVG
      var svg = d3.select("div.jumbotron")
        .append("svg")
            .attr("width", w)
            .attr("height", h)

      svg.selectAll("circle")
        .data(dataset)
        .enter()
        .append("circle")
            .attr("cx", w / 2)
            .attr("cy", h / 2)

            .attr("r", function(d) {
                return rScale(d[1]) * 25;
            })
            .attr("stroke", "rgb(255, 255, 255)")
            .attr("stroke-width", "8")
            .attr("fill", function(d) {
                return "rgb(233, 236, 239)";
            });

            svg.on("click", function() {
                document.getElementById("msg").setAttribute("style", "display:none;");
                document.getElementById("msg").innerHTML = '';
                d3.event.stopPropagation();
            });

      var dataCircle = d3.select("svg")
        .append("svg")
            .attr("width", w)
            .attr("height", h)

      dataCircle.selectAll("circle")
        .data(data)
        .enter()
        .append("circle")
            .attr("cx", function(d) {
                return xScale_data(d[0]);
            })
            .attr("cy", function(d) {
                return yScale_data(d[1]);
            })
            .attr("id", function(d){
                return "circle-" + d[1]
            })
            .on("mouseover", function(d) {
                document.getElementById("msg").removeAttribute("style");
                document.getElementById("circle-" + d[1]).setAttribute("stroke", "rgb(140, 233, 255)");
                document.getElementById("circle-" + d[1]).setAttribute("stroke-width", "5");
                document.getElementById("msg").innerHTML = d[2];
                d3.event.stopPropagation();
            })
            .on("mouseout", function(d) {
                document.getElementById("msg").setAttribute("style", "display:none;");
                document.getElementById("circle-" + d[1]).removeAttribute("stroke");
                document.getElementById("circle-" + d[1]).removeAttribute("stroke-width");
                document.getElementById("msg").innerHTML = '';
                d3.event.stopPropagation();
            })
            .on("click", function(d) {
                document.getElementById("msg").removeAttribute("style");
                document.getElementById("msg").innerHTML = d[2];
                d3.event.stopPropagation();
            })
            .attr("style", "cursor:pointer;")

            .attr("r", function(d) {
                return rScale_data(d[1]) * 8;
            })

            .attr("fill", function(d) {
                return "rgba(" + Math.floor((Math.random() * 255) + 0) + "," + Math.floor((Math.random() * 255) + 0) + "," + Math.floor((Math.random() * 255) + 0) + ", 0.30)";
            })

    var color = d3.scale.category20();

    var pie = d3.layout.pie()
        .value(function(d) { return 5; })
        .sort(null);

    var arc = d3.svg.arc()
        .innerRadius(radius - 508)
        .outerRadius(radius - 480);

    var svg = d3.select("svg")
        .append("svg")
            .attr("width", w )
            .attr("height", h )
            .append("g")
                .attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");

    svg.datum(data_colors).selectAll("path")
        .data(pie)
        .enter()
        .append("path")
            .attr("cx", w / 2)
            .attr("cy", h / 2)
            .attr("r", 125)
            .attr("fill", function(d, i) { return color(i); })
            .attr("d", arc);

    </script>
      <div class="row">
        <div class="col-lg-12">
          <div id="msg" style="display:none;" class="underline alert alert-warning" align="center"></div>
        </div>
      </div>
    </div>
  </div>
</body>
</html>

If you don't need to be too specific where the small circles are positioned around the main circle, you could use d3.forceRadial ( https://github.com/d3/d3-force#forceRadial ).

If you want to be more precise about where the small circles appear on the main circle's circumference, you can write a function that specifies the x and y coordinate (relative to the centre of the circle) based on the radius and angle required, for example

function xyCoordinates(angle, radius) {
            let radians = 0.0174532925
            let x = radius * Math.sin(a * radians)
            let y = radius * Math.cos(a * radians)
            return [x,y]        
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM