Skip to content

Instantly share code, notes, and snippets.

@mugshepherd
Forked from SeanMGonzalez/DVDC Stream Graph
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mugshepherd/adbc8e8af6503ab9fdcd to your computer and use it in GitHub Desktop.
Save mugshepherd/adbc8e8af6503ab9fdcd to your computer and use it in GitHub Desktop.
<!-- <!-- <!-- <!-- <!-- <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>D3.js Demo</title>
<meta charset="utf-8">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="wrapper">
<!-- Title page -->
<h1>Introduction<br>to<br>Graphing<br>with<br>D3.js</h1>
<h3>Jan Milosh&nbsp;&nbsp;<a href="http://janmilosh.com">janmilosh.com</a></h3>
<p class="text-center">Clone the repo: <a href="https://github.com/janmilosh/d3js-presentation">github.com/janmilosh/d3js-presentation</a><br>
View online: <a href="http://janmilosh.github.io/d3js-presentation">janmilosh.github.io/d3js-presentation</a></p>
<!-- What is D3.js --><hr>
<h2>What is D3.js?</h2>
<p>D3.js <a href="http://d3js.org">(d3js.org)</a> stands for Data-Driven Documents, a JavaScript library for data visualization. It was created by Mike Bostock, based on his PhD studies in the Stanford University data visualization program. Mike now works at the New York Times who sponsors his open source work.</p>
<p>D3 was designed for more than just graphs and charts. It's also capable of presenting maps, networks, and ordered lists. <strong>It was created for the efficient manipulation of documents based on data.</strong></p>
<p>This demonstration will focus on creating a simple scatter plot.</p>
<h3>DOM and Data Binding</h3>
<p>D3 provides the ability to select DOM elements and bind data to them (any kind of element, including images and text).</p>
<p>The magic of D3 comes from the ability to use data and web page elements together. Elements can be selected and their appearance modified to reflect differences in the data.</p>
<p>Note: D3 makes use of web standards such as HTML5, CSS3, and SVG, so it is therefore designed for modern browsers. It also requires utf-8 encoding.</p>
<!-- Demo 1, Getting started --><hr>
<h2>Getting Started</h2>
<p>First include the d3.js file which can be downloaded from <a href="d3js.org">D3js.org</a>, or linked through a CDN. I'll be using the downloaded file.</p>
<p>My graph will be created with a script embedded in this html page. The d3.js file will be included before the graph script.</p>
<p>We will be using SVG elements to create our graph, so we need to create an SVG canvas to contain it.</p>
<p>Demo 1:</p>
<script src="js/d3.min.js"></script>
<svg id="demo-1" height="400" width="750" style="background: #222;"></svg>
<!-- Demo 2, Select, Append, and Chained Operators --><hr>
<h2>Select, Append, and Chained Operators</h2>
<p>D3 has a <code>select()</code> method for grabbing DOM elements. Once selected, you can apply operators to these elements. This method selects the first element of that type.</p>
<p>Operators can then be used to get or set items such as attributes, properties, styles, text, and html.</p>
<p>D3 methods can be chained with a syntax much like jQuery.</p>
<p>Each operator in the chain returns a selection and the next operator in the chain operates on that selection.</p>
<p>Notice that order matters, the last item is on top.</p>
<p>Demo 2:</p>
<div id="demo-2"></div>
<script>
var height = 400; //We need the height and width as variables for later
var width = 750;
var svgColor = '#222';
var svgSelection = d3.select('#demo-2') // select our div
.append('svg') // append the svg and define attributes and style
.attr('height', height)
.attr('width', width)
.style('background', svgColor);
svgSelection.append('circle') // do the same with a circle
.attr("cx", 380) // but append it to the svg
.attr("cy", 200)
.attr("r", 100)
.style("fill", "white");
svgSelection.append('circle') // and another circle
.attr("cx", 360) // order matters, last is on top
.attr("cy", 180)
.attr("r", 50)
.style("fill", "orange");
</script>
<!-- Demo 3, Binding Data to the SVG --><hr>
<h2>Binding Data to the SVG</h2>
<p>D3 can load data from a number of types of external resources. These include CSV, TSV, JSON, and XML. We just need to ultimately construct an array from the data. For now we'll use an array of JSON objects.</p>
<p>There are several methods required for for binding data points to our graph (I've chosen to represent the data with circles):</p>
<p><code>selectAll('circle')</code> - selects all circles in our SVG and returns an empty array if there aren't any yet.</p>
<p><code>data(dataArray)</code> - this joins an array of data to the current selection.</p>
<p><code>enter()</code> - joins the data to placeholders for the circles.</p>
<p><code>append('circle')</code> - appends the circles to the SVG.</p>
<p>Mike Bostock has a pretty good explanation of this in his article: <a href="http://bost.ocks.org/mike/join/">Thinking with Joins</a>.</p>
<p>Note that when we use a data array, we need to reference the data from an anonymous function.</p>
<p>Demo 3:</p>
<div id="demo-3"></div>
<script>
var dataArray = [ // Defines the new data, an array of objects
{x: 5, y: 10, color: 'red'},
{x: 8, y: 10, color: 'orange'},
{x: 9, y: 13, color: 'pink'},
{x: 16, y: 3, color: 'violet'},
{x: 6, y: 9, color: 'lightgreen'},
{x: 3, y: 4,color: 'yellow'},
{x: 12, y: 8,color: 'cyan'},
{x: 7, y: 5, color: 'lightblue'}
];
var height = 400;
var width = 750;
var svgColor = '#222';
var svgSelection = d3.select('#demo-3')
.append('svg')
.attr('height', height)
.attr('width', width)
.style('background', svgColor);
var dataPoints = svgSelection
.selectAll('circle') // selects all circles (whether they exist or not)
.data(dataArray) // joins the data to the current selection (all circles)
.enter() // joins the data to placeholders for the circles
.append('circle'); // appends the circles to the svg
var dataAttributes = dataPoints // defines the circle attributes
.attr('cx', function (d) { return d.x; }) // when data array is used,
.attr('cy', function(d) { return d.y; }) // reference it from an anonymous function
.attr('r', 95)
.attr('fill', function(d) { return d.color; });
</script>
<!-- Demo 4, Scaling our Data --><hr>
<h2>Scaling our Data</h2>
<p>We need to scale our data to fit the space available. D3 provides functions to help us do this. There are different scale types available, but for this example we'll use a linear scale, <code>d3.scale.linear()</code>. We need to specify a domain and range. The domain refers to the data and the range refers to the SVG space.</p>
<p>The origin of the SVG is in the upper left corner, but our graph origin will be in the lower left corner.</p>
<p>Demo 4:</p>
<div id="demo-4"></div>
<script>
var dataArray = [
{x: 5, y: 10, color: 'red'},
{x: 8, y: 10, color: 'orange'},
{x: 9, y: 13, color: 'pink'},
{x: 16, y: 3, color: 'violet'},
{x: 6, y: 9, color: 'lightgreen'},
{x: 3, y: 4,color: 'yellow'},
{x: 12, y: 8,color: 'cyan'},
{x: 7, y: 5, color: 'lightblue'}
];
var height = 400;
var width = 750;
var svgColor = '#222';
var xScale = d3.scale.linear() // adds xScale
.domain([4.7, 16]) // range of x data
.range([0, width]); // map x data to the svg
var yScale = d3.scale.linear() // adds yScale
.domain([0, 13]) // range of y data
.range([0,height]); // map y data to the svg
var svgSelection = d3.select('#demo-4')
.append('svg')
.attr('height', height)
.attr('width', width)
.style('background', svgColor);
var dataPoints = svgSelection
.selectAll('circle')
.data(dataArray)
.enter()
.append('circle');
var dataAttributes = dataPoints
.attr('cx', function (d) { return xScale(d.x); }) // scales the x values
.attr('cy', function(d) { return yScale(d.y); }) // scales the y values
.attr('r', 15)
.attr('fill', function(d) { return d.color; });
</script>
<!-- Demo 5, Make data scaling more dynamic --><hr>
<h2>Make Data Scaling More Dynamic</h2>
<p>So far we've hard-coded our domain, but it would be better to have D3 help us determine our domain by calculating the max and min for our data using the <code>d3.max()</code> and <code>d3.min()</code> methods.</p>
<p>Demo 5:</p>
<div id="demo-5"></div>
<script>
var dataArray = [
{x: 5, y: 10, color: 'red'},
{x: 8, y: 10, color: 'orange'},
{x: 9, y: 13, color: 'pink'},
{x: 16, y: 3, color: 'violet'},
{x: 6, y: 9, color: 'lightgreen'},
{x: 3, y: 4,color: 'yellow'},
{x: 12, y: 8,color: 'cyan'},
{x: 7, y: 5, color: 'lightblue'}
];
var height = 400;
var width = 750;
var svgColor = '#222';
var maxX = d3.max(dataArray, function(d) { return d.x; }); // Get the max and min
var minX = d3.min(dataArray, function(d) { return d.x; }); // values in the data
var maxY = d3.max(dataArray, function(d) { return d.y; });
var minY = d3.min(dataArray, function(d) { return d.y; });
var xScale = d3.scale.linear()
.domain([minX, maxX]) // Define the x domain by the max and min x values
.range([0, width]);
var yScale = d3.scale.linear()
.domain([minY, maxY]) // Define the y domain by the max and min y values
.range([height, 0]);
var svgSelection = d3.select('#demo-5')
.append('svg')
.attr('height', height)
.attr('width', width)
.style('background', svgColor);
var dataPoints = svgSelection
.selectAll('circle')
.data(dataArray)
.enter()
.append('circle');
var dataAttributes = dataPoints
.attr('cx', function (d) { return xScale(d.x); })
.attr('cy', function(d) { return yScale(d.y); })
.attr('r', 15)
.attr('fill', function(d) { return d.color; });
</script>
<!-- Demo 6, Add Labels to the Data Points --><hr>
<h2>Add Labels to the Data Points</h2>
<p>We can use the SVG text element to add labels to our data points. The text is appended just like the other elements. We add it last so it's on top. The position is offset slightly, otherwise it would be on top of our circles.</p>
<p>Demo 6:</p>
<div id="demo-6"></div>
<script>
var dataArray = [
{x: 5, y: 10, color: 'red'},
{x: 8, y: 10, color: 'orange'},
{x: 9, y: 13, color: 'pink'},
{x: 16, y: 3, color: 'violet'},
{x: 6, y: 9, color: 'lightgreen'},
{x: 3, y: 4,color: 'yellow'},
{x: 12, y: 8,color: 'cyan'},
{x: 7, y: 5, color: 'lightblue'}
];
var height = 400;
var width = 750;
var svgColor = '#222';
var maxX = d3.max(dataArray, function(d) { return d.x; });
var minX = d3.min(dataArray, function(d) { return d.x; });
var maxY = d3.max(dataArray, function(d) { return d.y; });
var minY = d3.min(dataArray, function(d) { return d.y; });
var xScale = d3.scale.linear()
.domain([minX, maxX])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([minY, maxY])
.range([height, 0]);
var svgSelection = d3.select('#demo-6')
.append('svg')
.attr('height', height)
.attr('width', width)
.style('background', svgColor);
var dataPoints = svgSelection
.selectAll('circle')
.data(dataArray)
.enter()
.append('circle');
var dataAttributes = dataPoints
.attr('cx', function (d) { return xScale(d.x); })
.attr('cy', function(d) { return yScale(d.y); })
.attr('r', function(d){return d.x>d.y ? d.x*9 : d.y*3})
.attr('fill', function(d) { return d.color });
var text = svgSelection
.selectAll('text') // The text is appended in the same manner as the circles
.data(dataArray)
.enter()
.append('text');
var dataLabels = text
.attr('x', function(d) { return xScale(d.x) + 15; }) // Add some x offset
.attr('y', function(d) { return yScale(d.y) - 15; }) // Add some y offset
.text( function (d) { return d.x * d.y; }) // The text string
.attr('font-family', 'helvetica')
.attr('font-size', '16px')
.attr('fill', function(d) { return 'white' });
// .attr('fill', function(d) { return d.color });
</script>
<!-- Demo 7, Add Some Margin --><hr>
<h2>Add Some Margin</h2>
<p>Our elements are hanging over the edge of our SVG, so we need some margin. This will also provide room for axes. We do this in a way that keeps our data normalized. </p>
<p>Demo 7:</p>
<div id="demo-7"></div>
<script>
var dataArray = [
{x: 5, y: 10, color: 'red'},
{x: 8, y: 10, color: 'orange'},
{x: 9, y: 13, color: 'pink'},
{x: 16, y: 3, color: 'violet'},
{x: 6, y: 9, color: 'lightgreen'},
{x: 3, y: 4,color: 'yellow'},
{x: 12, y: 8,color: 'cyan'},
{x: 7, y: 5, color: 'lightblue'}
];
var margin = {top: 50, right: 75, bottom: 50, left: 50}; //sets the margin values
var svgHeight = 400; //new variable defines the outer SVG height
var svgWidth = 750; //new variable defines the outer SVG width
var height = svgHeight - margin.top - margin.bottom; //subtracts top and bottom margins
var width = svgWidth - margin.left - margin.right; //subtracts left and right margins
var svgColor = '#222';
var maxX = d3.max(dataArray, function(d) { return d.x; });
var minX = d3.min(dataArray, function(d) { return d.x; });
var maxY = d3.max(dataArray, function(d) { return d.y; });
var minY = d3.min(dataArray, function(d) { return d.y; });
var xScale = d3.scale.linear()
.domain([minX, maxX])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([minY, maxY])
.range([height, 0]);
var laura = d3.select('#demo-7')
.append('svg')
.style('background', svgColor) // Had to move this up as it needs to act on the svg, not the group
.attr('height', svgHeight) // Graph size plus margin
.attr('width', svgWidth); // Graph size plus margin
var svgSelection = laura.append('g') // This will append the group element
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')'); // Moves the group into position
// try inspect element in the browser to see this
var dataPoints = svgSelection
.selectAll('circle')
.data(dataArray)
.enter()
.append('circle');
var dataAttributes = dataPoints
.attr('cx', function (d) { return xScale(d.x); })
.attr('cy', function(d) { return yScale(d.y); })
.attr('r', 15)
.attr('fill', function(d) { return d.color });
var text = svgSelection
.selectAll('text')
.data(dataArray)
.enter()
.append('text');
var dataLabels = text
.attr('x', function(d) { return xScale(d.x) + 15; })
.attr('y', function(d) { return yScale(d.y) - 15; })
.text( function (d) { return d.x + ', ' + d.y; })
.attr('font-family', 'helvetica')
.attr('font-size', '16px')
.attr('fill', function(d) { return d.color });
laura.append('g')
.attr('transform', 'translate(' + String(width/2) + ',' + String(height/2) + ')')
.append('text')
.text("great Example!")
.attr('fill','white');
</script>
<!-- Demo 8, Add Axes --><hr>
<h2>Add Axes</h2>
<p>Next we'll add the x and y axes. We'll use the <code>axis()</code>, <code>scale()</code>, <code>orient()</code>, <code>ticks()</code>, and <code>call()</code> methods to create our axes.</p>
<p>Demo 8:</p>
<style type="text/css">
.axis path, .axis line {
fill: none;
stroke: white;
stroke-width: 1px;
shape-rendering: crispEdges;
}
.tick text,
text.title {
font-family: helvetica;
fill: white;
}
</style>
<div id="demo-8"></div>
<script>
var dataArray = [
{x: 5, y: 10, color: 'red'},
{x: 8, y: 10, color: 'orange'},
{x: 9, y: 13, color: 'pink'},
{x: 16, y: 3, color: 'violet'},
{x: 6, y: 9, color: 'lightgreen'},
{x: 3, y: 4,color: 'yellow'},
{x: 12, y: 8,color: 'cyan'},
{x: 7, y: 5, color: 'lightblue'},
{x: 3, y: 1,color: 'white'},
{x: 7, y: 2, color: 'blue'}
];
var margin = {top: 50, right: 75, bottom: 50, left: 50};
var svgHeight = 500;
var svgWidth = 750;
var height = svgHeight - margin.top - margin.bottom;
var width = svgWidth - margin.left - margin.right;
var svgColor = '#222';
var maxX = d3.max(dataArray, function(d) { return d.x; });
var minX = d3.min(dataArray, function(d) { return d.x; });
var maxY = d3.max(dataArray, function(d) { return d.y; });
var minY = d3.min(dataArray, function(d) { return d.y; });
var xScale = d3.scale.linear()
.domain([minX - 1, maxX + 1]) // -1 and +1 makes the graph a little bigger than our data
.range([0, width]);
var yScale = d3.scale.linear()
.domain([minY - 1, maxY + 1]) // -1 and +1 makes the graph a little bigger than our data
.range([height, 0]);
var svgSelection = d3.select('#demo-8')
.append('svg')
.style('background', svgColor)
.attr('height', svgHeight)
.attr('width', svgWidth)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
var dataPoints = svgSelection
.selectAll('circle')
.data(dataArray)
.enter()
// .append('g')
.append('circle');
dataPoints.append("svg:title").text('WELCOME TO DVDC!');
var dataAttributes = dataPoints
.attr('cx', function (d) { return xScale(d.x); })
.attr('cy', function(d) { return yScale(d.y); })
.attr('r', 10)
.attr('fill', function(d) { return d.color })
.on('click',function(d){return console.log('Hey it worked!')});
var text = svgSelection
.selectAll('text')
.data(dataArray)
.enter()
.append('text');
var dataLabels = text
.attr('x', function(d) { return xScale(d.x) + 10; })
.attr('y', function(d) { return yScale(d.y) - 10; })
.text( function (d) { return d.x + ', ' + d.y; })
.attr('font-family', 'helvetica')
.attr('font-size', '16px')
.attr('fill', function(d) { return d.color });
var num_ticks = dataArray.length;
var xAxis = d3.svg.axis() //create a generic axis function
.scale(xScale) // pass in our scale
.orient('bottom') //we want the labels at the bottom
.ticks(11); //This is the approximate number, d3 will make the numbers nice
var yAxis = d3.svg.axis() //create a generic axis function
.scale(yScale) // pass in our scale
.orient('left') //we want the labels at the left
.ticks(num_ticks); //This is the approximate number, d3 will make the numbers nice
svgSelection.append('g') // use the group element for the x axis
.attr('class', 'axis') // add a class for styling
.attr('transform', 'translate(0, ' + (height-20) + ')') //translate in svg coordinates
.call(xAxis); // Run the axis function on the newly created and appended group
svgSelection.append('g') // use the group element for the y axis
.attr('class', 'axis') // same class again for styling
.call(yAxis); // Run the axis function on the newly created and appended group
</script>
<!-- Demo 9, Add Title and Axis Labels --><hr>
<h2>Add Title and Axis Labels</h2>
<p>The last elements that we'll add are the title and axis labels. These are simple text elements that are appended to the SVG and positioned using the height and margin variables. Some of the margins were increased to better accomodate the added text.</p>
<p>Demo 9:</p>
<style type="text/css">
.axis path, .axis line {
fill: none;
stroke: white;
stroke-width: 1px;
shape-rendering: crispEdges;
}
.tick text,
text.title,
text.label {
font-family: helvetica;
fill: white;
}
</style>
<div id="demo-9"></div>
<script>
var dataArray = [
{x: 5, y: 10, color: 'red'},
{x: 8, y: 10, color: 'orange'},
{x: 9, y: 13, color: 'pink'},
{x: 16, y: 3, color: 'violet'},
{x: 6, y: 9, color: 'lightgreen'},
{x: 3, y: 4,color: 'yellow'},
{x: 12, y: 8,color: 'cyan'},
{x: 7, y: 5, color: 'lightblue'}
];
var margin = {top: 75, right: 75, bottom: 75, left: 75};
var svgHeight = 500;
var svgWidth = 750;
var height = svgHeight - margin.top - margin.bottom;
var width = svgWidth - margin.left - margin.right;
var svgColor = '#222';
var maxX = d3.max(dataArray, function(d) { return d.x; });
var minX = d3.min(dataArray, function(d) { return d.x; });
var maxY = d3.max(dataArray, function(d) { return d.y; });
var minY = d3.min(dataArray, function(d) { return d.y; });
var xScale = d3.scale.linear()
.domain([minX - 1, maxX + 1])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([minY - 1, maxY + 1])
.range([height, 0]);
var svgSelection = d3.select('#demo-9')
.append('svg')
.style('background', svgColor)
.attr('height', svgHeight)
.attr('width', svgWidth)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
var dataPoints = svgSelection
.selectAll('circle')
.data(dataArray)
.enter()
.append('circle');
var dataAttributes = dataPoints
.attr('cx', function (d) { return xScale(d.x); })
.attr('cy', function(d) { return yScale(d.y); })
.attr('r', 10)
.attr('fill', function(d) { return d.color });
var text = svgSelection
.selectAll('text')
.data(dataArray)
.enter()
.append('text');
var dataLabels = text
.attr('x', function(d) { return xScale(d.x) + 10; })
.attr('y', function(d) { return yScale(d.y) - 10; })
.text( function (d) { return d.x + ', ' + d.y; })
.attr('font-family', 'helvetica')
.attr('font-size', '16px')
.attr('fill', function(d) { return d.color });
var xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom')
.ticks(8);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient('left')
.ticks(5);
svgSelection.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(0, ' + height + ')')
.call(xAxis);
svgSelection.append('g')
.attr('class', 'axis')
.call(yAxis);
svgSelection.append('text') // Add title, simply append and define text
.attr('class', 'title') // attributes and position
.attr('x', (width/2))
.attr('y', 0 - (margin.top/2))
.attr('text-anchor', 'middle')
.style('font-size', '20px')
.text('The Graph Title');
svgSelection.append('text') // Add x-axis label, similar to title
.attr('class', 'label')
.attr('x', (width/2))
.attr('y', height + margin.bottom/2)
.attr('dy', '16')
.attr('text-anchor', 'middle')
.style('font-size', '16px')
.text('x-axis data');
svgSelection.append('text') // Add y-axis label, similar to above, but with transform
.attr('class', 'label')
.attr('transform', 'rotate(-90)')
.attr('y', 0 - margin.left/2)
.attr('x', 0 - height/2)
.attr('dy', '-8')
.attr('text-anchor', 'middle')
.style('font-size', '16px')
.text('y-axis data');
</script>
<!-- References --><hr>
<h2>References</h2>
<p><a href="http://d3js.org">d3js.org</a> has an introduction, lots of examples, and documentation.</p>
<p>For an extensive list of tutorials, see <a href="https://github.com/mbostock/d3/wiki/Tutorials">https://github.com/mbostock/d3/wiki/Tutorials</a>.</p>
<p><a href="https://www.dashingd3js.com">www.dashingd3js.com</a> has a detailed tutorial (up to the point of adding axes).</p>
<p><a href="https://egghead.io/lessons/d3-margins">egghead.io</a> (pro) - good method for margins.</p>
<p><a href="http://www.d3noob.org/">www.d3noob.org</a> - good example for adding axis labels.</p>
<p><a href="http://chimera.labs.oreilly.com/books/1230000000345">Interactive Data Visualization for the Web</a> - O'Reilly book, free to read online.</p>
<p><a href="http://www.jeromecukier.net/blog/2011/08/11/d3-scales-and-color">http://www.jeromecukier.net/blog/2011/08/11/d3-scales-and-color</a> - a very detailed explanation of scales.</p>
</div>
</body>
</html> --> --> --> --> -->
<!DOCTYPE html>
<meta charset="utf-8">
<title>Streamgraph</title>
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: auto;
position: relative;
width: 960px;
}
button {
position: absolute;
right: 10px;
top: 10px;
}
</style>
<button onclick="transition()">Update</button>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var n = 20, // number of layers
m = 200, // number of samples per layer
stack = d3.layout.stack().offset("zero"),
layers0 = stack(d3.range(n).map(function() { return bumpLayer(m); })),
layers1 = stack(d3.range(n).map(function() { return bumpLayer(m); }));
var width = 960,
height = 500;
var x = d3.scale.linear()
.domain([0, m - 1])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, d3.max(layers0.concat(layers1), function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); })])
.range([0,height]);
var color = d3.scale.linear()
// .domain([0,n-1])
.range(["blue", "green"]);
var area = d3.svg.area()
.x(function(d) { return x(d.x); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.selectAll("path")
.data(layers0)
.enter().append("path")
.attr("d", area)
.style("fill", function(d,i) { return color(Math.random()); });
function transition() {
d3.selectAll("path")
.data(function() {
var d = layers1;
layers1 = layers0;
return layers0 = d;
})
.transition()
.duration(5000)
.attr("d", area);
}
// Inspired by Lee Byron's test data generator.
function bumpLayer(n) {
function bump(a) {
var x = 1 / (.1 + Math.random()),
y = 2 * Math.random() - .5,
z = 10 / (.1 + Math.random());
for (var i = 0; i < n; i++) {
var w = (i / n - y) * z;
a[i] += x * Math.exp(-w * w);
}
}
var a = [], i;
for (i = 0; i < n; ++i) a[i] = 0;
for (i = 0; i < 5; ++i) bump(a);
return a.map(function(d, i) { return {x: i, y: Math.max(0, d)}; });
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment