Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

add circle in a spiral chart with d3js with line connecting to center

enter image description herehi I created a spiral chart in d3.js, and I want to add circle to different position of the spiral lines.according to there values. circle closes to the center will have highest priority. any idea how to do that.

here is the code which i wrote

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) + ")")
  });
}

enter image description here please see the second solution for my implementation. Help me with connecting the circle with the center

like image 419
Saurabh Sinha Avatar asked Dec 15 '25 11:12

Saurabh Sinha


1 Answers

Here is a model for the technique you seem to be looking for...

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>
like image 122
Cool Blue Avatar answered Dec 17 '25 01:12

Cool Blue