|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<title>SVG Swarm</title> |
|
<style> |
|
|
|
svg { |
|
position: absolute; |
|
top: 0; |
|
} |
|
|
|
use { |
|
fill:none; |
|
stroke:#000; |
|
stroke-width:2; |
|
} |
|
|
|
</style> |
|
<div id="fps">FPS: <span>?</span></div> |
|
<input type='checkbox' id='reverse' /><label for='reverse'>reverse</label> |
|
<script src="http://d3js.org/d3.v2.min.js?2.9.1"></script> |
|
<script> |
|
|
|
var data = []; |
|
for (var t = 0; t < 12; t += 0.1) { |
|
data.push([ |
|
Math.cos(t * 0.5), |
|
Math.sin(t) |
|
]); |
|
} |
|
|
|
var width = 960, |
|
height = 500; |
|
|
|
var x = d3.scale.linear() |
|
.domain([-2, 2]) |
|
.range([0, width]); |
|
|
|
var y = d3.scale.linear() |
|
.domain([-2, 2]) |
|
.range([0, height]); |
|
|
|
var time0 = Date.now(), |
|
time1; |
|
|
|
var fps = d3.select("#fps span"); |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
var defs = svg.append('defs'); |
|
|
|
var path = defs.selectAll('path') |
|
.data([data]) |
|
.enter() |
|
.append('path').attr('id', 'p') |
|
.attr("d", function(d) { |
|
return 'M' + d.map(function(a) { |
|
return [x(a[0]), y(a[1])]; |
|
}).join('L'); |
|
}); |
|
|
|
var p = svg.selectAll('use') |
|
.data([data]) |
|
.enter() |
|
.append("use").attr('xlink:href', '#p'); |
|
|
|
var arrow = svg.append('text'); |
|
var alength = arrow.text(' ► ►').node().getComputedTextLength() - arrow.text('►').node().getComputedTextLength(); |
|
arrow.remove(); |
|
|
|
var tp = svg.append("text").attr('dy', 7).append('textPath'); |
|
|
|
var fpsqueue = []; |
|
var forward = true; |
|
|
|
var z = 0.5; |
|
|
|
var rev = d3.select('#reverse'); |
|
|
|
d3.timer(function() { |
|
|
|
data = []; |
|
var n = 0; |
|
for (var t = 0; t < 12; t += 0.001, n++) { |
|
data[n] = [ |
|
Math.cos(t * z), |
|
Math.sin(t) |
|
]; |
|
} |
|
z += 0.002; |
|
if (z > 4) z = 0.5; |
|
|
|
if (rev.node().checked) data.reverse(); |
|
|
|
tp.attr('xlink:href', '#p').text(function() { |
|
return 'A'//(new Array(Math.floor(path.node().getTotalLength() / alength / 4) )).join(' ► '); |
|
}); |
|
|
|
path.data([data]).attr("d", function(d) { |
|
return 'M' + d.map(function(a) { |
|
return [x(a[0]), y(a[1])]; |
|
}).join('L'); |
|
}); |
|
|
|
time1 = Date.now(); |
|
if (fpsqueue.length === 200) { fps.text(d3.mean(fpsqueue).toFixed(3)); fpsqueue = []; } |
|
fpsqueue.push(Math.round(1000 / (time1 - time0))); |
|
time0 = time1; |
|
}); |
|
</script> |