Public
Edited
Apr 13
Insert cell
Insert cell
barley.json
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
barley
Insert cell
barley
X
year
Y
yield
Color
Size
Facet X
site
Facet Y
variety
Mark
Auto
Type Chart, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
Insert cell
{
const width = 1400;
const height = 800;
const marginTop = 20;
const marginRight = 20;
const marginBottom = 50;
const marginLeft = 80;
const spacing = 12;
const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.style("overflow", "visible");

const x = d3.scaleBand()
.domain(Array.from(new Set(barley.map((d) => d.variety))))
.range([0, width - 400])
.padding(0.3);

const y = d3.scaleBand()
.domain(Array.from(new Set(barley.map((d) => d.site))))
.range([height - 100, 0])
.padding(0.3);

const g = svg
.append("g")
.attr("transform", `translate(${marginLeft}, ${marginBottom})`);

// Axes
g.append("g")
.attr("transform", `translate(0,${height - 100})`)
.call(d3.axisBottom(x));

g.append("g")
.call(d3.axisLeft(y));


// Container for barley marks
const barleyLayer = g.append("g").attr("class", "barley-layer");

const grouped = d3.group(barley, d => d.variety, d => d.site);

const updateFunctions = [];

for (const [variety, siteMap] of grouped) {
for (const [site, records] of siteMap) {
const record1931 = records.find(d => d.year === "1931") ;
const record1932 = records.find(d => d.year === "1932") ;

const cx = x(variety) + x.bandwidth() / 2;
const cy = y(site) + y.bandwidth() / 2;

const group = barleyLayer.append("g")
.attr("transform", `translate(${cx}, ${cy})`);

group.append("line")
.attr("x1", 0)
.attr("x2", 0)
.attr("y1", -spacing * 3.5)
.attr("y2", spacing * 4)
.attr("stroke", "black")
.attr("stroke-width", 1.5);

const updater = drawBarleyMark(group, record1931.yield, record1932.yield, 0, 0);
updateFunctions.push(updater);
}
}

// return svg.node();
const container = htl.html`<div></div>`;

// Append buttons to container ...refer to Introduction to D3 Course: Lesson 4 -
const buttons = d3.select(container)
.selectAll("button")
.data(["1931", "1932"])
.join("button")
.text(d => ` ${d}`)
.style("margin-right", "8px")
.on("click", (event, year) => {
updateFunctions.forEach(fn => fn(year));
});

// Append the generated SVG to the same container
d3.select(container).append(() => svg.node());

return container;

}
Insert cell
function drawBarleyMark(group, value1931, value1932, centerX, centerY) {
const radius = 7;
const spacing = 12;

const barleyData = [
{ color: "orange", dx: 0, dy: -3 * spacing },
{ color: "green", dx: 8, dy: -2 * spacing },
{ color: "green", dx: -8, dy: -1 * spacing },
{ color: "blue", dx: 8, dy: 0 },
{ color: "blue", dx: -8, dy: 1 * spacing },
{ color: "navy", dx: 8, dy: 2 * spacing },
{ color: "navy", dx: -8, dy: 3 * spacing }
];

const n = numCircle(value1931);
const initial = barleyData.slice(-n);

const g = group.append("g")
.attr("transform", `translate(${centerX}, ${centerY})`);

g.selectAll("circle")
.data(initial)
.enter()
.append("circle")
.attr("cx", d => d.dx)
.attr("cy", d => d.dy)
.attr("r", radius)
.attr("fill", d => d.color);

function update(year) {
const n = numCircle(year === "1931" ? value1931 : value1932);
const newData = barleyData.slice(-n);

g.selectAll("circle")
.data(newData, d => d.dy)
.join(
enter =>
enter.append("circle")
.attr("cx", d => d.dx)
.attr("cy", d => d.dy)
.attr("r", 0)
.attr("fill", d => d.color)
.transition().duration(800)
.attr("r", radius),
update =>
update.transition().duration(800)
.attr("cx", d => d.dx)
.attr("cy", d => d.dy)
.attr("fill", d => d.color),
exit =>
exit.transition().duration(800)
.attr("r", 0)
.remove()
);
}

return update;
}

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