Inspired by an exhibit at the Exploratorium
Last active
November 8, 2015 20:05
-
-
Save zanarmstrong/c9bb2842647140265d57 to your computer and use it in GitHub Desktop.
adding waves
This file contains 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
body { | |
background-color: #393939; | |
font-family: 'Raleway', sans-serif; | |
} | |
.area { | |
fill: lightsteelblue; | |
stroke-width: 0; | |
} | |
rect { | |
stroke-width: .4px; | |
stroke: #393939; | |
} | |
.topLine { | |
fill: red; | |
} | |
.mainWave { | |
fill: white; | |
} | |
.mainWaveHighlight { | |
fill: gray; | |
} | |
svg { | |
shape-rendering:"crisp-edges"; | |
} | |
/* slider stuff */ | |
.axis { | |
fill: gray; | |
-webkit-user-select: none; | |
-moz-user-select: none; | |
user-select: none; | |
} | |
.slider { | |
width: 50px; | |
} | |
.slider .handle .mainVertical { | |
stroke-width: 3px; | |
stroke-linecap: round; | |
stroke: white; | |
} | |
.slider .handle .halo { | |
stroke-width: 50px; | |
stroke-linecap: round; | |
opacity: 0; | |
} | |
.slider .handle text { | |
text-align: center; | |
font-size: 14px; | |
fill: white; | |
} |
This file contains 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
"use strict"; | |
// parameters | |
if(window.innerWidth > 500){ | |
var margin = { | |
top: 50, | |
right: 50, | |
bottom: 50, | |
left: 50 | |
}; | |
} else { | |
var margin = { | |
top: 5, | |
right: 5, | |
bottom: 5, | |
left: 5 | |
}; | |
} | |
var width = window.innerWidth - margin.left - margin.right, | |
height = window.innerHeight - margin.bottom - margin.top; | |
// for graphing parameters | |
var amp = 50, | |
period = width/6, | |
verticalShift = 200, | |
numWaves = 3, | |
offShift = period * numWaves, | |
floor = amp + verticalShift, | |
constantHeightWave2 = 20, | |
capHeight = 2, | |
barWidth = 4; | |
// check for mobile | |
if(window.innerWidth < 500){ | |
barWidth = 1; | |
capHeight = 1; | |
} | |
/* set up major elements */ | |
var sineArea = d3.svg.area(); | |
// function for wave 1 | |
function sineY(d) { | |
return amp * Math.cos(((d) * 2 * Math.PI) / period) | |
}; | |
// function for wave 2 | |
function sineY2(d) { | |
return amp * Math.cos(((d + period / 2) * 2 * Math.PI) / period) | |
}; | |
// height from baseline for wave 1 | |
function sineYheight(d) { | |
return sineY(d) - amp; | |
} | |
// height to add to wave 2, based on wave 1 and if they overlap | |
function addWave(d) { | |
// check for overlap of waves, return 0 if not overlapping or return wave height | |
if (d + offShift > period * numWaves) { | |
return 0; | |
} else { | |
return (sineYheight(d + offShift)); | |
} | |
} | |
// define x, y0, and y1 for left wave | |
sineArea | |
.x(function(d) { | |
return d; | |
}) | |
.y0(function(d) { | |
return sineY(d) + verticalShift | |
}) | |
.y1(amp + verticalShift); | |
// standard svg intro | |
var svg = d3.select("body").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
// set up data to use with d3 | |
// wave 1 | |
var k1 = []; | |
for (var i = 0; i < period * numWaves; i++) { | |
k1.push(i) | |
} | |
// wave 2 | |
var k2 = []; | |
for (var i = 0; i < period * numWaves / barWidth; i++) { | |
k2.push(i * barWidth) | |
} | |
// x and y functions | |
var positionFunctions = { | |
x: function(d) { | |
return d + offShift - barWidth / 2 | |
}, | |
y: function(d) { | |
return verticalShift - sineY2(d) + addWave(d) - constantHeightWave2; | |
} | |
}; | |
function highlight() { | |
this.classList.toggle('mainWaveHighlight') | |
} | |
// set up function for rectangles | |
function drawRectBody(z) { | |
z | |
.attr("x", positionFunctions.x) | |
.attr("height", function(d) { | |
return amp + sineY2(d) + constantHeightWave2; | |
}) | |
.attr("y", positionFunctions.y) | |
.attr("width", barWidth) | |
.on("click", highlight) | |
.attr("class", 'mainWave'); | |
}; | |
function drawRectCap(z) { | |
z.attr("x", positionFunctions.x) | |
.attr("height", capHeight) | |
.attr("y", positionFunctions.y) | |
.attr("width", barWidth) | |
.attr('class', 'topLine'); | |
}; | |
function updateRects() { | |
d3.selectAll(".mainWave").data(k2) | |
.attr("x", positionFunctions.x) | |
.attr("y", positionFunctions.y) | |
d3.selectAll(".topLine").data(k2) | |
.attr("x", positionFunctions.x) | |
.attr("y", positionFunctions.y) | |
} | |
// set up brush | |
// sets scale for slider | |
var x = d3.scale.linear() | |
.domain([0, (period * numWaves)]) | |
.range([0, (period * numWaves)]) | |
.clamp(true); | |
// defines brush | |
var brush = d3.svg.brush() | |
.x(x) | |
.extent([offShift, offShift]) | |
.on("brush", brushed); | |
// axis for brushing | |
var brushAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom") | |
.tickFormat(function(d) { | |
return d; | |
}) | |
.tickSize(0) | |
.tickPadding(12) | |
.tickValues([]) | |
// start drawing | |
// draw wave 1 | |
var myPath = svg.append("path") | |
.datum(k1) | |
.attr("class", "area") | |
.attr("d", sineArea); | |
// draw wave 2 | |
drawRectBody(svg.append("g").selectAll(".mainWave") | |
.data(k2) | |
.enter() | |
.append('rect')) | |
drawRectCap(svg.append("g").selectAll(".topLine") | |
.data(k2) | |
.enter() | |
.append('rect')) | |
// add axis, for brush | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + (verticalShift + amp) + ")") | |
// inroduce axis | |
.call(brushAxis) | |
.select(".domain") | |
.select(function() { | |
return this.parentNode.appendChild(this.cloneNode(true)); | |
}); | |
// create slider to call "brush" | |
var slider = svg.append("g") | |
.attr("class", "slider") | |
.call(brush); | |
slider.selectAll(".extent,.resize") | |
.remove(); | |
// create handle for slider | |
var handle = slider.append("g") | |
.attr("class", "handle"); | |
handle.append("path") | |
.attr("transform", "translate(0," + verticalShift + ")") | |
.attr("d", "M 0 -115 V 130") | |
.attr("class", "mainVertical") | |
handle.append("path") | |
.attr("transform", "translate("+ (-20) +"," + verticalShift + ")") | |
.attr("d", "M 0 -115 V 130") | |
.attr("class", "halo") | |
handle.append('text') | |
.text("slide me") | |
.attr("transform", "translate(" + (-60) + " ," + (verticalShift - 105) + ")"); | |
slider | |
.call(brush.event) | |
// to do on brush | |
function brushed() { | |
var value = brush.extent()[0]; | |
if (d3.event.sourceEvent) { // not a programmatic event | |
value = x.invert(d3.mouse(this)[0]); | |
brush.extent([value, value]); | |
} | |
offShift = value; | |
updateRects(); | |
handle.attr("transform", "translate(" + x(value) + ",0)"); | |
} |
This file contains 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>Adding Waves</title> | |
<link href='http://fonts.googleapis.com/css?family=Raleway' rel='stylesheet' type='text/css'> | |
<!-- standard meyer reset --> | |
<link rel="stylesheet" href="http://meyerweb.com/eric/tools/css/reset/reset.css"> | |
<link rel="stylesheet" href="addingWaves.css"> | |
<!--[if lt IE 9]> | |
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> | |
<![endif]--> | |
</head> | |
<body> | |
<section id="wave1"> | |
</section> | |
<!-- call JS files --> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script src="addingWaves.js"></script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment