Created
August 18, 2017 17:29
-
-
Save topologicallytony/0b3f74d118e670409f26374a2ab5d58a to your computer and use it in GitHub Desktop.
Wave 6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Wave 6</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(2 * Math.PI + d[2]) + 2) * Math.cos(d[2] * (freq + t * step))); | |
} | |
}) | |
.attrTween('cy', function(d,i){ | |
return function(t) { | |
return yScale((Math.cos(2 * Math.PI + d[2]) + 2) * Math.sin(d[2] * (freq + t * step))); | |
} | |
}); | |
} | |
//display a counter to show the current amplitude of sine 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