简体   繁体   中英

How to position circles/points at intersection on a Radar Chart in D3.js

I am working on a Radar chart. I have appended some circles that I am trying to position at intersections. However, there seems to be something wrong with the cx and cy attributes of the circles, which I am unable to figure out.

Any help with this will be greatly appreciated.

 var dataset = [{ "day": 1, "sales": 40 }, { "day": 2, "sales": 85 }, { "day": 3, "sales": 70 }, { "day": 4, "sales": 30 }, { "day": 5, "sales": 85 }, { "day": 6, "sales": 60 }, { "day": 7, "sales": 85 }, { "day": 8, "sales": 35 }, { "day": 9, "sales": 70 }, { "day": 10, "sales": 15 }]; var w = 460, h = 460; var margin = { top: 20, bottom: 10, left: 10, right: 10 }; var width = w - margin.left - margin.right; var height = h - margin.top - margin.bottom; var circleConstraint = d3.min([height, width]); var radius = d3.scale.linear() .domain([0, 100]) .range([0, (circleConstraint / 2)]); var centerXPos = width / 2 + margin.left; var centerYPos = height / 2 + margin.top; var svg = d3.select("body").append("svg") .attr("width", w) .attr("height", h) .append("g") .attr("transform", "translate(" + centerXPos + ", " + centerYPos + ")"); //Adds circular gridLines and labels var gridLines = [0, 20, 40, 60, 80, 100]; var circleAxes = svg.selectAll(".circularGrid") .data(gridLines) .enter().append("g") .attr("class", "circularGrid"); circleAxes.append("circle") .attr("r", function(d) { return radius(d); }) .style("stroke", "#CCC") .style("fill", "none"); circleAxes.append("text") .attr("text-anchor", "middle") .attr("dy", function(d) { return radius(-d - 1); }) .text(String) .style("font-size", "10pt") .style("font-family", "sans-serif"); //Append path for salesLine var sales = []; dataset.forEach(function(d) { sales.push(d.sales); }); svg.selectAll(".salesLine") .data([sales]) .enter().append("path") .attr("class", "salesLine") .style("fill", "none") .style("stroke", "#000") .attr("d", d3.svg.line.radial() .radius(function(d) { return radius(d); }) .angle(function(d, i) { return (i / dataset.length) * 2 * Math.PI; })); // Appending circles at intersections svg.selectAll(".datapoints") .data(dataset).enter() .append("circle") .attr("class", "datapoints") .attr("r", 3) .style("fill", "#4393c3") .attr("cx", function(d) { return radius(d.day); }) .attr("cy", function(d) { return radius(d.sales); }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 

To fix the code, you should implement little bit of trigonometry:

// Appending circles at intersections
svg.selectAll(".datapoints")           // it doubles line [*]
  .data(dataset).enter()
  .append("svg:circle")                // full notation for the node
  .classed({"datapoints": true})       // [*] selection.classed() method for classes,
                                       // but you can omit this line because you wrote .selectAll(".datapoints") above
  .attr({"r": 10, "fill": "#4393c3"})  // you must make big dots 
                                       // to be clickable for people
  .attr("cx", function(d, i) {
        var alpha = (2 * Math.PI / dataset.length) * i;
        return( radius(d.sales) * Math.cos(alpha - Math.PI / 2) ); // just as in trigonometry book
  })
  .attr("cy", function(d, i) {
        var alpha = (2 * Math.PI / dataset.length) * i;
        return( radius(d.sales) * Math.sin(alpha - Math.PI / 2) );
  })
  .on("click", function(d){
        alert("$" + d.sales);
  })                                // now you can click on it to see the sales value
  .on("mouseover", function(d){     // little kiss of animation
    d3.select(this).attr("r", "14");
  })
  .on("mouseout", function(d){
    d3.select(this).attr("r", "10");
  });

DEMO: http://jsbin.com/jitepuhitu/1/

DEMO (animation): http://jsbin.com/niculecuzo/2/

I recommend you to draw data points like markers:

DEMO: http://jsbin.com/sepunibove/2/

By the way, multiple .attr() lines:

.attr("class", "datapoints")
.attr("r", 3)

you can write like single associative array:

.attr({"class": "datapoints", "r": 3})

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