This data set consists of flowering dates of the Prunus Jamasakura (Cherry Blossom) trees in Kyoto, Japan. Yasuyuki Aono (associate professor at Osaka Prefecture University) has compiled this data set from the 9th century to current day by tracing data sources from newspapers to historical poems. This scatter plot identifies the year (x axis), flowering day of the year (y axis), and estimated temperature on the flowering day (color).
forked from curran's block: Stylized Scatter Plot with Color Legend
Built with blockbuilder.org
forked from thulse's block: Cherry Blossom Flowering History (Kyoto, Japan)
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js"></script>
<title>Basic Scatter Plot</title>
<style>
body {
margin: 0px;
}
.domain {
display: none;
}
.tick line {
stroke: #C0C0BB;
}
.tick text, .legendCells text {
fill: ;
font-size: 10pt;
font-family: 'Poiret One';
}
.axis-label, .legend-label {
fill: #fea3a3;
font-size: 18pt;
font-family: 'Poiret One';
}
</style>
</head>
<body>
<svg width="960" height="500"></svg>
<script>
var xValue = d => d.year;
var xLabel = 'Year';
var yValue = d => d.flowering_day;
var yLabel = 'Flowering Day of the Year';
var colorValue = d => d.estimated_temp;
var colorLabel = 'Temperature (C)';
var margin = { left: 120, right: 300, top: 20, bottom: 120 };
var hoveredColorValue;
var hoveredStrokeColor = "black";
var svg = d3.select("body").append("svg")
.attr("width", outerWidth)
.attr("height", outerHeight);
var g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
var xAxisG = g.append('g')
.attr('transform', `translate(0, ${innerHeight})`);
var yAxisG = g.append('g');
var colorLegendG = g.append('g')
.attr('transform', `translate(${innerWidth + 60}, 150)`);
// This is the layer where the bars are drawn.
var baselayer = g.append("g");
// This layer contains a semi-transparent overlay
// that fades out the base bars.
var overlaycircle = g.append("g")
.append("circle")
.attr("width", innerWidth)
.attr("height", innerHeight)
.attr("fill", "none")
.style("pointer-events", "none");
// This contains the subset of bars rendered on top
// when you hover over the entries in the color legend.
var foregroundlLayer = g.append("g");
//axis titles
xAxisG.append('text')
.attr('class', 'axis-label')
.attr('x', innerWidth / 2)
.attr('y', 75)
.text(xLabel);
yAxisG.append('text')
.attr('class', 'axis-label')
.attr('x', -innerHeight / 2)
.attr('y', -60)
.attr('transform', `rotate(-90)`)
.style('text-anchor', 'middle')
.text(yLabel);
colorLegendG.append('text')
.attr('class', 'legend-label')
.attr('x', -30)
.attr('y', -40)
.text(colorLabel);
var tipNumberFormat = d3.format(",");
var tip = d3.tip()
.attr("class", "d3-tip")
.offset([-10, 0])
.html(function(d) {
return [
d[colorValue],
" in ",
d[yValue],
": ",
tipNumberFormat(d[xValue])
].join("");
});
g.call(tip);
function render(data){
var nested = d3.nest()
.key(function (d){ return d[layerColumn]; })
.entries(data);
var stack = d3.layout.stack()
.y(function (d){ return d[xColumn]; })
.values(function (d){ return d.values; });
var layers = stack(nested.reverse()).reverse();
xScale.domain([
0,
d3.max(layers, function (layer){
return d3.max(layer.values, function (d){
return d.y0 + d.y;
});
})
]);
yScale.domain(layers[0].values.map(function (d){
return d[yColumn];
}));
colorScale.domain(layers.map(function (layer){
return layer.key;
}));
xAxisG.call(xAxis);
yAxisG.call(yAxis);
renderBars(baseBarLayer, layers);
if(hoveredColorValue){
setOverlayTransparency(0.7);
renderBars(foregroundBarLayer, layers.filter(function (layer){
return layer.key === hoveredColorValue;
}));
} else {
setOverlayTransparency(0.0);
renderBars(foregroundBarLayer, []);
}
colorLegendG.call(colorLegend);
// Move the text down a bit.
colorLegendG.selectAll("text").attr("y", 4);
listenForHover(colorLegendG.selectAll("rect"), data);
listenForHover(colorLegendG.selectAll("text"), data);
}
function renderBars(g, layers){
var layerGs = g.selectAll(".layer").data(layers);
layerGs.enter().append("g").attr("class", "layer");
layerGs.exit().remove();
layerGs.style("fill", function (d){
return colorScale(d.key);
});
var bars = layerGs.selectAll("rect").data(function (d){
return d.values;
});
bars.enter().append("rect")
.on("mouseover", function(d){
tip.show(d);
// Fix the issue where the tip goes off the screen.
d3.select(".d3-tip").style("left", "100px");
})
.on("mouseout", tip.hide);
bars.exit().remove();
bars
.attr("x", function (d){ return xScale(d.y0); })
.attr("y", function (d){ return yScale(d[yColumn]); })
.attr("width", function (d){ return xScale(d.y); })
.attr("height", yScale.rangeBand());
}
function listenForHover(selection, data){
selection
.on("mouseover", function (d){
hoveredColorValue = d;
render(data);
})
.on("mouseout", function (d){
hoveredColorValue = null;
render(data);
})
.style("cursor", "pointer");
}
function setOverlayTransparency(alpha){
overlayRect
.transition().duration(400)
.attr("fill", "rgba(255, 255, 255, " + alpha + ")");
}
function type(d){
d.population = +d.population;
return d;
}
//setting scale
const xScale = d3.scaleLinear();
const yScale = d3.scaleLinear();
var colorScale = d3.scaleQuantize()
.domain([3.0, 9.0])
.range([ "#7546cc","#467acc", "#46ccb1", "#ccca46", "#cc8746","#c43538"]);
const xAxis = d3.axisBottom()
.scale(xScale)
.tickPadding(15)
.tickSize(-innerHeight)
.tickFormat(d3.format("0"));
const yAxis = d3.axisLeft()
.scale(yScale)
.tickPadding(15)
.tickSize(-innerWidth);
//.tickFormat(d3.timeformat("%B"))
//var parseDate = d3.timeParse("%Y-%m")
const colorLegend = d3.legendColor()
.scale(colorScale)
.shape('circle');
const row = d => {
d.year = +d.year;
d.flowering_day = +d.flowering_day;
d.estimated_temp = +d.estimated_temp;
return d;
};
d3.csv('SakuraData5.csv', row, data => {
xScale
.domain(d3.extent(data, xValue))
.range([0, innerWidth])
.nice();
yScale
.domain(d3.extent(data, yValue))
.range([innerHeight, 0])
.nice();
g.selectAll('circle').data(data)
.enter().append('circle')
.attr('cx', d => xScale(xValue(d)))
.attr('cy', d => yScale(yValue(d)))
.attr('fill', d => colorScale(colorValue(d)))
.attr('fill-opacity', 0.8)
.attr('r', 5);
xAxisG.call(xAxis);
yAxisG.call(yAxis);
colorLegendG.call(colorLegend)
.selectAll('.cell text')
.attr('dy', '0.1em');
});
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js