|
<!DOCTYPE html> |
|
<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> |
|
const xValue = d => d.year; |
|
const xLabel = 'Year'; |
|
const yValue = d => d.flowering_day; |
|
const yLabel = 'Flowering Day of the Year'; |
|
const colorValue = d => d.estimated_temp; |
|
const colorLabel = 'Temperature (C)'; |
|
const margin = { left: 120, right: 300, top: 20, bottom: 120 }; |
|
|
|
const svg = d3.select('svg'); |
|
const width = svg.attr('width'); |
|
const height = svg.attr('height'); |
|
const innerWidth = width - margin.left - margin.right; |
|
const innerHeight = height - margin.top - margin.bottom; |
|
|
|
const g = svg.append('g') |
|
.attr('transform', `translate(${margin.left},${margin.top})`); |
|
const xAxisG = g.append('g') |
|
.attr('transform', `translate(0, ${innerHeight})`); |
|
const yAxisG = g.append('g'); |
|
// const colorLegendG = g.append('g') |
|
// .attr('transform', `translate(${innerWidth + 60}, 150)`); |
|
|
|
var brush = d3.brush().on("end", brushended), |
|
idleTimeout, |
|
idleDelay = 350; |
|
|
|
var k = height / width, |
|
x0 = [-4.5, 4.5], |
|
y0 = [-4.5 * k, 4.5 * k], |
|
x = d3.scaleLinear().domain(x0).range([0, width]), |
|
y = d3.scaleLinear().domain(y0).range([height, 0]), |
|
z = d3.scaleOrdinal(d3.schemeCategory10); |
|
|
|
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); |
|
|
|
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; |
|
}; |
|
|
|
svg.append("g") |
|
.attr("class", "axis axis--x") |
|
.attr("transform", "translate(0," + (height - 10) + ")") |
|
.call(xAxis); |
|
|
|
svg.append("g") |
|
.attr("class", "axis axis--y") |
|
.attr("transform", "translate(10,0)") |
|
.call(yAxis); |
|
|
|
svg.selectAll(".domain") |
|
.style("display", "none"); |
|
|
|
svg.append("g") |
|
.attr("class", "brush") |
|
.call(brush); |
|
|
|
function brushended() { |
|
var s = d3.event.selection; |
|
if (!s) { |
|
if (!idleTimeout) return idleTimeout = setTimeout(idled, idleDelay); |
|
x.domain(x0); |
|
y.domain(y0); |
|
} else { |
|
x.domain([s[0][0], s[1][0]].map(x.invert, x)); |
|
y.domain([s[1][1], s[0][1]].map(y.invert, y)); |
|
svg.select(".brush").call(brush.move, null); |
|
} |
|
zoom(); |
|
} |
|
|
|
function idled() { |
|
idleTimeout = null; |
|
} |
|
|
|
function zoom() { |
|
var t = svg.transition().duration(750); |
|
svg.select(".axis--x").transition(t).call(xAxis); |
|
svg.select(".axis--y").transition(t).call(yAxis); |
|
svg.selectAll("circle").transition(t) |
|
.attr("cx", function(d) { return x(d[0]); }) |
|
.attr("cy", function(d) { return y(d[1]); }); |
|
} |
|
|
|
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> |