"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)"); }