xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-request.v1.min.js"></script>
<script src="https://d3js.org/d3-time.v1.min.js"></script>
<script src="https://d3js.org/d3-time-format.v2.min.js"></script>
<script src="https://d3js.org/d3-scale.v1.min.js"></script>
<script src="https://d3js.org/d3-axis.v1.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0;padding:20px; }
.artist {
stroke-width: 1.5px;
stroke: steelblue;
fill: none;
stroke-opacity: 0.7;
}
circle {
fill: white;
fill-opacity: 0.7;
}
circle.start {
fill: white !important;
}
.highlight {
stroke: orange;
stroke-width: 3px;
stroke-opacity: 1 !important;
}
.highlight circle {
fill-opacity: 1;
}
.axis line {
stroke-opacity: 0.2;
stroke-width: 0.7px;
}
</style>
</head>
<body>
<h1>Deltagit fem gånger eller mer</h1>
<script>
var conf = { width: 700, height: 300, padding: 50 };
var idRegex = /[^\w]/gi;
d3.json("data.json", (d) => {
populateSelect(d.artists);
var svg = d3.select("body").append("svg")
.attr("width", conf.width)
.attr("height", conf.height)
let rainbow = d3.scaleOrdinal(d3.schemeCategory10);
let timeScale = d3.scaleTime()
.domain([new Date(1958, 1, 1), new Date(2018, 1, 1)])
.range([conf.padding, conf.width - conf.padding]);
let yScale = d3.scaleLinear()
.domain([0, 11])
.range([conf.height - conf.padding, conf.padding]);
let opacityScale = d3.scaleLinear()
.domain([0, 11])
.range([0, 1]);
let line = d3.line()
.x(function(d,i) { return timeScale(new Date(d, 1, 1)); })
.y(function(d,i) { return yScale(i+1); })
.curve(d3.curveCatmullRom)
let artist = svg.selectAll("g")
.data(d.artists)
.enter()
.append("g")
.classed("artist", true)
.attr("id", (d) => d.name.replace(idRegex, ''))
.style("stroke-opacity", (d) => opacityScale(d.year.length-1))
.style("stroke", (d) => rainbow(d.year.length-1));
artist.each(function(d, i) {
let aElem = d3.select(this);
let years = d.year.sort();
aElem.append("path")
.datum(years)
.attr("d", line);
aElem.append("circle")
.attr("cx", timeScale(new Date(years[0], 1, 1)))
.attr("cy", yScale(1))
.attr("r", 2)
.classed("start", true);
aElem.append("circle")
.attr("cx", timeScale(new Date(years.reverse()[0], 1, 1)))
.attr("cy", yScale(years.length))
.attr("r", 2)
.style("fill", (d) => rainbow(years.length-1))
});
let axisYear = d3.axisBottom(timeScale);
svg.append("g")
.attr("transform", "translate(0," + (conf.height - conf.padding) + ")")
.call(axisYear);
let axisEntries = d3.axisLeft(yScale)
.ticks(4)
.tickSizeOuter([0])
.tickSizeInner([2 * conf.padding - conf.width ])
svg.append("g")
.classed("axis", true)
.attr("transform", "translate(" + conf.padding + ", 0)")
.call(axisEntries);
});
function populateSelect(data) {
var artists = data.slice(0);
artists.sort((a, b) => {
if(a.name < b.name) return -1;
if(a.name > b.name) return 1;
return 0;
});
var select = d3.select("body")
.append("div")
.append("select")
select
.on("change", function(d) {
d3.selectAll(".highlight circle").attr("r", 2);
d3.select(".highlight").classed("highlight", false);
let selection =
d3.select("#" + d3.select(this).property("value")).classed("highlight", true);
selection.raise();
selection.selectAll("circle").attr("r", 5);
});
artists.unshift({ name: " - Filtrera - ", year: []});
select.selectAll("option")
.data(artists)
.enter()
.append("option")
.attr("value", (d) => d.name.replace(idRegex, ''))
.text((d) => d.name);
}
</script>
</body>
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-request.v1.min.js
https://d3js.org/d3-time.v1.min.js
https://d3js.org/d3-time-format.v2.min.js
https://d3js.org/d3-scale.v1.min.js
https://d3js.org/d3-axis.v1.min.js