chart_4 = {
const margin = {top: 30, right: 10, bottom: 10, left: 0};
const width = 700 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width + margin.left + margin.right, height + margin.top + margin.bottom])
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const dragging = {};
const y = {};
for (const dim of dimensions) {
y[dim] = d3.scaleLinear()
.domain(d3.extent(data, d => +d[dim]))
.range([height, 0]);
}
let x = d3.scalePoint()
.domain(dimensions)
.range([0, width])
.padding(1);
function path(d) {
return d3.line()(dimensions.map(p => [position(p), y[p](d[p])]));
}
function position(d) {
return dragging[d] == null ? x(d) : dragging[d];
}
const lines = g.append("g")
.attr("class", "lines")
.selectAll("path")
.data(data)
.join("path")
.attr("d", path)
.attr("fill", "none")
.attr("stroke", d => color(d.class))
.attr("stroke-width", 1.5)
.attr("opacity", 0.5);
const axes = g.selectAll(".axis")
.data(dimensions)
.join("g")
.attr("class", "axis")
.attr("transform", d => `translate(${x(d)},0)`)
.call(d3.drag()
.subject(d => ({x: x(d)}))
.on("start", function(event, d) {
dragging[d] = x(d);
})
.on("drag", function(event, d) {
dragging[d] = Math.min(width, Math.max(0, event.x));
dimensions.sort((a, b) => position(a) - position(b));
x.domain(dimensions);
axes.attr("transform", d => `translate(${position(d)},0)`);
lines.attr("d", path);
})
.on("end", function(event, d) {
delete dragging[d];
axes.transition().duration(500).attr("transform", d => `translate(${x(d)},0)`);
lines.transition().duration(500).attr("d", path);
})
);
axes.each(function(d) {
d3.select(this).call(d3.axisLeft(y[d]));
})
.append("text")
.attr("y", -9)
.attr("text-anchor", "middle")
.text(d => d)
.style("fill", "black");
return svg.node();
}