使用d3js在螺旋图中添加圆圈,并连接到中心的线。

3

图片描述你好,我在d3.js中创建了一个螺旋图表,并希望将圆圈添加到螺旋线的不同位置,根据它们的值。 靠近中心的圆圈优先级最高。 有什么想法吗?

这是我编写的代码:

var width = 400,
height = 430
num_axes = 8,
tick_axis = 1,
start = 0
end = 4;

var theta = function(r) {
  return -2*Math.PI*r;
};

var arc = d3.svg.arc()
  .startAngle(0)
  .endAngle(2*Math.PI);

var radius = d3.scale.linear()
  .domain([start, end])
  .range([0, d3.min([width,height])/2-20]);

var angle = d3.scale.linear()
  .domain([0,num_axes])
  .range([0,360])

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

var pieces = d3.range(start, end+0.001, (end-start)/1000);

var spiral = d3.svg.line.radial()
  .interpolate("cardinal")
  .angle(theta)
  .radius(radius);

//svg.append("text")
//  .text("And there was much rejoicing!")
//  .attr("class", "title")
//  .attr("x", 0)
//  .attr("y", -height/2+16)
//  .attr("text-anchor", "middle")

//svg.selectAll("circle.tick")
//    .data(d3.range(end,start,(start-end)/4))
//  .enter().append("circle")
//    .attr("class", "tick")
//    .attr("cx", 0)
//    .attr("cy", 0)
//    .attr("r", function(d) { return radius(d); })

svg.selectAll(".axis")
    .data(d3.range(num_axes))
  .enter().append("g")
    .attr("class", "axis")
    .attr("transform", function(d) { return "rotate(" + -angle(d) + ")"; })
  .call(radial_tick)
  .append("text")
    .attr("y", radius(end)+13)
    .text(function(d) { return angle(d) + "°"; })
    .attr("text-anchor", "middle")
    .attr("transform", function(d) { return "rotate(" + -90 + ")" })

svg.selectAll(".spiral")
    .data([pieces])
  .enter().append("path")
    .attr("class", "spiral")
    .attr("d", spiral)
    .attr("transform", function(d) { return "rotate(" + 90 + ")" });

function radial_tick(selection) {
  selection.each(function(axis_num) {
    d3.svg.axis()
      .scale(radius)
      .ticks(5)
      .tickValues( axis_num == tick_axis ? null : [])
      .orient("bottom")(d3.select(this))

    d3.select(this)
      .selectAll("text")
      .attr("text-anchor", "bottom")
      .attr("transform", "rotate(" + angle(axis_num) + ")")
  });
}

请参考第二个解决方案来实现圆心连接圆的问题。

如果我的回答不是你想要的,请评论说明。在我看来,问题已经得到了解答... - Cool Blue
1个回答

1

这里是一个模型,似乎符合您正在寻找的技术...

var width = 400,
  height = 430,
  num_axes = 8,
  tick_axis = 1,
  start = 0,
  end = 4,
  testValue = 2;

  var theta = function (r) {
   return -2 * Math.PI * r;
  };

  var arc = d3.svg.arc()
   .startAngle(0)
   .endAngle(2 * Math.PI);

  var radius = d3.scale.linear()
   .domain([start, end])
   .range([0, (d3.min([width, height]) / 2 - 20)]);

  var angle = d3.scale.linear()
   .domain([0, num_axes])
   .range([0, 360]);

  var chart = d3.select("#chart")
   .style("width", width + "px");

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

  var pieces = d3.range(start, end + 0.001, (end - start) / 500);

  var spiral = d3.svg.line.radial()
   .interpolate("linear")
   .angle(theta)
   .radius(radius);
  
  svg.append("text")
   .text("Title")
   .attr("class", "title")
   .attr("x", 0)
   .attr("y", -height/2+16)
   .attr("text-anchor", "middle")

  svg.selectAll("circle.tick")
    .data(d3.range(end,start,(start-end)/4))
   .enter().append("circle")
    .attr("class", "tick")
    .style({fill: "black", opacity: 0.1})
    .attr("cx", 0)
    .attr("cy", 0)
    .attr("r", function(d) { return radius(d); })

  svg.selectAll(".axis")
    .data(d3.range(num_axes))
   .enter().append("g")
    .attr("class", "axis")
    .attr("transform", function (d) { return "rotate(" + -angle(d) + ")"; })
   .call(radial_tick)
   .append("text")
    .attr("y", radius(end) + 13)
    .text(function (d) { return angle(d) + "°"; })
    .attr("text-anchor", "middle")
    .attr("transform", function (d) { return "rotate(" + -90 + ")" })

  svg.selectAll(".axis path")
   .style({fill: "none", stroke: "black"})
   .attr("stroke-dasharray", "5 5")

  svg.selectAll(".spiral")
    .data([pieces])
   .enter().append("path")
    .attr("class", "spiral")
    .attr("fill", "none")
    .attr("stroke", "black")
    .attr("d", spiral)
    .attr("transform", function (d) { return "rotate(" + 90 + ")" });

  function radial_tick(selection) {
   selection.each(function (axis_num) {
    d3.svg.axis()
     .scale(radius)
     .ticks(5)
     .tickValues(axis_num == tick_axis ? null : [])
     .tickSize(1)
     .orient("bottom")(d3.select(this))

    d3.select(this)
     .selectAll("text")
     .attr("text-anchor", "bottom")
     .attr("transform", "rotate(" + angle(axis_num) + ")")
   });
  }
  function radialScale(x) {
   var t = theta(x), r = radius(x);
   d3.select(this)
   .attr("cx", r * Math.cos(t))
   .attr("cy", r * Math.sin(t))
  }

  slider = SliderControl("#circleSlider", "data", update, [start, end], ",.3f");

  function update(x) {

    if (typeof x != "undefined") testValue = x;
   
   var circles = svg.selectAll(".dataPoints")
    .data([testValue]);
   circles.enter().append("circle");

    circles.attr("class", "dataPoints")
     .style({ fill: "black", opacity: 0.6 })
     .attr("r", 10)
     .each(radialScale)
   circles.exit().remove();
   return testValue
  }

  function SliderControl(selector, title, value, domain, format) {
   var accessor = d3.functor(value), rangeMax = 1000,
     _scale = d3.scale.linear().domain(domain).range([0, rangeMax]),
     _$outputDiv = $("<div />", { class: "slider-value" }),
     _update = function (value) {
      _$outputDiv.css("left", 'calc( '
       + (_$slider.position().left + _$slider.outerWidth()) + 'px + 1em )')
      _$outputDiv.text(d3.format(format)(value));
      $(".input").width(_$outputDiv.position().left + _$outputDiv.outerWidth() - _innerLeft)

     },

     _$slider = $(selector).slider({
      value: _scale(accessor()),
      max: rangeMax,
      slide: function (e, ui) {
       _update(_scale.invert(ui.value));
       accessor(_scale.invert(ui.value));
      }
     }),
     _$wrapper = _$slider.wrap("<div class='input'></div>")
     .before($("<div />").text(title + ":"))
     .after(_$outputDiv).parent(),
     _innerLeft = _$wrapper.children().first().position().left;

   _update(_scale.invert($(selector).slider("value")))

   return d3.select(selector)
  };
.domain {
   stroke-width: 1px;
  }
<link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
 <div id="chart">
  <div id="circleSlider"></div>
 </div>


你的答案是正确的,但我用了不同的方法实现它。无论如何,我会将其标记为正确答案 :)。我在下面发布了我的解决方案。如果可以的话,我还想再请你帮个忙。我想把下一张图片中的所有圆都移到中心,请看下面我的答案。 - Saurabh Sinha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接