Skip to content

Instantly share code, notes, and snippets.

@m99coder
Last active August 29, 2015 14:24
Show Gist options
  • Save m99coder/136db7134df6fdc3e3cf to your computer and use it in GitHub Desktop.
Save m99coder/136db7134df6fdc3e3cf to your computer and use it in GitHub Desktop.
D3 Multiline Chart
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Pure D3 Charts</title>
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Roboto+Slab:400,100,300,700">
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div>
<h1>Pure D3</h1>
<p>
Using pure d3 for a line chart.
</p>
<h2>Line Chart</h2>
<div id="line-chart"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script src="line-chart.js"></script>
<script>
var getIncrementedTimestamp = function(increment) {
return new Date(2015, 0, 1).getTime() + increment * 60000;
};
var lastRandom = {};
var getRandomValue = function(series) {
var options = {
min: 0,
max: 2,
integers: false
};
var randomize = function() {
if (lastRandom[series] === undefined || lastRandom[series] === null) {
lastRandom[series] = Math.random() * Math.abs(options.max - options.min) + options.min;
return lastRandom[series];
}
lastRandom[series] = Math.abs(lastRandom[series] + Math.random() - 0.5);
return lastRandom[series];
};
return options.integers ? Math.ceil(randomize()) : randomize();
};
var NUMBER_OF_TIMESERIES = 2;
var VALUES_PER_TIMESERIES = 60;
var data = [];
for (var series=0; series<NUMBER_OF_TIMESERIES; series++) {
data[series] = [];
for (var dp=0; dp<VALUES_PER_TIMESERIES; dp++) {
data[series][dp] = {
timestamp: getIncrementedTimestamp(dp),
value: getRandomValue(series)
};
}
}
var lineChart = new LineChart();
lineChart.draw(data);
var currentTS = data[0].length - 1;
window.setInterval(function() {
// remove old data point from start
if (data[0].length > VALUES_PER_TIMESERIES) {
data.forEach(function(d) {
d.shift();
});
}
// add new data point to end
data.forEach(function(d, i) {
d.push({
timestamp: getIncrementedTimestamp(currentTS + 1),
value: getRandomValue(i)
});
});
currentTS++;
// update line
lineChart.draw(data);
}, 1000);
</script>
</body>
</html>
var LineChart = function LineChart() {
// OPTIONS
// -------
var options = {};
options.margin = {
top: 10,
right: 10,
bottom: 10,
left: 10
};
options.width = 600 - options.margin.left - options.margin.right;
options.height = 140 - options.margin.top - options.margin.bottom;
// SCALES
// ------
var scales = {};
scales.x = d3.time.scale().range([0, options.width]);
scales.y = d3.scale.linear().range([options.height, 0]);
scales.color = d3.scale.category10();
// LINE
// ----
var line =
d3.svg.line()
.interpolate('basis')
.x(function(d) {
return scales.x(d.timestamp);
})
.y(function(d) {
return scales.y(d.value);
});
// INIT
// ----
// svg container
var svg =
d3.select('#line-chart')
.append('svg')
.attr('width', options.width + options.margin.left + options.margin.right)
.attr('height', options.height + options.margin.top + options.margin.bottom);
// translate with margins
var canvas =
svg.append('g')
.attr('transform', 'translate(' + options.margin.left + ',' + options.margin.right + ')');
// clipping path
canvas.append('defs').append('clipPath')
.attr('id', 'clip')
.append('rect')
.attr('width', options.width)
.attr('height', options.height);
// DRAW
// ----
this.draw = function draw(data) {
// DOMAINS
// -------
scales.x.domain([
d3.min(data, function(dp) {
return d3.min(dp, function(d) {
return d.timestamp;
});
}) + 60000,
d3.max(data, function(dp) {
return d3.max(dp, function(d) {
return d.timestamp;
});
}) - 60000
]);
//console.info(scales.x.domain());
scales.y.domain([
d3.min(data, function(dp) {
return d3.min(dp, function(d) {
return d.value;
});
}),
d3.max(data, function(dp) {
return d3.max(dp, function(d) {
return d.value;
});
})
]);
// UPDATE
// ------
// create series g container and paths inside
canvas.selectAll('.series')
.data(data)
.enter()
.append('g')
.attr('clip-path', 'url(#clip)')
.attr('class', 'series')
.append('path')
.attr('class', 'line')
.attr('stroke', function(d, i) {
return scales.color(i);
});
/*
canvas.selectAll('.line')
.transition()
.duration(600)
.attr('d', function(d) {
return line(d);
});
*/
canvas.selectAll('.line')
.attr('d', function(d) {
return line(d);
})
.attr('transform', null)
.transition()
.duration(1000)
.ease('linear')
.attr('transform', function(d) {
return 'translate(' + scales.x(d[0].timestamp - 60000) + ')';
});
};
};
* {
font-family: 'Roboto', sans-serif;
color: #666;
}
body {
margin: 20px 20px 20px 100px;
}
h1, h2, h3 {
font-family: 'Roboto Slab', serif;
color: #000;
}
.background {
fill: #eee;
}
.line {
fill: none;
/*stroke: steelblue;*/
stroke-width: 1.5px;
}
.point {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment