Run this example in a full screen, or click "Open".
$ curl https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered_comma.csv | head -n4
date,value
2013-04-28,135.98
2013-04-29,147.49
2013-04-30,146.93
Run this example in a full screen, or click "Open".
$ curl https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered_comma.csv | head -n4
date,value
2013-04-28,135.98
2013-04-29,147.49
2013-04-30,146.93
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
position: fixed; | |
left: 0px; | |
right: 0px; | |
top: 0px; | |
bottom: 0px; | |
margin: 0px; | |
padding: 0px; | |
} | |
.line { | |
fill: none; | |
stroke: steelblue; | |
stroke-opacity: 0.4; | |
stroke-width: 2px; | |
} | |
.dot { | |
fill: #8080ff; | |
fill-opacity: 0.4; | |
} | |
g.x_axis path, g.y_axis path { | |
stroke: lightgray; | |
stroke-width: 1px; | |
} | |
g.x_axis line, g.y_axis line{ | |
stroke: lightgray; | |
stroke-opacity: 0.7; | |
shape-rendering: crispEdges; | |
} | |
</style> | |
</head> | |
<body></body> | |
<script src="https://d3js.org/d3.v7.min.js"></script> | |
<script> | |
const margin = {top: 20, right: 40, bottom: 40, left: 60}; | |
let dataSet; | |
(async () => { | |
const csvUrl = "https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered_comma.csv"; | |
dataSet = parseData(await d3.csv(csvUrl)); | |
render(); | |
setFileDrop(); | |
})(); | |
window.addEventListener("resize", debounce(render)); | |
function parseData(data) { | |
const parseDate = d3.timeParse("%Y-%m-%d"); | |
return data.map(d => {return {'date': parseDate(d.date), 'value': +d.value}}).filter(d => d.date);; | |
} | |
function render() { | |
const container = d3.select('body'); | |
const containerArea = container.node().getBoundingClientRect(); | |
const plotArea = { | |
'width': containerArea.width - margin.left - margin.right, | |
'height': containerArea.height - margin.top - margin.bottom}; | |
// svg | |
d3.select('svg').selectAll('*').remove(); | |
let svg = container.selectAll('svg').data([null]); | |
svg = svg.enter().append('svg').merge(svg) | |
svg = svg.attr("width", containerArea.width) | |
.attr("height", containerArea.height) | |
.append("g") | |
.attr("transform", | |
"translate(" + margin.left + "," + margin.top + ")"); | |
// xy | |
const domain = {'x': d3.extent(dataSet, d => d.date), | |
'y': [0, d3.max(dataSet, d => d.value)*1.01]}; | |
const x = d3.scaleTime().domain(domain.x).range([0, plotArea.width]); | |
const y = d3.scaleLinear().domain(domain.y).range([plotArea.height, 0]); | |
const f = {'x': d => x(d.date), 'y': d => y(d.value)}; | |
// axes | |
svg.append("g") | |
.attr("class", "x_axis") | |
.attr("transform", "translate(0," + plotArea.height + ")") | |
.call(d3.axisBottom(x).ticks(10).tickSize(-plotArea.height)); | |
svg.append("g") | |
.attr("class", "y_axis") | |
.call(d3.axisLeft(y).ticks(10).tickSize(-plotArea.width)); | |
// line chart | |
svg.append("path") | |
.data([dataSet]) | |
.attr("class", "line") | |
.attr("d", d3.line().x(f.x).y(f.y)); | |
// scatter plot | |
svg.selectAll("dot") | |
.data(dataSet) | |
.enter().append("circle") | |
.attr("r", 2) | |
.attr("class", "dot") | |
.attr("cx", f.x) | |
.attr("cy", f.y); | |
} | |
function debounce(func, time){ | |
time = time || 80; | |
let timer; | |
return function(event){ | |
if(timer) clearTimeout(timer); | |
timer = setTimeout(func, time, event); | |
}; | |
} | |
function setFileDrop(){ | |
d3.select('svg') | |
.on('dragover', function(event, _) { | |
event.stopPropagation(); | |
event.preventDefault(); | |
}) | |
.on('drop', async function(event, _) { | |
event.stopPropagation(); | |
event.preventDefault(); | |
let data = Array.from(event.dataTransfer.files).map(f => f.text()); | |
data = await Promise.all(data); | |
dataSet = parseData(d3.csvParse(data.flat()[0])); | |
console.log(dataSet.length); | |
render(); | |
}); | |
} | |
</script> | |
</html> |