Skip to content

Instantly share code, notes, and snippets.

@jebeck
Last active August 29, 2015 14:02
Show Gist options
  • Save jebeck/a639c8d8fb6ad384a8e3 to your computer and use it in GitHub Desktop.
Save jebeck/a639c8d8fb6ad384a8e3 to your computer and use it in GitHub Desktop.
second verse...not same as the first

Constant-Update Scatterplot

The standard constant-updating scatterplot model, drawing many independent circles.

Seems to render slower than SVG circle line markers on a single transparent line, with the FPS dropping below ~40 at about 450 items.

Disclaimer: not (yet) a scientific study ;)

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<title>
Line Markers in D3
</title>
<script src='http://d3js.org/d3.v3.min.js' charset='utf-8'></script>
<style type='text/css'>
svg {
display: block;
margin: 0 auto;
}
.axis path, .axis line {
fill: none;
stroke: #594E4D;
shape-rendering: crispEdges;
}
.axis text {
fill: #594E4D;
font-family: sans-serif;
font-size: 14px;
font-weight: bold;
}
#lineGraph {
stroke: rgba(0,0,0,0);
stroke-width: 2;
fill: none;
marker-start: url(#circle);
marker-mid: url(#circle);
marker-end: url(#circle);
}
.circleMarker {
stroke: none;
opacity: 0.5;
fill: #BF6989;
}
.transient {
fill: #D9C7C7;
stroke: #97A676;
stroke-width: 5px;
}
</style>
</head>
<body>
<script type='text/javascript'>
var margin = {top: 20, right: 15, bottom: 20, left: 40};
var width = 555 - margin.left - margin.right;
var height = 440 - margin.top - margin.bottom;
var random = d3.random.normal(5, 2);
var data = [];
for (var i = 0; i < Math.floor(Math.random() * 101); i++) {
data.push(random());
}
function circles() {
var svg = d3.select('body')
.append('svg')
.attr({
'width': width + margin.left + margin.right,
'height': height + margin.top + margin.bottom
})
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
svg.append('clipPath')
.attr('id', 'activeGraphArea')
.append('rect')
.attr({
width: width,
height: height,
x: 0,
y: 0
});
svg.append('rect')
.attr({
width: width,
height: height,
x: 0,
y: 0,
fill: '#F8F8F8'
});
var xScale = d3.scale.linear().domain([0, data.length]).range([0, width]);
var xAxis = d3.svg.axis().scale(xScale).orient('bottom');
svg.append('g')
.attr({
'class': 'x axis',
'transform': 'translate(0,' + height + ')'
})
.call(xAxis);
var yScale = d3.scale.linear().domain([0, d3.max(data)]).range([height, 0]);
var yAxis = d3.svg.axis().scale(yScale).orient('left');
svg.append('g')
.attr({
'class': 'y axis'
})
.call(yAxis);
svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr({
cx: function(d, i) { return xScale(i); },
cy: function(d) { return yScale(d); },
r: 5,
'class': 'circleMarker',
'clip-path': 'url(#activeGraphArea)'
});
return function() {
xScale.domain([0, data.length]);
yScale.domain([0, d3.max(data)]);
xAxis.scale(xScale);
yAxis.scale(yScale);
svg.select('.x.axis').transition().call(xAxis);
svg.select('.y.axis').transition().call(yAxis);
var latest = data[data.length -1];
var circles = svg.selectAll('circle.circleMarker')
.data(data);
circles.transition()
.attr({
cx: function(d, i) { return xScale(i); },
cy: function(d) { return yScale(d); },
r: 5,
'class': 'circleMarker',
'clip-path': 'url(#activeGraphArea)'
});
circles.enter()
.append('circle')
.attr({
cx: function(d, i) { return xScale(i); },
cy: function(d) { return yScale(d); },
r: 5,
'class': 'circleMarker',
'clip-path': 'url(#activeGraphArea)'
});
svg.append('circle')
.attr({
cx: xScale(data.length - 1),
cy: yScale(latest),
r: 15,
'class': 'transient'
})
.transition()
.duration(1000)
.attr('r', 0)
.remove();
};
}
var addData = function() {
data.push(random());
update();
};
setInterval(addData, 25);
update = circles();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment