Last active
September 10, 2015 18:11
-
-
Save cool-Blue/23ca2f006b720c784fc2 to your computer and use it in GitHub Desktop.
SVG speed test
This file contains hidden or 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></title> | |
<style> | |
svg { | |
border: 1px solid rgba(0,0,0,0.5); | |
} | |
#results, #container { | |
display: inline-block; | |
margin: 15px; | |
} | |
p { | |
margin: 15px; | |
} | |
td { | |
border: 1px solid #bbb; | |
text-align: right; | |
} | |
.header { | |
font-weight: bold; | |
} | |
</style> | |
</head> | |
<body> | |
<p id="user-agent"></p> | |
<div id="container"></div> | |
<table id="results"> | |
<tr class="header"> | |
<td>Circles</td> | |
<td>FPS</td> | |
<td>repaint [ms]</td> | |
</tr> | |
</table> | |
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.1.2/tinycolor.min.js"></script> | |
<script src="https://gitcdn.xyz/repo/cool-Blue/d3-lib/master/filters/shadow.js"></script> | |
<div id="log1"></div> | |
<div id="log2"></div> | |
<script> | |
$(function (){ | |
/* global requestAnimationFrame, $, PIXI, canvg */ | |
window.requestAnimationFrame = (function() { | |
return window.requestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.mozRequestAnimationFrame || | |
window.oRequestAnimationFrame || | |
window.msRequestAnimationFrame || | |
function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) { | |
return window.setTimeout(callback, 1000/60); | |
}; | |
})(); | |
var tests = [250, 500, 750, 1000, 2000, 3000, 10000, 20000]; | |
var refTest = tests[0]; | |
var maxRadius = 30, | |
maxX = 680, | |
maxY = 400; | |
function addRecord(count) { | |
var results = d3.select("#results") | |
.append("tr").selectAll("td").data([d3.format(",f")(count),"",""]) | |
results.enter().append("td") | |
.text(function(d){return d}); | |
return function updateResults(time, steps) { | |
var repaint = time / steps; | |
results.datum([count, (1000 / repaint).toFixed(2), repaint.toFixed(2)]) | |
.text(function(d, i){return this.textContent || d[i]}); | |
} | |
} | |
// set up svg | |
var svg = d3.select("#container").append("svg") | |
.attr({width: maxX, height: maxY}) | |
.append("g"), | |
g = svg.append("g"), | |
bubble = Bubble(svg), | |
x = d3.scale.linear() | |
.range([0, maxX]) | |
.domain([maxX * 0.1, maxX * 0.9]), | |
y = d3.scale.linear() | |
.range([0, maxY]) | |
.domain([maxY * 0.1, maxY * 0.9]), | |
constraint = [ | |
[x.invert(0), y.invert(0)], | |
[x.invert(maxX), y.invert(0)], | |
[x.invert(maxX), y.invert(maxY)], | |
[x.invert(0), y.invert(maxY)] | |
]; | |
function test() { | |
var count, | |
maxSteps = 100, | |
steps = 0, | |
startTime, | |
circle, | |
v = 20; | |
if (tests.length > 0) { | |
count = tests.shift(); | |
} else { | |
return; | |
} | |
var r = Math.pow(1.1, -(count - refTest) / refTest) * (1 - 1/10) + 1/10, | |
updateResults = addRecord(count), | |
circles = g.selectAll("circle").data(d3.range(count).map( function(d) { | |
var species = Math.random(), rMax = maxRadius * r; | |
return { | |
x: x.invert(rMax + (maxX - rMax*2) * Math.random()), | |
y: y.invert(rMax + (maxY - rMax*2) * Math.random()), | |
r : rMax * (species + 0.25), | |
color: Math.round(species * 19), | |
vx: (Math.random() - 0.5) * v, | |
vy: (Math.random() - 0.5) * v, | |
index: d | |
}; | |
})); | |
circles.exit().remove(); | |
circles.enter().append("circle") | |
.on("mouseover", onMouseOver) | |
.on("mouseout", onMouseOut) | |
.call(d3.behavior.drag() | |
.on("dragstart", onDragStart) | |
.on("drag", onDragMove) | |
.on("dragend", onDragEnd)); | |
circles.attr("r", function(d){return d.r}) | |
.attr("transform", function(d){return "translate(" + [d.x, d.y] + ")"}) | |
.call(bubble.call); | |
svg.selectAll("path").data([constraint]) | |
.enter().append("path").attr("d", function(d){ | |
return d3.svg.line()(d) + "Z"; | |
}) | |
.style({fill: "none", stroke: "black", opacity: 0.3}); | |
// Start animation. | |
startTime = new Date().getTime(); | |
requestAnimationFrame(step); | |
function step() { | |
var time; | |
circles.attr("transform", function(c){ | |
if(!c.fixed) { | |
if(x(c.x) >= (maxX - c.r) || x(c.x) <= c.r) c.vx *= -1; | |
if(y(c.y) >= (maxY - c.r) || y(c.y) <= c.r) c.vy *= -1; | |
c.x += c.vx; | |
c.y += c.vy; | |
} | |
return "translate(" + [c.x, c.y] + ")"; | |
}); | |
if (steps < maxSteps) { | |
steps++; | |
requestAnimationFrame(step); | |
} else { | |
time = new Date().getTime() - startTime; | |
updateResults(time, maxSteps); | |
test(); | |
} | |
} | |
function onMouseOver(d) { | |
d.fixed |= 4; | |
console.log([myName(arguments), this.index].join(": ")) | |
d.x -= d.vx; | |
d.y -= d.vy; | |
d3.select(this).moveToFront(); | |
} | |
function onMouseOut(d) { | |
console.log(["\t", myName(arguments), this.index].join(": ")) | |
d.fixed &= ~4; | |
} | |
function onDragStart(d) { | |
console.log([myName(arguments), this.index].join(": ")) | |
// store a reference to the data | |
// the reason for this is because of multitouch | |
// we want to track the movement of this particular touch | |
d3.select(this).style("opacity", 0.5); | |
d.fixed |= 2; | |
} | |
function onDragEnd(d) { | |
console.log(["\t", myName(arguments), this.index].join(": ")) | |
d3.select(this).style("opacity", 1); | |
d.fixed &= ~6; | |
} | |
function onDragMove(d) { | |
if (d.fixed & 2) { | |
console.log([myName(arguments), this.index].join(": ")) | |
var newPosition = d3.mouse(svg.node()) || d3.touch(svg.node()); | |
d.x = newPosition[0]; | |
d.y = newPosition[1]; | |
} | |
} | |
} | |
$(function () { | |
$("#user-agent").text(navigator.userAgent); | |
test(); | |
}); | |
function Bubble(svg) { | |
var colors = d3.range(20).map(d3.scale.category10()).map(function(d) { | |
return filters.sphere(svg, d, 1) | |
}); | |
return { | |
call: function(selection) { | |
selection.style("fill", function(d) { | |
return colors[d.color] | |
}) | |
}, | |
map : function(d, i, data) { | |
d.fill = colors[~~(Math.random() * 20)]; | |
}, | |
fill: function(d) { | |
return d.fill | |
} | |
} | |
} | |
function myName(args) { | |
return /function\s+(\w*)\(/.exec(args.callee)[1]; | |
} | |
d3.selection.prototype.moveToFront = function() { | |
return this.each(function() { | |
this.parentNode.appendChild(this); | |
}); | |
} | |
}) | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment