Skip to content

Instantly share code, notes, and snippets.

@topologicallytony
Last active August 18, 2017 17:41
Show Gist options
  • Save topologicallytony/eb62c5d4b3961a0ed3a0d83046b645f1 to your computer and use it in GitHub Desktop.
Save topologicallytony/eb62c5d4b3961a0ed3a0d83046b645f1 to your computer and use it in GitHub Desktop.
Wave 8
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Wave 8</title>
<!-- D3.js -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<style type="text/css">
</style>
</head>
<body>
<div id=svgContainer></div>
<script type="text/javascript">
//Width and height of the visualization. Smaller numbers will zoom in, larger numbers zoom out
var w = 500;
var h = 500;
//padding creates a buffer of white space around the chart to make it a little easier to look at
var padding = 20;
//This will hold the sampled function's data
var dataset = [];
var curr_t = 0;
//How finely to partition interval
var numDataPoints = 500;
var numLinePoints = numDataPoints * 2;
//duration of a single transition in ms (for Sine this is the period)
var time = 1000;
//var time = numDataPoints * 1000;
//how fast will the frequency increase - another way to adjust time
var step = 1;
//initialize frequency of the function
var freq = 0;
//size of the circles, more data points should have smaller radii
var radius = 3;
//define y axis (domain of function)
//Note: if domain is 2pi then animation will reset after [numDataPoints] iterations
var y_min = -1 * Math.PI;
var y_max = 1 * Math.PI;
//define x axis domain (range of function)
//var x_min = 2;
//var x_max = -2;
var x_min = 2*Math.exp(y_max);
var x_max = -2 * Math.exp(y_max);
//Generate a random sample of the space
for (var i = 1; i <= numDataPoints; i++) {
//Partition interval
var curr_t = ((i * (y_max - y_min)) / (numDataPoints)) + y_min;
//determine function's value at current point
//var curr_x = Math.exp(curr_y / 2) * Math.sin(amp*curr_y);
//var curr_x = Math.exp(Math.abs(curr_y) - 5) * Math.sin(amp*curr_y);
var curr_x = Math.cos(curr_t);
var curr_y = Math.sin(curr_t);
dataset.push([curr_x, curr_y, curr_t]);
}
//Create x & y scales to convert points to proper svg canvas positions
var xScale = d3.scaleLinear()
.domain([-4, 4])
.range([padding, w + padding]);
var yScale = d3.scaleLinear()
.domain([-4, 4])
.range([h + padding, padding]);
//Define the format for the number
var format = d3.format(",.2f");
//Create a canvas to display the chart on
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Make the background of the canvas white
svg.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "#fff");
//Create group elements to layer the svg
//This is an easy way to make sure things you want on top are on top, and things you want behind stay behind
var layer1 = svg.append('g');
var layer2 = svg.append('g');
//'draw' the function using points sampled at a regular interval
function drawPts() {
var pts = layer2
.selectAll(".points")
.data(dataset);
pts
.enter()
.append("circle")
.attr("class", "points")
.attr("cy", function(d){ return yScale(d[1]); })
.attr("cx", function(d){ return xScale(d[0]); })
.attr("r", radius)
.attr("fill","steelblue");
pts
.transition()
.ease(d3.easeLinear)
.duration(time)
//transition the x position (aka the function value) from its current value to to its new value (the value after incrementing the frequency). The transition path is determined by linearly interpolating the amplitude of the sine function between the two points
.attrTween('cx', function(d,i){
return function(t) {
return xScale((Math.cos(d[2] * (freq + t * step)) + 2) * Math.cos(d[2]));
}
})
.attrTween('cy', function(d,i){
return function(t) {
return yScale((Math.cos(d[2] * (freq + t * step)) + 2 ) * Math.sin(d[2]));
}
});
}
//display a counter to show the current frequency of function
function counter(){
var freq_ctr = layer2.selectAll(".freq")
.data([0]);
freq_ctr
.transition()
.ease(d3.easeLinear)
.duration(time)
.on("start", function repeat() {
d3.active(this)
.tween("text", function() {
var that = d3.select(this),
i = d3.interpolateNumber(freq, freq + step);
return function(t) { that.text(format(i(t))); };
});
});
freq_ctr.enter().append("text")
.attr("x", 2 * padding)
.attr("y", 2 * padding)
.text(freq)
.attr("font-size", "12px")
.attr("class", "freq")
.transition()
.ease(d3.easeLinear)
.duration(time)
.on("start", function repeat() {
d3.active(this)
.tween("text", function() {
var that = d3.select(this),
i = d3.interpolateNumber(freq, freq + step);
return function(t) { that.text(format(i(t))); };
});
});
freq_ctr.exit().remove();
}
//initialize the animation
drawPts();
counter();
setInterval(function() {
freq = freq + step;
drawPts();
counter();
}, time);
drawPts();
counter();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment