Skip to content

Instantly share code, notes, and snippets.

@kyleslattery
Created June 14, 2013 18:39
Show Gist options
  • Save kyleslattery/5784217 to your computer and use it in GitHub Desktop.
Save kyleslattery/5784217 to your computer and use it in GitHub Desktop.
Resizable, zoomable D3 line chart
var padding = 0;
var data, xScale, yScale, line, area;
var prevChartWidth = 0, prevChartHeight = 0;
var data = [
[],[]
]
for (var y = 0; y<data.length; y++) {
var prev = 5;
if (y==1) prev=2;
for (var i=0; i < 100; i+=1) {
prev = prev + Math.floor(Math.random()*3)-1;
if (prev < 0) prev = 0;
data[y].push([i, prev]);
}
}
var svg = d3.select("#chart")
.append("svg")
// Set up data
var yExtents = d3.extent(d3.merge(data), function(d) { return d[1]; });
var xExtents = d3.extent(d3.merge(data), function(d) { return d[0] });
xScale = d3.scale.linear().domain(xExtents)
yScale = d3.scale.linear().domain([0,yExtents[1]])
line = d3.svg.line()
.x(function(d) { return xScale(d[0]); })
.y(function(d) { return yScale(d[1]); })
.interpolate('basis');
area = d3.svg.area()
.x(function(d) { return xScale(d[0]) })
.y(function(d) { return yScale(d[1]) })
.interpolate("basis")
$(function() {updateChart(true)});
function updateChart(init) {
var $chart = $('#chart');
var chartWidth = $('#chart').width();
var chartHeight = $('#chart').height();
// if (prevChartHeight == chartHeight && prevChartWidth == chartWidth) return;
prevChartHeight = chartHeight;
prevChartWidth = chartWidth;
svg.attr('height', chartHeight).attr('width', chartWidth);
xScale.range([0, chartWidth]);
yScale.range([chartHeight,0]);
area.y0(chartHeight);
var pathContainers = svg.selectAll('g.line')
.data(data)
.enter()
.append('g').attr('class', 'line');
var areas = pathContainers.selectAll('path.area')
.data(function(d) {return[d]}, function(d) {return d[0]})
.enter().append('path')
.attr('class', 'area')
.attr('d', area)
var lines = pathContainers.selectAll('path.line')
.data(function(d,index) {
return [d];
}, function(d) { return d[0]})
.enter().append('path')
.attr('class', 'line')
.attr('d', line)
var selectedLines = svg.selectAll('path.line')
var selectedAreas = svg.selectAll('path.area')
selectedLines.transition().duration(300).attr("d", line)
selectedAreas.transition().duration(300).attr("d", area)
}
function updatedData() {
var yExtents = d3.extent(d3.merge(data), function(d) { return d[1]; });
var xExtents = d3.extent(d3.merge(data), function(d) { return d[0]; });
oldXScale = xScale.copy();
oldYScale = yScale.copy();
var selectedLines = svg.selectAll('path.line')
var selectedAreas = svg.selectAll('path.area')
svg.selectAll('g.line').data(data)
selectedLines.attr("d", line)
selectedAreas.attr("d", area)
xScale.domain(xExtents);
console.log(yExtents);
yScale.domain([0, yExtents[1]])
selectedLines.transition().duration(300).attr("d", line)
selectedAreas.transition().duration(300).attr("d", area)
// updateChart(false)
}
function zoomIn() {
var dataLength = data[0].length;
var dataLengthBy3 = Math.floor(dataLength/3)
for (var i = 0; i<data.length; i++) {
data[i] = data[i].slice(dataLengthBy3, dataLengthBy3*2)
}
updatedData()
}
function zoomOut() {
for (var i = 0; i<data.length; i++) {
var dataEnd = data[i][data[i].length-1]
var dataStart = data[i][0]
var prevEnd = dataEnd[1];
var prevStart = dataStart[1];
for (var j=1; j<25; j++) {
prevEnd = prevEnd + Math.floor(Math.random()*3)-1;
prevStart = prevStart + Math.floor(Math.random()*3)-1;
if (prevEnd < 0) prevEnd = 0;
if (prevStart < 0) prevStart = 0;
data[i].push([dataEnd[0]+j, prevEnd])
data[i].unshift([dataStart[0]-j, prevStart])
}
}
updatedData();
}
var resizeTimer;
window.onresize = function(event) {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function()
{
updateChart(false);
}, 20);
}
$(function() {
$("#zoom_out").click(function() {
zoomOut();
})
$("#zoom_in").click(function() {
zoomIn();
})
})
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<div id="chart"></div>
<p style="text-align: center"><button id="zoom_out">Zoom Out</button> <button id="zoom_in">Zoom In</button></p>
<script src="graph.js"></script>
</body>
</html>
body {
padding: 0;
margin: 0;
}
#chart {
width: 100%;
height: 400px;
margin: auto;
background-color: #ddd;
}
g.line path.line {
fill: none;
stroke: #666;
stroke-width: 2px;
}
.area {
fill: rgba(0,0, 135, 0.5);
stroke-width: 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment