|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<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>DC Bike Share Test Chart</title> |
|
<style> |
|
|
|
#viz1 { |
|
position: fixed; |
|
left: 0px; |
|
right: 0px; |
|
top: 0px; |
|
bottom:0px; |
|
} |
|
|
|
body { |
|
margin: 0px; |
|
} |
|
.domain { |
|
display: none; |
|
} |
|
.tick line { |
|
stroke: #C0C0BB; |
|
} |
|
.tick text, .legendCells text { |
|
fill: #8E8883; |
|
font-size: 8pt; |
|
font-family: sans-serif; |
|
} |
|
.axis-label, .legend-label { |
|
fill: #635F5D; |
|
font-size: 10pt; |
|
font-family: sans-serif; |
|
} |
|
|
|
|
|
|
|
</style> |
|
</head> |
|
<body> |
|
|
|
<div id="viz1"></div> |
|
|
|
<script> |
|
|
|
var viz1Div = document.getElementById('viz1'); |
|
var svg = d3.select(viz1Div) |
|
.selectAll('svg') |
|
.data([null]); |
|
|
|
var svgEnter = svg |
|
.enter() |
|
.append('svg'); |
|
|
|
const localFile = 'data/day.csv' |
|
const blocksFile = 'day.csv' |
|
var datafile = blocksFile |
|
|
|
const defaultOpacity =0.2; |
|
|
|
|
|
//set x and y value pointers and axis labels |
|
const xValue = d => d.temp; |
|
const xLabel = 'Temperature'; |
|
const yValue = d => d.casual; |
|
const yValue2 = d => d.registered; |
|
const yLabel = 'Users'; |
|
|
|
const margin = { left: 120, right: 60, top: 60, bottom: 120 }; |
|
|
|
//row function to parse csv |
|
const row = d => { |
|
d.instant = +d.instant; |
|
d.dteday = new Date(d.dteday); //need to parse date |
|
d.season = +d.season; |
|
d.yr = +d.yr; |
|
d.mnth = +d.mnth; |
|
d.holiday = +d.holiday; //flag |
|
d.weekday = +d.weekday; //integer day of week (0-6) |
|
d.workingday = +d.workingday; //flag |
|
d.weathersit = +d.weathersit; //(1-4) |
|
d.temp = +d.temp; |
|
d.atemp = +d.atemp; |
|
d.hum = +d.hum; |
|
d.windspeed = +d.windspeed; |
|
d.casual = +d.casual; |
|
d.registered = +d.registered; |
|
d.cnt = +d.cnt; |
|
return d; |
|
}; |
|
|
|
|
|
|
|
function scatterPlot(svg, data, xValue, yValue, width, height, margin) { |
|
// maintain 1:1 aspect ratio for plot |
|
const minDimension = d3.min([width, height]); |
|
//set svg size to window |
|
svg = svgEnter |
|
.merge(svg) |
|
.attr('width',minDimension) |
|
.attr('height',minDimension); |
|
|
|
console.log(width, height, minDimension); |
|
console.log(svg.attr('width'), svg.attr('height')); |
|
|
|
const innerHeight = minDimension - margin.top - margin.bottom; |
|
const innerWidth = minDimension - margin.left - margin.right; |
|
|
|
const xScale = d3.scaleLinear(); |
|
const yScale = d3.scaleLinear(); |
|
|
|
xScale |
|
.domain(d3.extent(data, xValue)) |
|
.range([0, innerWidth]) |
|
.nice(); |
|
|
|
yScale |
|
.domain(d3.extent(data, yValue)) |
|
.range([innerHeight, 0]) |
|
.nice(); |
|
|
|
const xAxis = d3.axisBottom() |
|
.scale(xScale) |
|
.tickPadding(10) |
|
.tickFormat(d3.format('0')) |
|
.tickSize(-innerHeight); |
|
|
|
const yAxis = d3.axisLeft() |
|
.scale(yScale) |
|
.tickPadding(10) |
|
.tickSize(-innerWidth); |
|
|
|
var g = svg.selectAll('g').data([null]); |
|
|
|
g = g.enter().append('g') |
|
.merge(g) |
|
.attr('transform', `translate(${margin.left},${margin.top})`); |
|
|
|
var xAxisG = g.selectAll('#x-axis-g').data([null]); |
|
|
|
xAxisG = xAxisG.enter().append('g').merge(xAxisG) |
|
.attr('id','x-axis-g') |
|
.attr('transform', `translate(0, ${innerHeight})`); |
|
|
|
var yAxisG = g.selectAll('#y-axis-g').data([null]); |
|
|
|
yAxisG = yAxisG.enter().append('g').merge(yAxisG) |
|
.attr('id','y-axis-g'); |
|
|
|
|
|
console.log(innerWidth, innerHeight, margin); |
|
|
|
|
|
var xAxisText = g.selectAll('#x-axis-label').data([null]); |
|
xAxisText = xAxisText.enter().append('text').merge(xAxisText) |
|
.attr('class', 'axis-label') |
|
.attr('id', 'x-axis-label') |
|
.attr('x', innerWidth / 2) |
|
.attr('y', innerHeight+margin.bottom/2) |
|
.style('text-anchor', 'middle') |
|
.text(xLabel); |
|
|
|
var yAxisText = g.selectAll('#y-axis-label').data([null]); |
|
yAxisText = yAxisText.enter().append('text').merge(yAxisText) |
|
.attr('class', 'axis-label') |
|
.attr('id', 'y-axis-label') |
|
.attr('x', -innerHeight / 2) |
|
.attr('y', -margin.left/2) |
|
.attr('transform', `rotate(-90)`) |
|
.style('text-anchor', 'middle') |
|
.text(yLabel); |
|
|
|
|
|
|
|
|
|
//log domain of yValues |
|
console.log(d3.extent(data, yValue)); |
|
|
|
//log exoected max values of x and y scale |
|
console.log(xScale(0), xScale(1)) |
|
console.log(yScale(0), yScale(3410)) |
|
|
|
//data join |
|
var circles = g.selectAll('circle').data(data); |
|
|
|
//Add new elements |
|
var circlesEnter = circles.enter().append('circle'); |
|
var t = d3.transition().duration(500); |
|
|
|
var circlesExit = circles.exit() |
|
.attr('class','exit') |
|
.remove(); |
|
|
|
//UPDATE old elements present (change class) |
|
circles |
|
.attr('class','update') |
|
|
|
//merge new and existing ell |
|
circlesEnter |
|
.attr('class','enter') |
|
.attr('fill', 'green') |
|
.attr('r', 5) |
|
.merge(circles) |
|
.attr('cx', d => xScale(xValue(d))) |
|
.attr('cy', d => yScale(yValue(d))) |
|
.attr('fill-opacity', d=>(d.filterOpacity)); |
|
|
|
//remove elements for which there is no data |
|
circlesExit |
|
|
|
//call X and Y axis |
|
xAxisG.call(xAxis); |
|
yAxisG.call(yAxis); |
|
//colorLegendG.call(colorLegend) |
|
// .selectAll('.cell text') |
|
// .attr('dy', '0.1em'); |
|
|
|
|
|
}; |
|
|
|
console.log('join data'); |
|
|
|
|
|
d3.csv(datafile, row, data => { |
|
|
|
const render =() => { |
|
//get window width and height computed by CCS |
|
const width = viz1Div.clientWidth; |
|
const height = viz1Div.clientHeight; |
|
|
|
data.forEach(d=>d.filterOpacity=.5); |
|
f7 =false |
|
filterMonth = [11,12,1,2,3,4,10] |
|
filterYear = 0 |
|
filterHoliday =3 |
|
filterWorking =1 |
|
|
|
function applyFilter(filterMonth,filterYear,filterHoliday,filterWorking,f7){ |
|
data.forEach(d =>{ |
|
if(filterMonth.includes(d.mnth)){d.filterOpacity=0} |
|
if(d.yr==filterYear && f7==false){d.filterOpacity=0} |
|
if(d.holiday==filterHoliday && f7==false){d.filterOpacity=0} |
|
if(d.workingday==filterWorking && f7==false){d.filterOpacity=0} |
|
}); |
|
}; |
|
|
|
applyFilter(filterMonth,filterYear,filterHoliday,filterWorking,f7) |
|
scatterPlot(svg, data, xValue, yValue, width, height, margin); |
|
} |
|
|
|
console.log('now render'); |
|
|
|
render(); |
|
|
|
console.log('resized and rendered...'); |
|
|
|
window.addEventListener('resize',render); |
|
|
|
}); |
|
|
|
|
|
|
|
</script> |
|
</body> |
|
</html> |