Published
Edited
Dec 3, 2020
Insert cell
md`# Soha Spiral`
Insert cell
data = FileAttachment("Journalists_Death.csv").csv()
Insert cell
chart = {
let width = 500,
height = 500,
start = 0,
end = 2.25,
numSpirals = 4;

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

var r = d3.min([width, height]) / 2 - 40;
var radius = d3.scaleLinear()
.domain([start, end])
.range([40, r]);

var svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])


let wrapper = svg.append("g")
.attr("transform", `translate(${width/2},${height/2})`);
// create the spiral, borrowed from http://bl.ocks.org/syntagmatic/3543186
var points = d3.range(start, end + 0.001, (end - start) / 1000);
var spiral = d3.radialLine()
.curve(d3.curveCardinal)
.angle(theta)
.radius(radius);
var path = wrapper.append("path")
.datum(points)
.attr("id", "spiral")
.attr("d", spiral)
.style("fill", "none")
.style("stroke", "steelblue");
//fudge some data, 2 years of data starting today
var spiralLength = path.node().getTotalLength(),
N = 730,
barWidth = (spiralLength / N) - 1;
let year = d => d.year
let Total = d => d.Total
//here's our time scale that'll run along the spiral
//line 52
var timeScale = d3.scaleTime()
.domain(d3.extent(data, function(d){
return d.year;
}))
.range([0, spiralLength]);
// yScale for the bar height
var yScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d){
return d.Total
})])
.range([0, (r/numSpirals) - 30]);
//append our rects
wrapper.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", function(d,i){
//placement calculations
var linePer = timeScale(d.year),
posOnLine = path.node().getPointAtLength(linePer),
angleOnLine = path.node().getPointAtLength(linePer - barWidth);

d.linePer = linePer; // % of distance are on the spiral
d.x = posOnLine.x; // x position on the spiral
d.y = posOnLine.y; // y on position on the spiral
d.a = (Math.atan2(angleOnLine.y, angleOnLine.x) * 180 / Math.PI) - 90;
return d.x;
})
.attr("y", function(d){
return d.y;
})
.attr("width", function(d){
return barWidth;
})
.attr("height", function(d){
return yScale(d.Total);
})
.style("fill", "steelblue")
.style("stroke", "none")
.attr("transform", function(d){
return "rotate(" + d.a + "," + d.x + "," + d.y + ")";
});


return svg.node()


}
Insert cell
d3= require("d3@6")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more