main.js
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,25,20);
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);
d3.timer(function(t) {
spines.style('stroke-width', 0);
spikys.attr('d', function(d, i) {
return getBlobbyPath(d.samples, mouse, squareWave(t - i * 200));
});
});
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) {
var amplitudinalJiggle = 2;
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));
}
function makeSquareWave(numberOfTerms, frequency, amplitude) {
return function(t) {
var terms = d3.range(numberOfTerms).map(function(i) {
var k = i + 1;
return Math.sin( 2 * Math.PI * (2 * k - 1) * frequency * t ) / (2 * k - 1)
})
return amplitude * 4/Math.PI * d3.sum(terms);
}
}
paths.svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="254px" height="373px" viewBox="0 0 254 373" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<title>Untitled</title>
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<path d="M192.957031,13.3476562 C118.351563,-6.1484375 67.6874998,-6.71875008 40.1914063,49 C12.6953125,104.71875 -29.3437414,149.187496 35.2304688,176.628906 C99.8046875,204.070314 162.765625,170.722656 162.765625,170.722656 C162.765625,170.722656 218.917967,124.47656 240.84375,169.636719 C262.769533,214.796877 256.210937,302.421875 218.652344,323.265625 C181.093752,344.109377 139.624997,408.289063 31.1054688,344.457031" id="Path-1" stroke="#979797" sketch:type="MSShapeGroup"></path>
</g>
</svg>
slanderspine.svg
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 863.3 224.4" enable-background="new 0 0 863.3 224.4" xml:space="preserve">
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M135.3,80.2c0,0-6.7-34-40-34s-41.3,16-42,34c-0.7,18,21,25,45,29
s41.3,12.3,41.3,36.7s-24.3,33.1-43.2,33.1s-48.8-10.4-48.8-41.7"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M164,46.2v129.7h78.3"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M356.3,178.9L304.5,48.2l-51.8,129"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M270.9,130.7h66.3"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M467.4,48.2v127.7l-92-127.7v130.7"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M498.4,48.2v127.7h48.2c0,0,48.2,2.6,48.2-63.3s-48.2-64.4-48.2-64.4
H498.4z"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M703.3,48.2h-84v127.7h84"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M619.3,111h78.2"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M727.5,115.3l51.8-0.2c0,0,33.1,0.1,33.1-33.1s-32.2-33.8-32.2-33.8
h-52.7v130.7"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M780,115.1l36.5,63.8"/>
</svg>