Skip to content

Instantly share code, notes, and snippets.

@lloydroc
Last active March 19, 2018 04:40
Show Gist options
  • Select an option

  • Save lloydroc/c615008f180ca98ff417d40f6bd4cc08 to your computer and use it in GitHub Desktop.

Select an option

Save lloydroc/c615008f180ca98ff417d40f6bd4cc08 to your computer and use it in GitHub Desktop.
D3 Line Chart Sound Pressure
<html>
<head>
<meta charset="utf-8">
</head>
<style>
.peak-line {
fill: none;
stroke-width: 1;
stroke: red;
stroke-dasharray: 2,2;
}
.peak-line-label {
font-size: 8pt;
stroke: red;
}
.paths {
fill: none;
stroke-width: 2;
stroke: blue;
}
.paths-selected {
fill: none;
stroke-width: 4;
stroke: blue;
}
.points {
fill: blue;
}
.point-selected {
fill: blue;
}
.point-callout {
fill: grey;
}
.text-callout {
font-size: 8pt;
}
</style>
<body>
<svg width="900" height="300" id="timeseries"></svg>
</body>
<script src="https://d3js.org/d3.v5.js"></script>
<script>
var values = [],
endTime = Date.now(),
startTime = endTime - 24*30*60*60*1000,
n = 50;
step = (endTime-startTime)/n;
for(var i=0;i<n;i++) {
values.push({ t: i*step+startTime, y: Math.random()*120});
}
drawSvg(startTime,endTime,values);
function drawSvg(startTime,endTime,data) {
var svg = d3.select("#timeseries"),
margin = {top: 20, right: 20, bottom: 20, left: 20},
width = svg.attr('width')-margin.left-margin.right,
height = svg.attr('height')-margin.top-margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleTime()
.domain([startTime, endTime])
.range([0, width])
.nice();
var y = d3.scaleTime()
.domain([0, 150])
.range([height,0])
.nice();
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + y(0) + ")")
.call(d3.axisBottom(x));
var line = d3.line()
.x(function(d) { return x(d.t); })
.y(function(d) { return y(d.y); })
.curve(d3.curveCatmullRom.alpha(0.5));
var lineZero = d3.line()
.x(function(d) { return x(d.t); })
.y(function(d) { return y(0); })
.curve(d3.curveCatmullRom.alpha(0.5));
var t = d3.transition()
.duration(2000)
.ease(d3.easeElasticOut);
var peakLineData = [{t: startTime, y: 140},{t: endTime, y: 140}];
var peakLine = g.append('g').selectAll('peakLine').data(peakLineData);
peakLine.enter().append('path').classed('peak-line',true).attr('d',line(peakLineData));
var peakLineText = g.append('text')
.text('Peak Sound Pressure 140dB')
.attr('x',x(endTime)-120)
.attr('y',y(142))
.classed('peak-line-label',true);
var paths = g.append('g').selectAll('paths').data(data);
paths.enter().append('path')
.classed('paths',true)
.on('mouseover', function(d) {
d3.select(this).classed('paths-selected',true);
var thisColor = d3.select(this).attr('stroke');
})
.on('mouseout', function(d) {
d3.select(this).classed('paths',true);
})
.attr('d',lineZero(data))
.transition(t)
.attr('d',line(data))
var points = g.append('g').selectAll('points').data(data);
points.enter().append('circle')
.attr('r',4)
.attr('cx',function(d) { return x(d.t)})
.attr('cy',function(d) { return y(0)})
.attr('class','points')
.on('mouseover', function(d) {
d3.select(this).attr('class','point-selected').attr('r',6);
var thisColor = d3.select(this).attr('stroke');
var callout = g.append('g').classed('callout',true)
function smartLabelX(d) {
var xv = x(d.t)-110;
if(xv < 0) return 0;
if(xv+220>x(endTime)) return x(endTime)-220;
return xv;
}
var calloutRect = callout.selectAll('point-callout').data([d])
calloutRect.enter()
.append('rect')
.attr('width',220)
.attr('height',50)
.attr('x',smartLabelX)
.attr('y',function(d) { return y(d.y)-60})
.attr('rx',5)
.attr('ry',5)
.classed('point-callout',true);
var triData = [
{x: x(d.t)-9, y: y(d.y)-10},
{x: x(d.t)+0, y: y(d.y)},
{x: x(d.t)+9, y: y(d.y)-10}
];
var triLine = d3.line()
.x(function(d) { ;return d.x; })
.y(function(d) { return d.y; });
var calloutTri = callout.selectAll('point-callout-tri').data(triData)
calloutTri.enter()
.append('path')
.attr('d',triLine(triData))
.classed('point-callout',true);
function createCalloutText(d,i) {
return i==0 ? new Date(d.t) : parseFloat(d.y).toFixed(1)+'dB';
}
var calloutText = callout.selectAll('text-callout').data([d,d]).enter()
.append('text')
.attr("x",function(d,i) { return i==0 ? smartLabelX(d)+10 : Math.min(x(d.t)-20,x(endTime)-100)})
.attr("y",function(d,i) { return i==0 ? y(d.y)-40 : y(d.y) - 20})
.text(createCalloutText)
.classed('text-callout',function(d,i) { return i==0 ? true : false})
})
.on('mouseout', function(d) {
d3.select(this).attr('class','points').attr('r',4);
g.selectAll('.callout').remove();
})
.transition(t)
.attr('cx',function(d) { return x(d.t)})
.attr('cy',function(d) { return y(d.y)})
}
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment