Create a gist now

Instantly share code, notes, and snippets.

Slander
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link rel="stylesheet" type="text/css" href="main.css"/>
<body>
</body>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js" charset="utf-8"></script>
<script src="//cdn.rawgit.com/gka/d3-jetpack/master/d3-jetpack.js" charset="utf-8"></script>
<script src="main.js" charset="utf-8"></script>
</html>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0em;
}
svg {
width: 100%;
height: 100%;
overflow: visible;
}
path.spine {
fill: none;
stroke: black;
stroke-width: 10;
/*opacity: 0;*/
}
// cf http://bl.ocks.org/mbostock/3916621
var spinePaths = [
'M135.3,80.2c0,0-6.7-34-40-34s-41.3,16-42,34c-0.7,18,21,25,45,29s41.3,12.3,41.3,36.7s-24.3,33.1-43.2,33.1s-48.8-10.4-48.8-41.7',
'M164,46.2v129.7h78.3',
'M356.3,178.9L304.5,48.2l-51.8,129',
'M270.9,130.7h66.3',
'M467.4,48.2v127.7l-92-127.7v130.7',
'M498.4,48.2v127.7h48.2c0,0,48.2,2.6,48.2-63.3s-48.2-64.4-48.2-64.4H498.4z',
'M703.3,48.2h-84v127.7h84',
'M619.3,111h78.2',
'M727.5,115.3l51.8-0.2c0,0,33.1,0.1,33.1-33.1s-32.2-33.8-32.2-33.8h-52.7v130.7',
'M780,115.1l36.5,63.8'
];
var mouse = [0,0];
var svg = d3.select('body').append('svg')
.on('mousemove', function() { mouse = d3.mouse(this); });
var spines = svg.selectAll('path.spine')
.data(spinePaths)
.enter()
.append('path.spine')
.attr('d', ƒ())
.each(function(d) {
var pathSamples = samplePath(this,7,10); // for spiky
// var pathSamples = samplePath(this,25,20); // for blobby
var datum = {
'spine': this,
'samples': pathSamples
}
svg.append('path.spiky')
.datum(datum);
});
var spikys = svg.selectAll('path.spiky');
var spineShrink = d3.scale.linear()
.domain([ 0, 1e3, 2e3, 4e3 ])
.range([ 10, 10, 2, 0 ])
.clamp(true);
var spikeGrow = d3.scale.linear()
.domain([ 1e3, 2e3, 7e3, 8e3 ])
.range([ 0, 30, 60, 300 ])
.clamp(true);
var squareWave = makeSquareWave(2, 2e-4, 15);
// // spiky
d3.timer(function(t) {
spines.style('stroke-width', spineShrink(t));
spikys.attr('d', function(d) {
// w/ square wave oscillation: spikeGrow(t) + (.3 * spikeGrow(t) * (squareWave(t)+2))
return getSpikyPath(d.samples, mouse, spikeGrow(t) );
});
});
// blobby
// d3.timer(function(t) {
// spines.style('stroke-width', 0);
// spikys.attr('d', function(d) {
// return getBlobbyPath(d.samples, mouse, squareWave(t));
// });
// });
function samplePath(path, precision, jiggle) {
var sampleJiggle = jiggle || 0;
var samplePrecision = precision || 5;
var totalLength = path.getTotalLength();
var samples = totalLength / samplePrecision;
var distances = d3.range(samples).map(function(d) {
var randomJiggleOffset = (sampleJiggle / totalLength) * (Math.random()-0.5);
return (d===0) ? 0 : Math.max(Math.min((d / samples) + randomJiggleOffset, 1),0);
});
distances.push(1);
return distances.map(function(d,i) {
var pt = path.getPointAtLength(d * totalLength);
return [pt.x, pt.y];
});
}
function getSpikyPath(spinePoints, origin, magnitude) {
var axisOrigin = origin || [0,0];
var axisMagnitude = magnitude || 0;
var offsetPoints = spinePoints.slice(0).map(function(pt,i) {
// an additional degree of irregularity! amplitudinal irregularity, just based on sample index
var amplitudinalJiggle = 2; // the lower, the bigger
var mag = axisMagnitude + (axisMagnitude/amplitudinalJiggle) * Math.sin(i);
var axis = [axisOrigin[0] - pt[0], axisOrigin[1] - pt[1]];
var axisNorm = distance([0,0], axis);
var normalizedAxis = axis.map(function(d,i) { return (d / axisNorm) * mag; });
var direction = (i % 2 == 0) ? 1 : -1;
return [pt[0] + direction * normalizedAxis[0], pt[1] + direction * normalizedAxis[1]];
})
var points = spinePoints.concat(offsetPoints.reverse());
return "M" + points.join("L");
}
function getBlobbyPath(spinePoints, origin, magnitude) {
var axisOrigin = origin || [0,0];
var axisMagnitude = magnitude || 0;
var line = d3.svg.line().interpolate('basis');
var offsetPoints = spinePoints.slice(0).map(function(pt,i) {
var axis = [axisOrigin[0] - pt[0], axisOrigin[1] - pt[1]];
var axisNorm = distance([0,0], axis);
var normalizedAxis = axis.map(function(d,i) { return (d / axisNorm) * magnitude; });
var direction = (i % 2 == 0) ? 1 : -1;
return [
pt[0] + normalizedAxis[0] + direction * normalizedAxis[0],
pt[1] + normalizedAxis[1] + direction * normalizedAxis[1]
];
})
var offsetPoints2 = spinePoints.slice(0).map(function(pt,i) {
var axis = [axisOrigin[0] - pt[0], axisOrigin[1] - pt[1]];
var axisNorm = distance([0,0], axis);
var normalizedAxis = axis.map(function(d,i) { return (d / axisNorm) * magnitude; });
var direction = (i % 2 == 0) ? -1 : 1;
return [
pt[0] - normalizedAxis[0] - direction * normalizedAxis[0],
pt[1] - normalizedAxis[1] - direction * normalizedAxis[1]
];
})
var points = offsetPoints.concat(offsetPoints2.reverse());
return line(points) +'Z';
}
function distance(a,b) {
var x = b[0] - a[0];
var y = b[1] - a[1];
return Math.sqrt(Math.pow(x,2) + Math.pow(y,2));
}
// https://en.wikipedia.org/wiki/Square_wave
function makeSquareWave(numberOfTerms, frequency, amplitude) {
return function(t) {
var terms = d3.range(numberOfTerms).map(function(i) {
var k = i + 1; //1-indexed
return Math.sin( 2 * Math.PI * (2 * k - 1) * frequency * t ) / (2 * k - 1)
})
return amplitude * 4/Math.PI * d3.sum(terms);
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment