Skip to content

Instantly share code, notes, and snippets.

@darosh
Last active March 20, 2020 13:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save darosh/a71ff1c9d6e163e2faea to your computer and use it in GitHub Desktop.
Save darosh/a71ff1c9d6e163e2faea to your computer and use it in GitHub Desktop.
Benchmark

Notes

  • inspired by pjanik’s blocks
  • animation frame and FPS calculation powered by d3.timer
  • 3D based frameworks are producing a lot of DOM elements in SVG renderers thanks to shape triangulation
  • some test have limited number of objects because of high memory needs or incomplete/reference implementation (triangles)
  • click run link or run single test in the table
  • path is using d3-path
  • stackgl based on this block

Change log

  • 2015-11-09 longer pause improved slightly webgl and two.js, minor fixes, updated Chrome sample result
  • 2015-11-08 added art.js
  • 2015-11-08 shorter test time and pause, disabled chart animation between tests, updated sample results, minor fixes
  • 2015-11-07 release

Sample results

Chrome

<iframe sandbox="allow-scripts allow-forms allow-same-origin allow-top-navigation" width="527px" height="673px" frameborder="0" style="border: none" src="http://bl.ocks.org/darosh/raw/a71ff1c9d6e163e2faea/?s=tl&r={art:{canvas:{circle:{60:60,240:60,720:60,1440:53,1920:43.8},rectangle:{60:60,240:60,720:59.5,1440:56.4,1920:49.7},rounded:{60:60,240:59.7,720:27.9,1440:13.8,1920:11.4},text:{60:60,240:60,720:60,1440:60,1920:59.3}},svg:{circle:{60:60,240:59.6,720:56.7,1440:36.4,1920:30},rectangle:{60:60,240:60,720:58.5,1440:39.5,1920:33.6},rounded:{60:60,240:59.4,720:33.7,1440:26.9,1920:19.7},text:{60:60,240:59.5,720:31.3,1440:20.3,1920:15.9}}},d3:{canvas:{circle:{60:60,240:60,720:59.6,1440:58.6,1920:52.2},rectangle:{60:60,240:60,720:60,1440:60,1920:60},rounded:{60:60,240:60,720:29.1,1440:15.5,1920:11.9},text:{60:60,240:60,720:60,1440:60,1920:60}},path:{circle:{60:60,240:59.3,720:42.9,1440:29.1,1920:23},rectangle:{60:60,240:60,720:56.4,1440:34.6,1920:28.4},rounded:{60:60,240:58.6,720:29.1,1440:14.3,1920:11.3}},svg:{circle:{60:60,240:60,720:34.1,1440:27.6,1920:21},rectangle:{60:60,240:60,720:35.7,1440:29.9,1920:23.5},rounded:{60:60,240:59.5,720:27.7,1440:15.4,1920:11.6},text:{60:60,240:59.6,720:35.7,1440:28.4,1920:22.6}}},pixi:{canvas:{circle:{60:60,240:60,720:60,1440:52.3,1920:44.1},rectangle:{60:60,240:60,720:60,1440:60,1920:60},rounded:{60:60,240:60,720:29.6,1440:15.5,1920:11.2},text:{60:60,240:60,720:60,1440:54.6,1920:41.4}},webgl:{circle:{60:60,240:60,720:56.2,1440:48.5,1920:31.2},rectangle:{60:60,240:60,720:60,1440:57.7,1920:32},rounded:{60:60,240:60,720:60,1440:48.4,1920:31.6},text:{60:60,240:60,720:60,1440:60,1920:56.2}}},stackgl:{webgl:{circle:{60:60,240:60,720:60,1440:60,1920:60},rectangle:{60:60,240:60,720:60,1440:60,1920:60},text:{60:60,240:60,720:60,1440:60,1920:60}}},three:{canvas:{circle:{60:59.3,240:27.3,720:10.7,1440:4.3,1920:2.8},rectangle:{60:60,240:59.6,720:55.5,1440:37.5,1920:28.4}},css:{circle:{60:60,240:59.2,720:36.4,1440:18.8,1920:14.1},rectangle:{60:60,240:59.7,720:36.6,1440:19,1920:13.8},rounded:{60:60,240:60,720:34.5,1440:17.9,1920:13}},svg:{circle:{60:32.4},rectangle:{60:60,240:47.7}},webgl:{circle:{60:60,240:59.5,720:59.4,1440:57.9,1920:49.3},rectangle:{60:60,240:60,720:59.5,1440:53.8,1920:48.4}}},two:{canvas:{circle:{60:60,240:59.6,720:29.8},rectangle:{60:60,240:60,720:32.1},rounded:{60:59,240:31.5,720:12.9}},svg:{circle:{60:60,240:59.5,720:31.1},rectangle:{60:60,240:59.6,720:32.5},rounded:{60:59.4,240:36,720:21.7}},webgl:{circle:{60:60,240:59.6,720:48.4},rectangle:{60:60,240:59.8,720:34.4},rounded:{60:60,240:59.7,720:33.5}}}}"></iframe>

Firefox

<iframe sandbox="allow-scripts allow-forms allow-same-origin allow-top-navigation" width="527px" height="673px" frameborder="0" style="border: none" src="http://bl.ocks.org/darosh/raw/a71ff1c9d6e163e2faea/?s=tl&r={d3:{canvas:{circle:{60:60,240:60,720:60,1440:55.6,1920:41.4},rectangle:{60:60,240:60,720:60,1440:60,1920:60},rounded:{60:60,240:60,720:55,1440:30.2,1920:22.9},text:{60:60,240:58.4,720:30.1,1440:16.3,1920:12.4}},path:{circle:{60:60,240:60,720:32.5,1440:17.8,1920:14.1},rectangle:{60:60,240:60,720:33.6,1440:19.5,1920:15.2},rounded:{60:59.2,240:46.6,720:19.9,1440:10.2,1920:8.1}},svg:{circle:{60:60,240:60,720:41.9,1440:25.5,1920:20.4},rectangle:{60:60,240:60,720:57.8,1440:35.1,1920:29.5},rounded:{60:60,240:60,720:34,1440:18.9,1920:15.1},text:{60:60,240:51,720:23.7,1440:12.4,1920:10.4}}},pixi:{canvas:{circle:{60:60,240:60,720:60,1440:50.7,1920:39.1},rectangle:{60:60,240:60,720:60,1440:60,1920:60},rounded:{60:60,240:60,720:60,1440:32.3,1920:25.9},text:{60:60,240:60,720:60,1440:60,1920:59.2}},webgl:{circle:{60:60,240:60,720:60,1440:49.9,1920:42},rectangle:{60:60,240:60,720:60,1440:43.1,1920:34.1},rounded:{60:60,240:60,720:60,1440:51.7,1920:40.2},text:{60:60,240:60,720:60,1440:60,1920:48.2}}},stackgl:{webgl:{circle:{60:60,240:60,720:60,1440:60,1920:60},rectangle:{60:60,240:60,720:60,1440:60,1920:60},text:{60:60,240:60,720:60,1440:60,1920:59.9}}},three:{canvas:{circle:{60:59.2,240:26.6,720:9.1,1440:4.5,1920:3.8},rectangle:{60:60,240:60,720:60,1440:31.8,1920:19.8}},css:{circle:{60:60,240:53.4,720:18.1,1440:8.1,1920:6.2},rectangle:{60:60,240:60,720:19.8,1440:11.3,1920:8.8},rounded:{60:60,240:59.5,720:20.6,1440:8.4,1920:5.9}},svg:{circle:{60:10.8},rectangle:{60:50,240:18.5}},webgl:{circle:{60:60,240:60,720:58.5,1440:29.4,1920:23.3},rectangle:{60:60,240:60,720:53.8,1440:32.5,1920:20.6}}},two:{canvas:{circle:{60:60,240:53.2,720:19},rectangle:{60:60,240:60,720:23.6},rounded:{60:60,240:30.2,720:11}},svg:{circle:{60:59.2,240:55.4,720:20},rectangle:{60:59.2,240:54.6,720:20.1},rounded:{60:59.6,240:46,720:18.4}},webgl:{circle:{60:60,240:60,720:23},rectangle:{60:60,240:60,720:29.8},rounded:{60:60,240:60,720:23}}}}"></iframe>

Edge

<iframe sandbox="allow-scripts allow-forms allow-same-origin allow-top-navigation" width="536px" height="673px" frameborder="0" style="border: none" src="http://bl.ocks.org/darosh/raw/a71ff1c9d6e163e2faea/?s=tl&r={d3:{canvas:{circle:{60:59.9,240:59.9,720:55.6,1440:29.2,1920:22.2},rectangle:{60:60,240:60,720:60,1440:60,1920:59.9},rounded:{60:59.9,240:59.9,720:41.1,1440:20.2,1920:15.2},text:{60:59.9,240:59.9,720:57.4,1440:34.2,1920:26.8}},path:{circle:{60:59.9,240:59.6,720:28,1440:14.4,1920:11},rectangle:{60:59.9,240:59.8,720:43.5,1440:22.4,1920:17.3},rounded:{60:59.8,240:44.4,720:16.2,1440:8.2,1920:6.2}},svg:{circle:{60:59.9,240:59.8,720:55.6,1440:28.8,1920:21.3},rectangle:{60:59.9,240:59.8,720:59.5,1440:31.8,1920:23.1},rounded:{60:59.9,240:59.8,720:43.9,1440:22.3,1920:16.6},text:{60:59.8,240:59.5,720:24.9,1440:13.2,1920:9.7}}},pixi:{canvas:{circle:{60:59.9,240:59.9,720:46.8,1440:24.4,1920:18.5},rectangle:{60:60,240:59.9,720:59.9,1440:59.9,1920:59.9},rounded:{60:59.9,240:59.9,720:35.6,1440:18.6,1920:14.1},text:{60:60,240:60,720:60,1440:60,1920:58.6}},webgl:{circle:{60:60,240:60,720:60,1440:60,1920:45.8},rectangle:{60:60,240:59.9,720:59.9,1440:59.1,1920:46},rounded:{60:60,240:60,720:60,1440:58,1920:45.5},text:{60:60,240:60,720:60,1440:60,1920:59.1}}},stackgl:{webgl:{circle:{60:60,240:60,720:60,1440:60,1920:60},rectangle:{60:60,240:60,720:60,1440:60,1920:60},text:{60:60,240:60,720:60,1440:60,1920:60}}},three:{canvas:{circle:{60:41.3,240:6.5,720:2.2,1440:1.3,1920:1},rectangle:{60:58.3,240:41.1,720:14.4,1440:8.3,1920:5.6}},css:{circle:{60:59.6,240:22.5,720:8.5,1440:4.2,1920:2.9},rectangle:{60:59.6,240:37.9,720:13.2,1440:6.9,1920:4.9},rounded:{60:22.5,240:15.5,720:4.9,1440:2.5,1920:1.9}},svg:{circle:{60:4.5},rectangle:{60:32.7,240:8.8}},webgl:{circle:{60:59.9,240:54.7,720:22.6,1440:11.2,1920:8.3},rectangle:{60:58.4,240:49.4,720:20.1,1440:10.8,1920:7.6}}},two:{canvas:{circle:{60:59.8,240:30,720:11.3},rectangle:{60:59.8,240:39.5,720:13.7},rounded:{60:58.9,240:18.6,720:6.5}},svg:{circle:{60:59.8,240:28.4,720:9.9},rectangle:{60:59.1,240:32.6,720:12.4},rounded:{60:58.9,240:22.2,720:7.3}},webgl:{circle:{60:60,240:41.1,720:14.4},rectangle:{60:60,240:40.5,720:14.5},rounded:{60:60,240:41.4,720:14.2}}}}"></iframe>

Mobile Chrome

<iframe sandbox="allow-scripts allow-forms allow-same-origin allow-top-navigation" width="527px" height="673px" frameborder="0" style="border: none" src="http://bl.ocks.org/darosh/raw/a71ff1c9d6e163e2faea/?s=tl&r={d3:{canvas:{circle:{60:56.2,240:55,720:24.1,1440:12.9,1920:9.6},rectangle:{60:59.2,240:56.2,720:48.4,1440:38.9,1920:27.2},rounded:{60:59.4,240:21.3,720:8.2,1440:4.4,1920:3.5},text:{60:59.1,240:53.1,720:24.3,1440:13.6,1920:9.9}},path:{circle:{60:41,240:21,720:9.7,1440:5.3,1920:4.3},rectangle:{60:45.2,240:20.4,720:10.8,1440:6.1,1920:4.7},rounded:{60:28.4,240:13.5,720:5.5,1440:2.9,1920:2.3}},svg:{circle:{60:35,240:19,720:7.6,1440:4.1,1920:3.2},rectangle:{60:38.5,240:19.4,720:8.9,1440:4.8,1920:3.5},rounded:{60:24.9,240:7.5,720:4.8,1440:2.4,1920:1.9},text:{60:30,240:14.9,720:6,1440:3.4,1920:2.4}}},pixi:{canvas:{circle:{60:59.1,240:38,720:15.8,1440:8.3,1920:6.6},rectangle:{60:59.1,240:52.6,720:24.6,1440:15.2,1920:11.2},rounded:{60:52.2,240:17.6,720:7,1440:3.5,1920:2.7},text:{60:59,240:48.7,720:17.3,1440:8.1,1920:6.2}},webgl:{circle:{60:59.2,240:58.4,720:40.5,1440:21.1,1920:17.2},rectangle:{60:59.3,240:56.1,720:39.3,1440:22.1,1920:14.4},rounded:{60:58.4,240:58.4,720:42.6,1440:23.3,1920:10.1},text:{60:58.4,240:57.7,720:56.9,1440:28.1,1920:20}}},stackgl:{webgl:{circle:{60:56.8,240:57.6,720:38.5,1440:18.3,1920:13.5},rectangle:{60:57.6,240:57.6,720:39.1,1440:17.3,1920:13.3},text:{60:59.2,240:58.5,720:36.1,1440:16.3,1920:13.9}}},three:{canvas:{circle:{60:16.1,240:4.3,720:1.7,1440:0.6,1920:0.5},rectangle:{60:54.7,240:25.3,720:10.3,1440:5.2,1920:4.3}},css:{circle:{60:48.5,240:15.9,720:6.1,1440:2.8,1920:null},rectangle:{60:51.8,240:16.1,720:5.8,1440:3.2,1920:null},rounded:{60:49.2,240:17.1,720:5.5,1440:null,1920:null}},svg:{circle:{60:4.7},rectangle:{60:19.9,240:7.9}},webgl:{circle:{60:54.2,240:38.9,720:21.5,1440:11.4,1920:6.3},rectangle:{60:54.1,240:42.2,720:16.2,1440:9.4,1920:7.7}}},two:{canvas:{circle:{60:39.5,240:13,720:4.9},rectangle:{60:50.3,240:14.5,720:5.8},rounded:{60:23.1,240:6.8,720:2.6}},svg:{circle:{60:21.5,240:9.6,720:4.5},rectangle:{60:22,240:11.2,720:4.8},rounded:{60:17.4,240:1.5,720:3.1}},webgl:{circle:{60:53.9,240:18.7,720:7.9},rectangle:{60:57,240:19.8,720:7},rounded:{60:53.8,240:19.5,720:7.1}}}}"></iframe>
function BenchArtCircles(container, width, height, data, params) {
var self, objects, surface, art;
return self = {
init: function () {
if (params.renderer === 'canvas') {
var canvas = params.cache('2d-alpha');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
canvas.getContext('2d', {alpha: true});
art = ArtCanvas;
surface = art.Surface(width, height, canvas);
surface._valid = false;
} else {
art = ArtSvg;
surface = art.Surface(width, height);
surface.inject(container.node());
}
objects = [];
for (var i = 0; i < data.length; i++) {
var c = data[i];
var o = art.Ellipse(c.radius * 2, c.radius * 2)
.fill(c.fillRgba)
.inject(surface);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
objects[i].moveTo(data[i].x, data[i].y);
}
if(params.renderer === 'canvas') {
surface.render();
}
},
destroy: function () {
}
};
}
BenchArtCircles.framework = 'art';
BenchArtCircles.version = ArtCanvas.version;
BenchArtCircles.object = 'circle';
BenchArtCircles.renderers = ['canvas', 'svg'];
Bench.list.push(BenchArtCircles);
function BenchArtRectangles(container, width, height, data, params) {
var self, objects, surface, art;
return self = {
init: function () {
if (params.renderer === 'canvas') {
var canvas = params.cache('2d-alpha');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
canvas.getContext('2d', {alpha: true});
art = ArtCanvas;
surface = art.Surface(width, height, canvas);
surface._valid = false;
} else {
art = ArtSvg;
surface = art.Surface(width, height);
surface.inject(container.node());
}
objects = [];
for (var i = 0; i < data.length; i++) {
var c = data[i];
var o = art.Rectangle(c.w, c.h)
.fill(c.fillRgba)
.inject(surface);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
objects[i].moveTo(data[i].x, data[i].y);
}
if(params.renderer === 'canvas') {
surface.render();
}
},
destroy: function () {
}
};
}
BenchArtRectangles.version = ArtCanvas.version;
BenchArtRectangles.framework = 'art';
BenchArtRectangles.object = 'rectangle';
BenchArtRectangles.renderers = ['canvas', 'svg'];
Bench.list.push(BenchArtRectangles);
function BenchArtRounded(container, width, height, data, params) {
var self, objects, surface, art;
return self = {
init: function () {
if (params.renderer === 'canvas') {
var canvas = params.cache('2d-alpha');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
canvas.getContext('2d', {alpha: true});
art = ArtCanvas;
surface = art.Surface(width, height, canvas);
surface._valid = false;
} else {
art = ArtSvg;
surface = art.Surface(width, height);
surface.inject(container.node());
}
objects = [];
for (var i = 0; i < data.length; i++) {
var c = data[i];
var o = art.Rectangle(c.w, c.h, c.cornerRadius)
.fill(c.fillRgba)
.stroke(c.strokeRgba, c.lineWidth)
.inject(surface);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
objects[i].moveTo(data[i].x, data[i].y);
}
if(params.renderer === 'canvas') {
surface.render();
}
},
destroy: function () {
}
};
}
BenchArtRounded.version = ArtCanvas.version;
BenchArtRounded.framework = 'art';
BenchArtRounded.object = 'rounded';
BenchArtRounded.renderers = ['canvas', 'svg'];
Bench.list.push(BenchArtRounded);
function BenchArtText(container, width, height, data, params) {
var self, objects, surface, art;
return self = {
init: function () {
if (params.renderer === 'canvas') {
var canvas = params.cache('2d-alpha');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
canvas.getContext('2d', {alpha: true});
art = ArtCanvas;
surface = art.Surface(width, height, canvas);
surface._valid = false;
} else {
art = ArtSvg;
surface = art.Surface(width, height);
surface.inject(container.node());
}
objects = [];
for (var i = 0; i < data.length; i++) {
var c = data[i];
var o = art.Text(c.text, c.textSize + 'px ' + c.fontFamily)
.fill(c.fillRgba)
.inject(surface);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
objects[i].moveTo(data[i].x, data[i].y);
}
if(params.renderer === 'canvas') {
surface.render();
}
},
destroy: function () {
}
};
}
BenchArtText.version = ArtCanvas.version;
BenchArtText.framework = 'art';
BenchArtText.object = 'text';
BenchArtText.renderers = ['canvas', 'svg'];
Bench.list.push(BenchArtText);
function BenchD3CanvasCircles(container, width, height, data, params) {
var self, ctx;
return self = {
init: function () {
var canvas = params.cache('2d');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
ctx = canvas.getContext('2d', {alpha: false});
self.update();
},
update: function () {
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, width, height);
for (var i = 0; i < data.length; i++) {
var c = data[i];
ctx.beginPath();
ctx.arc(c.x, c.y, c.radius, 0, 2 * Math.PI);
ctx.closePath();
ctx.fillStyle = c.fillRgba;
ctx.fill();
}
},
destroy: function () {
ctx = null;
}
};
}
BenchD3CanvasCircles.version = d3.version;
BenchD3CanvasCircles.framework = 'd3';
BenchD3CanvasCircles.object = 'circle';
BenchD3CanvasCircles.renderers = ['canvas'];
Bench.list.push(BenchD3CanvasCircles);
function BenchD3CanvasRectangles(container, width, height, data, params) {
var self, ctx;
return self = {
init: function () {
var canvas = params.cache('2d');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
ctx = canvas.getContext('2d', {alpha: false});
self.update();
},
update: function () {
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, width, height);
for (var i = 0; i < data.length; i++) {
var c = data[i];
ctx.fillStyle = c.fillRgba;
ctx.fillRect(c.x, c.y, c.w, c.h);
}
},
destroy: function () {
ctx = null;
}
};
}
BenchD3CanvasRectangles.version = d3.version;
BenchD3CanvasRectangles.framework = 'd3';
BenchD3CanvasRectangles.object = 'rectangle';
BenchD3CanvasRectangles.renderers = ['canvas'];
Bench.list.push(BenchD3CanvasRectangles);
function BenchD3CanvasRounded(container, width, height, data, params) {
var self, ctx;
return self = {
init: function () {
var canvas = params.cache('2d');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
ctx = canvas.getContext('2d', {alpha: false});
self.update();
},
update: function () {
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, width, height);
for (var i = 0; i < data.length; i++) {
var c = data[i];
ctx.beginPath();
ctx.moveTo(c.x + c.cornerRadius, c.y);
ctx.lineTo(c.x + c.w - c.cornerRadius, c.y);
ctx.quadraticCurveTo(c.x + c.w, c.y, c.x + c.w, c.y + c.cornerRadius);
ctx.lineTo(c.x + c.w, c.y + c.h - c.cornerRadius);
ctx.quadraticCurveTo(c.x + c.w, c.y + c.h, c.x + c.w - c.cornerRadius, c.y + c.h);
ctx.lineTo(c.x + c.cornerRadius, c.y + c.h);
ctx.quadraticCurveTo(c.x, c.y + c.h, c.x, c.y + c.h - c.cornerRadius);
ctx.lineTo(c.x, c.y + c.cornerRadius);
ctx.quadraticCurveTo(c.x, c.y, c.x + c.cornerRadius, c.y);
ctx.closePath();
ctx.fillStyle = c.fillRgba;
ctx.strokeStyle = c.strokeRgba;
ctx.lineWidth = c.lineWidth;
ctx.fill();
ctx.stroke();
}
},
destroy: function () {
ctx = null;
}
};
}
BenchD3CanvasRounded.version = d3.version;
BenchD3CanvasRounded.framework = 'd3';
BenchD3CanvasRounded.object = 'rounded';
BenchD3CanvasRounded.renderers = ['canvas'];
Bench.list.push(BenchD3CanvasRounded);
function BenchD3CanvasText(container, width, height, data, params) {
var self, ctx;
return self = {
init: function () {
var canvas = params.cache('2d');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
ctx = canvas.getContext('2d', {alpha: false});
self.update();
},
update: function () {
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, width, height);
for (var i = 0; i < data.length; i++) {
var c = data[i];
ctx.fillStyle = c.fillRgba;
ctx.font = c.textSize + 'px ' + c.fontFamily;
ctx.fillText(c.text, c.x, c.y);
}
},
destroy: function () {
ctx = null;
}
};
}
BenchD3CanvasText.version = d3.version;
BenchD3CanvasText.framework = 'd3';
BenchD3CanvasText.object = 'text';
BenchD3CanvasText.renderers = ['canvas'];
Bench.list.push(BenchD3CanvasText);
function BenchD3CanvasTriangles(container, width, height, data, params) {
var self, ctx;
return self = {
init: function () {
var canvas = params.cache('2d');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
ctx = canvas.getContext('2d', {alpha: false});
self.update();
},
update: function () {
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, width, height);
for (var i = 0; i < data.length; i++) {
var c = data[i];
ctx.beginPath();
ctx.moveTo(c.x + c.triangleSide / 2, c.y);
ctx.lineTo(c.x, c.y + c.triangleHeight);
ctx.lineTo(c.x + c.triangleSide, c.y + c.triangleHeight);
ctx.closePath();
ctx.fillStyle = c.fillRgba;
ctx.fill();
}
},
destroy: function () {
ctx = null;
}
};
}
BenchD3CanvasTriangles.version = d3.version;
BenchD3CanvasTriangles.framework = 'd3';
BenchD3CanvasTriangles.object = 'triangles';
BenchD3CanvasTriangles.renderers = ['canvas'];
BenchD3CanvasTriangles.limits = {canvas: -1};
Bench.list.push(BenchD3CanvasTriangles);
function BenchD3SvgCircles(container, width, height, data) {
var renderer, svg;
return {
init: function () {
svg = container.append('svg').attr({width: width, height: height});
renderer = svg.selectAll('circle').data(data);
renderer.enter().append('circle')
.attr('r', function (d) {
return d.radius;
})
.attr('fill', function (d) {
return d.fillRgba;
})
.attr('cx', function (d) {
return d.x;
})
.attr('cy', function (d) {
return d.y;
});
},
update: function () {
renderer.attr('cx', function (d) {
return d.x;
})
.attr('cy', function (d) {
return d.y;
});
},
destroy: function () {
renderer = null;
svg = null;
}
};
}
BenchD3SvgCircles.version = d3.version;
BenchD3SvgCircles.framework = 'd3';
BenchD3SvgCircles.object = 'circle';
BenchD3SvgCircles.renderers = ['svg'];
Bench.list.push(BenchD3SvgCircles);
function BenchD3SvgPathCircles(container, width, height, data) {
var renderer, svg;
return {
init: function () {
svg = container.append('svg').attr({width: width, height: height});
renderer = svg.selectAll('path').data(data);
renderer.enter().append('path')
.attr('fill', function (d) {
return d.fillRgba;
});
},
update: function () {
renderer.attr('d', function (c) {
var ctx = new Path();
ctx.arc(c.x, c.y, c.radius, 0, 2 * Math.PI);
ctx.closePath();
return ctx.toString();
});
},
destroy: function () {
renderer = null;
svg = null;
}
};
}
BenchD3SvgPathCircles.version = d3.version;
BenchD3SvgPathCircles.framework = 'd3';
BenchD3SvgPathCircles.object = 'circle';
BenchD3SvgPathCircles.renderers = ['path'];
Bench.list.push(BenchD3SvgPathCircles);
function BenchD3SvgPathRectangles(container, width, height, data) {
var renderer, svg;
return {
init: function () {
svg = container.append('svg').attr({width: width, height: height});
renderer = svg.selectAll('path').data(data);
renderer.enter().append('path')
.attr('fill', function (d) {
return d.fillRgba;
});
},
update: function () {
renderer.attr('d', function (c) {
var ctx = new Path();
ctx.moveTo(c.x, c.y);
ctx.lineTo(c.x + c.w, c.y);
ctx.lineTo(c.x + c.w, c.y + c.h);
ctx.lineTo(c.x, c.y + c.h);
ctx.closePath();
return ctx.toString();
});
},
destroy: function () {
renderer = null;
svg = null;
}
};
}
BenchD3SvgPathRectangles.version = d3.version;
BenchD3SvgPathRectangles.framework = 'd3';
BenchD3SvgPathRectangles.object = 'rectangle';
BenchD3SvgPathRectangles.renderers = ['path'];
Bench.list.push(BenchD3SvgPathRectangles);
function BenchD3SvgPathRounded(container, width, height, data) {
var renderer, svg;
return {
init: function () {
svg = container.append('svg').attr({width: width, height: height});
renderer = svg.selectAll('path').data(data);
renderer.enter().append('path')
.attr('fill', function (d) {
return d.fillRgba;
})
.attr('stroke', function (d) {
return d.strokeRgba;
})
.attr('stroke-width', function (d) {
return d.lineWidth;
});
},
update: function () {
renderer.attr('d', function (c) {
var ctx = new Path();
ctx.moveTo(c.x + c.cornerRadius, c.y);
ctx.lineTo(c.x + c.w - c.cornerRadius, c.y);
ctx.quadraticCurveTo(c.x + c.w, c.y, c.x + c.w, c.y + c.cornerRadius);
ctx.lineTo(c.x + c.w, c.y + c.h - c.cornerRadius);
ctx.quadraticCurveTo(c.x + c.w, c.y + c.h, c.x + c.w - c.cornerRadius, c.y + c.h);
ctx.lineTo(c.x + c.cornerRadius, c.y + c.h);
ctx.quadraticCurveTo(c.x, c.y + c.h, c.x, c.y + c.h - c.cornerRadius);
ctx.lineTo(c.x, c.y + c.cornerRadius);
ctx.quadraticCurveTo(c.x, c.y, c.x + c.cornerRadius, c.y);
ctx.closePath();
return ctx.toString();
});
},
destroy: function () {
renderer = null;
svg = null;
}
};
}
BenchD3SvgPathRounded.version = d3.version;
BenchD3SvgPathRounded.framework = 'd3';
BenchD3SvgPathRounded.object = 'rounded';
BenchD3SvgPathRounded.renderers = ['path'];
Bench.list.push(BenchD3SvgPathRounded);
function BenchD3SvgRectangles(container, width, height, data) {
var renderer, svg;
return {
init: function () {
svg = container.append('svg').attr({width: width, height: height});
renderer = svg.selectAll('rect').data(data);
renderer.enter().append('rect')
.attr('width', function (d) {
return d.w;
})
.attr('height', function (d) {
return d.h;
})
.attr('fill', function (d) {
return d.fillRgba;
})
.attr('x', function (d) {
return d.x;
})
.attr('y', function (d) {
return d.y;
});
},
update: function () {
renderer.attr('x', function (d) {
return d.x;
})
.attr('y', function (d) {
return d.y;
});
},
destroy: function () {
renderer = null;
svg = null;
}
};
}
BenchD3SvgRectangles.version = d3.version;
BenchD3SvgRectangles.framework = 'd3';
BenchD3SvgRectangles.object = 'rectangle';
BenchD3SvgRectangles.renderers = ['svg'];
Bench.list.push(BenchD3SvgRectangles);
function BenchD3SvgRounded(container, width, height, data) {
var renderer, svg;
return {
init: function () {
svg = container.append('svg').attr({width: width, height: height});
renderer = svg.selectAll('rect').data(data);
renderer.enter().append('rect')
.attr('width', function (d) {
return d.w;
})
.attr('height', function (d) {
return d.h;
})
.attr('rx', function (d) {
return d.cornerRadius;
})
.attr('ry', function (d) {
return d.cornerRadius;
})
.attr('fill', function (d) {
return d.fillRgba;
})
.attr('stroke', function (d) {
return d.strokeRgba;
})
.attr('stroke-width', function (d) {
return d.lineWidth;
})
.attr('x', function (d) {
return d.x;
})
.attr('y', function (d) {
return d.y;
});
},
update: function () {
renderer.attr('x', function (d) {
return d.x;
})
.attr('y', function (d) {
return d.y;
});
},
destroy: function () {
renderer = null;
svg = null;
}
};
}
BenchD3SvgRounded.version = d3.version;
BenchD3SvgRounded.framework = 'd3';
BenchD3SvgRounded.object = 'rounded';
BenchD3SvgRounded.renderers = ['svg'];
Bench.list.push(BenchD3SvgRounded);
function BenchD3SvgText(container, width, height, data) {
var renderer, svg;
return {
init: function () {
svg = container.append('svg').attr({width: width, height: height});
renderer = svg.selectAll('text').data(data);
renderer.enter().append('text')
.text(function (d) {
return d.text;
})
.style('font-size', function (d) {
return d.textSize + 'px';
})
.style('font-family', function (d) {
return d.fontFamily;
})
.attr('fill', function (d) {
return d.fillRgba;
})
.attr('dx', function (d) {
return d.x;
})
.attr('dy', function (d) {
return d.y;
});
},
update: function () {
renderer.attr('dx', function (d) {
return d.x;
})
.attr('dy', function (d) {
return d.y;
});
},
destroy: function () {
renderer = null;
svg = null;
}
};
}
BenchD3SvgText.version = d3.version;
BenchD3SvgText.framework = 'd3';
BenchD3SvgText.object = 'text';
BenchD3SvgText.renderers = ['svg'];
Bench.list.push(BenchD3SvgText);
function BenchEaselCircles(container, width, height, data, params) {
var self, objects, stage;
return self = {
init: function () {
var canvas = canvas = params.cache('2d');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
stage = new createjs.Stage(canvas);
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = new createjs.Shape();
o.graphics
.beginFill(d.fillRgba)
.drawCircle(0, 0, d.radius);
stage.addChild(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].x = c.x;
objects[i].y = c.y;
}
stage.update();
},
destroy: function () {
objects = null;
stage = null;
}
};
}
BenchEaselCircles.version = createjs.EaselJS.version;
BenchEaselCircles.framework = 'easel';
BenchEaselCircles.object = 'circle';
BenchEaselCircles.renderers = ['canvas'];
Bench.list.push(BenchEaselCircles);
function BenchEaselRectangles(container, width, height, data, params) {
var self, objects, stage;
return self = {
init: function () {
var canvas = canvas = params.cache('2d');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
stage = new createjs.Stage(canvas);
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = new createjs.Shape();
o.graphics
.beginFill(d.fillRgba)
.drawRect(0, 0, d.w, d.h);
stage.addChild(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].x = c.x;
objects[i].y = c.y;
}
stage.update();
},
destroy: function () {
objects = null;
stage = null;
}
};
}
BenchEaselRectangles.version = createjs.EaselJS.version;
BenchEaselRectangles.framework = 'easel';
BenchEaselRectangles.object = 'rectangle';
BenchEaselRectangles.renderers = ['canvas'];
Bench.list.push(BenchEaselRectangles);
function BenchEaselRounded(container, width, height, data, params) {
var self, objects, stage;
return self = {
init: function () {
var canvas = canvas = params.cache('2d');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
stage = new createjs.Stage(canvas);
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = new createjs.Shape();
o.graphics
.beginFill(d.fillRgba)
.setStrokeStyle(d.lineWidth)
.beginStroke(d.strokeRgba)
.drawRoundRect(0, 0, d.w, d.h, d.cornerRadius);
stage.addChild(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].x = c.x;
objects[i].y = c.y;
}
stage.update();
},
destroy: function () {
objects = null;
stage = null;
}
};
}
BenchEaselRounded.version = createjs.EaselJS.version;
BenchEaselRounded.framework = 'easel';
BenchEaselRounded.object = 'rounded';
BenchEaselRounded.renderers = ['canvas'];
Bench.list.push(BenchEaselRounded);
function BenchEaselText(container, width, height, data, params) {
var self, objects, stage;
return self = {
init: function () {
var canvas = canvas = params.cache('2d');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
stage = new createjs.Stage(canvas);
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = new createjs.Text(d.text, d.textSize + 'px ' + d.fontFamily, d.fillRgba);
stage.addChild(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].x = c.x;
objects[i].y = c.y;
}
stage.update();
},
destroy: function () {
objects = null;
stage = null;
}
};
}
BenchEaselText.version = createjs.EaselJS.version;
BenchEaselText.framework = 'easel';
BenchEaselText.object = 'text';
BenchEaselText.renderers = ['canvas'];
Bench.list.push(BenchEaselText);
function BenchPixiCircles(container, width, height, data, params) {
var self, renderer, objects, stage;
return self = {
init: function () {
PIXI.utils._saidHello = true;
var map = {
webgl: 'WebGLRenderer',
canvas: 'CanvasRenderer'
};
var canvas;
if (params.renderer === 'webgl') {
canvas = params.cache('webgl-pixi');
} else if (params.renderer === 'canvas') {
canvas = params.cache('2d');
}
params.renderer = map[params.renderer];
renderer = new PIXI[params.renderer](width, height, {
view: canvas,
backgroundColor: 0xFFFFFF
});
container.node().appendChild(renderer.view);
stage = new PIXI.Container();
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = new PIXI.Graphics();
o.beginFill(d.fillNumber, d.fillOpacity);
o.drawCircle(0, 0, d.radius);
o.endFill();
stage.addChild(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].position.x = c.x;
objects[i].position.y = c.y;
}
renderer.render(stage);
},
destroy: function () {
objects = null;
renderer.destroy();
stage.destroy();
stage = null;
renderer = null;
}
};
}
BenchPixiCircles.version = PIXI.VERSION;
BenchPixiCircles.framework = 'pixi';
BenchPixiCircles.object = 'circle';
BenchPixiCircles.renderers = ['webgl', 'canvas'];
Bench.list.push(BenchPixiCircles);
function BenchPixiRectangles(container, width, height, data, params) {
var self, renderer, objects, stage;
return self = {
init: function () {
PIXI.utils._saidHello = true;
var map = {
webgl: 'WebGLRenderer',
canvas: 'CanvasRenderer'
};
var canvas;
if (params.renderer === 'webgl') {
canvas = params.cache('webgl-pixi');
} else if (params.renderer === 'canvas') {
canvas = params.cache('2d');
}
params.renderer = map[params.renderer];
renderer = new PIXI[params.renderer](width, height, {
view: canvas,
backgroundColor: 0xFFFFFF
});
container.node().appendChild(renderer.view);
stage = new PIXI.Container();
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = new PIXI.Graphics();
o.beginFill(d.fillNumber, d.fillOpacity);
o.drawRect(0, 0, d.w, d.h);
o.endFill();
stage.addChild(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].position.x = c.x;
objects[i].position.y = c.y;
}
renderer.render(stage);
},
destroy: function () {
objects = null;
renderer.destroy();
stage.destroy();
stage = null;
renderer = null;
}
};
}
BenchPixiRectangles.version = PIXI.VERSION;
BenchPixiRectangles.framework = 'pixi';
BenchPixiRectangles.object = 'rectangle';
BenchPixiRectangles.renderers = ['webgl', 'canvas'];
Bench.list.push(BenchPixiRectangles);
function BenchPixiRounded(container, width, height, data, params) {
var self, renderer, objects, stage;
return self = {
init: function () {
PIXI.utils._saidHello = true;
var map = {
webgl: 'WebGLRenderer',
canvas: 'CanvasRenderer'
};
var canvas;
if (params.renderer === 'webgl') {
canvas = params.cache('webgl-pixi');
} else if (params.renderer === 'canvas') {
canvas = params.cache('2d');
}
params.renderer = map[params.renderer];
renderer = new PIXI[params.renderer](width, height, {
view: canvas,
backgroundColor: 0xFFFFFF
});
container.node().appendChild(renderer.view);
stage = new PIXI.Container();
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = new PIXI.Graphics();
o.lineStyle(d.lineWidth, d.strokeNumber, d.strokeOpacity);
o.beginFill(d.fillNumber, d.fillOpacity);
o.drawRoundedRect(0, 0, d.w, d.h, d.cornerRadius);
o.endFill();
stage.addChild(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].position.x = c.x;
objects[i].position.y = c.y;
}
renderer.render(stage);
},
destroy: function () {
objects = null;
renderer.destroy();
stage.destroy();
stage = null;
renderer = null;
}
};
}
BenchPixiRounded.version = PIXI.VERSION;
BenchPixiRounded.framework = 'pixi';
BenchPixiRounded.object = 'rounded';
BenchPixiRounded.renderers = ['webgl', 'canvas'];
Bench.list.push(BenchPixiRounded);
function BenchPixiText(container, width, height, data, params) {
var self, renderer, objects, stage;
return self = {
init: function () {
PIXI.utils._saidHello = true;
var map = {
webgl: 'WebGLRenderer',
canvas: 'CanvasRenderer'
};
var canvas;
if (params.renderer === 'webgl') {
canvas = params.cache('webgl-pixi');
} else if (params.renderer === 'canvas') {
canvas = params.cache('2d');
}
params.renderer = map[params.renderer];
renderer = new PIXI[params.renderer](width, height, {
view: canvas,
backgroundColor: 0xFFFFFF
});
container.node().appendChild(renderer.view);
stage = new PIXI.Container();
renderer.render(stage);
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = new PIXI.Text(d.text, {font: d.textSize + 'px ' + d.fontFamily, fill: d.fillRgba});
stage.addChild(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].position.x = c.x;
objects[i].position.y = c.y;
}
renderer.render(stage);
},
destroy: function () {
objects = null;
renderer.destroy();
stage.destroy();
stage = null;
renderer = null;
}
};
}
BenchPixiText.version = PIXI.VERSION;
BenchPixiText.framework = 'pixi';
BenchPixiText.object = 'text';
BenchPixiText.renderers = ['webgl', 'canvas'];
Bench.list.push(BenchPixiText);
function BenchStackGLCircles(container, width, height, data, params) {
var self, renderer, objects, scene, camera;
return self = {
init: function () {
var canvas = params.cache('webgl-stackgl');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
stackgl.init(canvas, [1, 1, 1, 1]);
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = stackgl.circle(d.radius, d.circleSegments, d.fillRgbaArray);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].t[0] = c.x;
objects[i].t[1] = c.y;
}
stackgl.update(objects);
},
destroy: function () {
stackgl.dispose();
renderer = null;
scene = null;
camera = null;
}
};
}
BenchStackGLCircles.version = stackgl.version;
BenchStackGLCircles.framework = 'stackgl';
BenchStackGLCircles.object = 'circle';
BenchStackGLCircles.renderers = ['webgl'];
Bench.list.push(BenchStackGLCircles);
function BenchStackGLRectangles(container, width, height, data, params) {
var self, renderer, objects, scene, camera;
return self = {
init: function () {
var canvas = params.cache('webgl-stackgl');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
stackgl.init(canvas, [1, 1, 1, 1]);
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = stackgl.rectangle(d.w, d.h, d.fillRgbaArray);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].t[0] = c.x;
objects[i].t[1] = c.y;
}
stackgl.update(objects);
},
destroy: function () {
stackgl.dispose();
renderer = null;
scene = null;
camera = null;
}
};
}
BenchStackGLRectangles.version = stackgl.version;
BenchStackGLRectangles.framework = 'stackgl';
BenchStackGLRectangles.object = 'rectangle';
BenchStackGLRectangles.renderers = ['webgl'];
Bench.list.push(BenchStackGLRectangles);
function BenchStackGLText(container, width, height, data, params) {
var self, renderer, objects, scene, camera;
return self = {
init: function () {
var canvas = params.cache('webgl-stackgl');
canvas.width = width;
canvas.height = height;
container.node().appendChild(canvas);
stackgl.init(canvas, [1, 1, 1, 1]);
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = stackgl.text(d.text, d.textSize, d.fontFamily, d.fillRgbaArray);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].t[0] = c.x;
objects[i].t[1] = c.y;
}
stackgl.update(objects);
},
destroy: function () {
stackgl.dispose();
renderer = null;
scene = null;
camera = null;
}
};
}
BenchStackGLText.version = stackgl.version;
BenchStackGLText.framework = 'stackgl';
BenchStackGLText.object = 'text';
BenchStackGLText.renderers = ['webgl'];
Bench.list.push(BenchStackGLText);
function BenchThreeCircles(container, width, height, data, params) {
var self, renderer, objects, scene, camera;
return self = {
init: function () {
var canvas;
if (params.renderer === 'canvas') {
canvas = params.cache('2d');
} else if (params.renderer === 'webgl') {
canvas = params.cache('webgl-three');
}
params.renderer = {
webgl: 'WebGLRenderer',
canvas: 'CanvasRenderer',
svg: 'SVGRenderer',
css: 'CSS3DRenderer'
}[params.renderer];
scene = new THREE.Scene();
var log = console.log;
console.log = function () {
};
renderer = new THREE[params.renderer]({
premultipliedAlpha: false,
alpha: false,
antialias: false,
view: canvas
});
console.log = log;
renderer.setClearColor(new THREE.Color(0xFFFFFF, 1.0));
renderer.setSize(width, height);
container.node().appendChild(renderer.domElement);
camera = new THREE.OrthographicCamera(0, width, height, 0, 1, 1000);
camera.position.z = 100;
camera.lookAt(new THREE.Vector3(0, 0, 0));
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var meshMaterial = new THREE.MeshBasicMaterial({
color: d.fillNumber,
opacity: d.fillOpacity,
transparent: true
});
var o;
if (params.renderer === 'CSS3DRenderer') {
var element = document.createElement('div');
element.style.width = (d.radius * 2) + 'px';
element.style.height = (d.radius * 2) + 'px';
element.style.background = d.fillRgba;
element.style.borderRadius = d.radius + 'px';
o = new THREE.CSS3DObject(element);
} else {
o = new THREE.Mesh(new THREE.CircleGeometry(d.radius, d.circleSegments), meshMaterial);
}
scene.add(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].position.x = c.x;
objects[i].position.y = c.y;
}
renderer.render(scene, camera);
},
destroy: function () {
for (var i = 0; i < objects.length; i++) {
var o = objects[i];
if (o.geometry) {
o.geometry.dispose();
}
if (o.material) {
o.material.dispose();
}
scene.remove(o);
}
scene = null;
camera = null;
renderer = null;
}
};
}
BenchThreeCircles.version = THREE.REVISION;
BenchThreeCircles.framework = 'three';
BenchThreeCircles.object = 'circle';
BenchThreeCircles.renderers = ['webgl', 'canvas', 'svg', 'css'];
BenchThreeCircles.limits = {svg: 60};
Bench.list.push(BenchThreeCircles);
function BenchThreeRectangles(container, width, height, data, params) {
var self, renderer, objects, scene, camera;
return self = {
init: function () {
var canvas;
if (params.renderer === 'canvas') {
canvas = params.cache('2d');
} else if (params.renderer === 'webgl') {
canvas = params.cache('webgl-three');
}
params.renderer = {
webgl: 'WebGLRenderer',
canvas: 'CanvasRenderer',
svg: 'SVGRenderer',
css: 'CSS3DRenderer'
}[params.renderer];
scene = new THREE.Scene();
var log = console.log;
console.log = function () {
};
renderer = new THREE[params.renderer]({
premultipliedAlpha: false,
alpha: false,
antialias: false,
view: canvas
});
console.log = log;
renderer.setClearColor(new THREE.Color(0xFFFFFF, 1.0));
renderer.setSize(width, height);
container.node().appendChild(renderer.domElement);
camera = new THREE.OrthographicCamera(0, width, height, 0, 1, 1000);
camera.position.z = 100;
camera.lookAt(new THREE.Vector3(0, 0, 0));
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var meshMaterial = new THREE.MeshBasicMaterial({
color: d.fillNumber,
opacity: d.fillOpacity,
transparent: true
});
var o;
if (params.renderer === 'CSS3DRenderer') {
var element = document.createElement('div');
element.style.width = d.w + 'px';
element.style.height = d.h + 'px';
element.style.background = d.fillRgba;
o = new THREE.CSS3DObject(element);
} else {
o = new THREE.Mesh(new THREE.PlaneGeometry(d.w, d.h, 1, 1), meshMaterial);
}
scene.add(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].position.x = c.x;
objects[i].position.y = c.y;
}
renderer.render(scene, camera);
},
destroy: function () {
for (var i = 0; i < objects.length; i++) {
var o = objects[i];
if (o.geometry) {
o.geometry.dispose();
}
if (o.material) {
o.material.dispose();
}
scene.remove(o);
}
scene = null;
camera = null;
renderer = null;
}
};
}
BenchThreeRectangles.version = THREE.REVISION;
BenchThreeRectangles.framework = 'three';
BenchThreeRectangles.object = 'rectangle';
BenchThreeRectangles.renderers = ['webgl', 'canvas', 'svg', 'css'];
BenchThreeRectangles.limits = {svg: 240};
Bench.list.push(BenchThreeRectangles);
function BenchThreeRounded(container, width, height, data, params) {
var self, renderer, objects, scene, camera;
return self = {
init: function () {
var canvas;
if (params.renderer === 'canvas') {
canvas = params.cache('2d');
} else if (params.renderer === 'webgl') {
canvas = params.cache('webgl-three');
}
params.renderer = {
webgl: 'WebGLRenderer',
canvas: 'CanvasRenderer',
svg: 'SVGRenderer',
css: 'CSS3DRenderer'
}[params.renderer];
scene = new THREE.Scene();
var log = console.log;
console.log = function () {
};
renderer = new THREE[params.renderer]({
premultipliedAlpha: false,
alpha: false,
antialias: false,
view: canvas
});
console.log = log;
renderer.setClearColor(new THREE.Color(0xFFFFFF, 1.0));
renderer.setSize(width, height);
container.node().appendChild(renderer.domElement);
camera = new THREE.OrthographicCamera(0, width, height, 0, 1, 1000);
camera.position.z = 100;
camera.lookAt(new THREE.Vector3(0, 0, 0));
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var meshMaterial = new THREE.MeshBasicMaterial({
color: d.fillNumber,
transparent: true,
opacity: d.fillOpacity
});
var o;
if (params.renderer === 'CSS3DRenderer') {
var element = document.createElement('div');
element.style.width = (d.w - d.lineWidth) + 'px';
element.style.height = (d.h - d.lineWidth) + 'px';
element.style.background = d.fillRgba;
element.style.border = d.lineWidth + 'px solid ' + d.strokeRgba;
element.style.borderRadius = d.cornerRadius + 'px';
o = new THREE.CSS3DObject(element);
} else {
o = new THREE.Mesh(new THREE.PlaneGeometry(d.w, d.h, 1, 1), meshMaterial);
}
scene.add(o);
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].position.x = c.x;
objects[i].position.y = c.y;
}
renderer.render(scene, camera);
},
destroy: function () {
for (var i = 0; i < objects.length; i++) {
var o = objects[i];
if (o.geometry) {
o.geometry.dispose();
}
if (o.material) {
o.material.dispose();
}
scene.remove(o);
}
scene = null;
camera = null;
renderer = null;
}
};
}
BenchThreeRounded.version = THREE.REVISION;
BenchThreeRounded.framework = 'three';
BenchThreeRounded.object = 'rounded';
BenchThreeRounded.renderers = ['css'];
Bench.list.push(BenchThreeRounded);
function BenchTwoCircles(container, width, height, data, params) {
var self, renderer, objects;
return self = {
init: function () {
renderer = Two.Instances.filter(function (d) {
return {webgl: 'WebGLRenderer', canvas: 'CanvasRenderer'}[params.renderer] === d.type;
})[0];
renderer = renderer || new Two({
type: Two.Types[params.renderer],
width: width,
height: height
});
renderer.appendTo(container.node());
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = renderer.makeCircle(0, 0, d.radius);
o.fill = d.fillRgba;
o.noStroke();
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].translation.set(c.x, c.y);
}
renderer.update();
},
destroy: function () {
objects = null;
renderer.clear();
if (params.renderer === 'svg') {
Two.Instances.pop();
} else {
// Garbage leftovers?
renderer.scene.subtractions.splice(0);
}
renderer = null;
}
};
}
BenchTwoCircles.version = Two.Version.replace('v', '');
BenchTwoCircles.framework = 'two';
BenchTwoCircles.object = 'circle';
BenchTwoCircles.renderers = ['webgl', 'canvas', 'svg'];
BenchTwoCircles.limits = {webgl: 720, canvas: 720, svg: 720};
Bench.list.push(BenchTwoCircles);
function BenchTwoRectangles(container, width, height, data, params) {
var self, renderer, objects;
return self = {
init: function () {
renderer = Two.Instances.filter(function (d) {
return {webgl: 'WebGLRenderer', canvas: 'CanvasRenderer'}[params.renderer] === d.type;
})[0];
renderer = renderer || new Two({
type: Two.Types[params.renderer],
width: width,
height: height
});
renderer.appendTo(container.node());
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = renderer.makeRectangle(0, 0, d.w, d.h);
o.fill = d.fillRgba;
o.noStroke();
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].translation.set(c.x, c.y);
}
renderer.update();
},
destroy: function () {
objects = null;
renderer.clear();
if (params.renderer === 'svg') {
Two.Instances.pop();
} else {
// Garbage leftovers?
renderer.scene.subtractions.splice(0);
}
renderer = null;
}
};
}
BenchTwoRectangles.version = Two.Version.replace('v', '');
BenchTwoRectangles.framework = 'two';
BenchTwoRectangles.object = 'rectangle';
BenchTwoRectangles.renderers = ['webgl', 'canvas', 'svg'];
BenchTwoRectangles.limits = {webgl: 720, canvas: 720, svg: 720};
Bench.list.push(BenchTwoRectangles);
function BenchTwoRounded(container, width, height, data, params) {
var self, renderer, objects;
return self = {
init: function () {
renderer = Two.Instances.filter(function (d) {
return {webgl: 'WebGLRenderer', canvas: 'CanvasRenderer'}[params.renderer] === d.type;
})[0];
renderer = renderer || new Two({
type: Two.Types[params.renderer],
width: width,
height: height
});
renderer.appendTo(container.node());
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = renderer.makeRoundedRectangle(0, 0, d.w, d.h, d.cornerRadius);
o.fill = d.fillRgba;
o.stroke = d.strokeRgba;
o.linewidth = d.lineWidth;
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].translation.set(c.x, c.y);
}
renderer.update();
},
destroy: function () {
objects = null;
renderer.clear();
if (params.renderer === 'svg') {
Two.Instances.pop();
} else {
// Garbage leftovers?
renderer.scene.subtractions.splice(0);
}
renderer = null;
}
};
}
BenchTwoRounded.version = Two.Version.replace('v', '');
BenchTwoRounded.framework = 'two';
BenchTwoRounded.object = 'rounded';
BenchTwoRounded.renderers = ['webgl', 'canvas', 'svg'];
BenchTwoRounded.limits = {webgl: 720, canvas: 720, svg: 720};
Bench.list.push(BenchTwoRounded);
function BenchTwoTriangles(container, width, height, data, params) {
var self, renderer, objects;
return self = {
init: function () {
renderer = Two.Instances.filter(function (d) {
return {webgl: 'WebGLRenderer', canvas: 'CanvasRenderer'}[params.renderer] === d.type;
})[0];
renderer = renderer || new Two({
type: Two.Types[params.renderer],
width: width,
height: height
});
renderer.appendTo(container.node());
objects = [];
for (var i = 0; i < data.length; i++) {
var d = data[i];
var o = renderer.makePolygon(0, 0, d.triangleRadius);
o.fill = d.fillRgba;
o.noStroke();
objects.push(o);
}
self.update();
},
update: function () {
for (var i = 0; i < data.length; i++) {
var c = data[i];
objects[i].translation.set(c.x, c.y);
}
renderer.update();
},
destroy: function () {
objects = null;
renderer.clear();
if (params.renderer === 'svg') {
Two.Instances.pop();
} else {
// Garbage leftovers?
renderer.scene.subtractions.splice(0);
}
renderer = null;
}
};
}
BenchTwoTriangles.version = Two.Version.replace('v', '');
BenchTwoTriangles.framework = 'two';
BenchTwoTriangles.object = 'triangle';
BenchTwoTriangles.renderers = ['webgl', 'canvas', 'svg'];
BenchTwoTriangles.limits = {webgl: -1, canvas: -1, svg: -1};
Bench.list.push(BenchTwoTriangles);
function Bench(cfg) {
var tests = cfg.tests;
var time = cfg.time;
var pause = cfg.pause;
var width = cfg.width;
var height = cfg.height;
var populate = cfg.populate || _populate;
var iterate = cfg.iterate || _iterate;
var color = Bench.color = cfg.color || d3.interpolateHcl(d3.hcl(0, 70, 70).brighter(1), d3.hcl(150, 70, 70).brighter(1));
var autoStart = cfg.autoStart || false;
var version = false;
var containerElement = d3.select('#container');
var chartElement = d3.select('#chart');
var tableElement = d3.select('#result');
var messageElement = d3.select('#message');
var nameLabel = d3.select('#name');
var noteLabel = d3.select('#note');
var runButton = d3.select('#run');
var stopButton = d3.select('#stop');
var infoButton = d3.select('#info');
var resetButton = d3.select('#reset');
var shareButton = d3.select('#share');
var linkElement = d3.select('#link');
var versionElement = d3.select('#version');
var arrowElement = d3.select('#arrow');
var packElement = d3.select('#pack');
var filterObjectElement = d3.select('#filter-object');
var filterCountElement = d3.select('#filter-count');
var expanded;
var grouped;
var stop;
var cursor = 0;
var cache = {};
var pack;
var results;
start();
function start() {
if (!window.location.origin) {
window.location.origin = window.location.protocol + "//" + window.location.hostname +
(window.location.port ? ':' + window.location.port : '');
}
initData();
var sharedStatus = shared();
//if (!sharedStatus.wasShared) {
// version = true;
//}
results = BechUtilsTable(tableElement, versionElement, version, chartElement, tests, grouped, color, retest);
chart = BenchUtilsChartLines(chartElement, tests, grouped, 960, 400 + 48 * 2, 48, color);
pack = BenchUtilsChartPack(packElement, filterObjectElement, filterCountElement,
grouped, expanded, 413, 400 - 2 * 20, 8, 14, color, 500, '14px monospace', 14 / 2);
initUi();
results.update();
chart.update();
pack.update();
if (autoStart) {
test();
} else {
results.update(true);
ui(false);
}
infoButton.style('display', 'none');
if (!sharedStatus.wasShared) {
resetButton.style('display', 'none');
shareButton.style('visibility', 'hidden');
}
if (!sharedStatus.isInSharedFrame) {
linkElement.style('display', 'none');
}
d3.selectAll('.cloak').classed('cloak', false);
}
function shared() {
var s = parseSearch();
var wasShared, isInSharedFrame;
if (s.r) {
try {
var json = JSON.parse(s.r.replace(/([^:,{]*):/g, '"$1":'));
wasShared = deserialize(json);
} catch (ign) {
}
}
if (wasShared && s.s) {
d3.selectAll('body > *').remove();
document.body.style.width = '960px';
tableElement.classed('pull-left', true);
packElement.classed('pull-right', true);
document.body.appendChild(tableElement.node());
document.body.appendChild(packElement.node());
var link = window.location.origin +
window.location.pathname.replace(/\/raw\/([^/]+)\/[^/]+(\/?)/gi, '/raw/$1$2');
linkElement.select('a').attr('href', link + '?r=' + s.r);
document.body.appendChild(linkElement.node());
isInSharedFrame = true;
}
return {
wasShared: wasShared,
isInSharedFrame: isInSharedFrame
};
}
function parseSearch() {
var r = {};
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
r[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
return r;
}
function initData() {
expanded = Bench.expanded = [];
grouped = Bench.grouped = [];
Bench.list.forEach(function (f) {
f.renderers.forEach(function (r) {
var d = [];
var dn = f.framework + '/' + r + '/' + f.object;
var sn = f.framework + ' /' + r + '/' + f.object;
var g = {
framework: f.framework,
object: f.object,
name: r,
version: f.version,
data: d,
displayName: dn,
sortName: sn
};
tests.forEach(function (t) {
var s = {
type: f,
renderer: r,
count: t,
displayName: dn + '/' + t,
sortName: sn + '/' + d3.format('06d')(t),
disabled: f.limits && f.limits[r] && t > f.limits[r],
parent: g
};
expanded.push(s);
d.push(s);
});
grouped.push(g);
});
});
expanded.sort(function (a, b) {
return a.sortName.localeCompare(b.sortName);
});
grouped.sort(function (a, b) {
return a.sortName.localeCompare(b.sortName);
});
}
function initUi() {
containerElement.style({width: width + 'px', height: height + 'px'});
stopButton.on('click', function () {
stop = true;
stopButton.style('display', 'none');
});
runButton.on('click', function () {
if (!available()) {
reset();
}
cursor = (cursor < expanded.length) ? cursor : 0;
test();
});
resetButton.on('click', reset);
infoButton.on('click', function () {
infoButton.style('display', 'none');
containerElement.selectAll('*').remove();
containerElement.node().appendChild(messageElement.node());
nameLabel.text('');
});
shareButton.on('mousedown', function () {
var serialized = serialize();
var str = JSON.stringify(serialized).replace(/"/g, '');
var link = window.location.origin +
window.location.pathname.replace(/\/raw\/([^/]+)\/[^/]+\/?/gi, '/raw/$1/');
shareButton.attr('href', link + '?r=' + str);
var tSize = tableElement.node().getBoundingClientRect();
var frame = '<iframe ' +
'sandbox="allow-scripts allow-forms allow-same-origin allow-top-navigation" ' +
'width="' + tSize.width + 'px" ' +
'height="' + tSize.height + 'px" ' +
'frameborder="0" ' +
'style="border: none" ' +
'src="' + link + '?s=tl&r=' + str + '">' +
'</iframe>';
if (console.dir) {
console.dir({table: frame, hash: str, link: link});
} else {
console.log(frame);
}
});
}
function ui(running) {
infoButton.style('display', !running ? null : 'none');
noteLabel.style('visibility', !running ? null : 'hidden');
runButton.style('display', !running ? null : 'none');
stopButton.style('display', running ? null : 'none');
resetButton.style('display', !running ? null : 'none');
shareButton.style('visibility', !running ? null : 'hidden');
}
function reset() {
expanded.forEach(function (d) {
delete d.fps;
delete d.pending;
});
//version = true;
results.update(true);
chart.update();
pack.update();
}
function serialize() {
var s = {};
grouped.forEach(function (g) {
var o = {};
var use = false;
g.data.forEach(function (d) {
if (d.fps !== undefined) {
o[d.count] = d3.round(d.fps, 1);
use = true;
}
});
if (use) {
var f = s[g.framework] = s[g.framework] || {};
var r = f[g.name] = f[g.name] || {};
r[g.object] = o;
}
});
return s;
}
function deserialize(j) {
var ret = false;
grouped.forEach(function (g) {
g.data.forEach(function (d) {
if (j[g.framework] &&
j[g.framework][g.name] &&
j[g.framework][g.name][g.object] &&
(j[g.framework][g.name][g.object][d.count] !== undefined)) {
d.fps = j[g.framework][g.name][g.object][d.count];
d.pending = false;
ret = true;
} else {
delete d.fps;
}
});
});
return ret;
}
function available() {
return expanded.filter(function (d) {
return (d.pending === undefined) && !d.disabled;
}).length;
}
function retest(d) {
results.update();
test(d);
}
var seed;
function random() {
var x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
}
function _populate(count) {
var data = [];
seed = 1;
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
var triangleSide = Math.sqrt(12 * 12 * 4 / Math.sqrt(3));
var triangleRadius = Math.sqrt(3) * triangleSide / 3;
var triangleHeight = Math.sqrt(3) * triangleSide / 2;
for (var i = 0; i < count; i++) {
var c = d3.rgb(color(i / count));
var d = {
x: width * random(),
y: height * random(),
vx: (random() - 0.5) * 1.4,
vy: (random() - 0.5) * 1.4,
w: 12,
h: 12,
cornerRadius: 3,
radius: 7, // === Math.round(Math.sqrt(((12 * 12) / Math.PI))),
lineWidth: 2,
fillNumber: parseInt(c.toString().replace('#', '0x')),
fillRgba: 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',0.75)',
fillOpacity: 0.75,
strokeRgba: 'rgba(128,128,128, 0.5)',
strokeNumber: 0x808080,
strokeOpacity: 0.5,
text: alphabet[i % alphabet.length],
textSize: 24,
fontFamily: 'Arial',
circleSegments: 16,
triangleSide: triangleSide,
triangleRadius: triangleRadius,
triangleHeight: triangleHeight
};
d.fillRgbaArray = [c.r / 255, c.g / 255, c.b / 255, d.fillOpacity];
data.push(d);
}
return data;
}
function _iterate(data) {
for (var i = 0; i < data.length; i++) {
var c = data[i];
if (c.x >= width || c.x <= 0) {
c.vx *= -1;
}
if (c.y >= height || c.y <= 0) {
c.vy *= -1;
}
c.x += c.vx;
c.y += c.vy;
}
}
function getCache(id) {
return cache[id] || (cache[id] = document.createElement('canvas'));
}
function test(single) {
var t = single || expanded[cursor++];
if (arrowElement) {
arrowElement.remove();
arrowElement = null;
}
if ((t.disabled || (t.fps !== undefined)) && !single) {
if (cursor < expanded.length) {
setTimeout(test, 0);
} else {
stop = false;
results.update(true);
ui(false);
}
return;
}
if (single) {
cursor = expanded.indexOf(single) + 1;
}
delete t.disabled;
var cycles = 0;
var data = populate(t.count);
var r = t.type(containerElement, width, height, data, {
renderer: t.renderer,
cache: getCache
});
t.pending = true;
t.time = 0;
t.first = true;
containerElement.style('display', null);
results.update();
ui(true);
setTimeout(function () {
containerElement.select('*').remove();
nameLabel.text('');
setTimeout(function () {
nameLabel.text(t.displayName);
r.init();
setTimeout(function () {
d3.timer(tick);
}, pause);
}, pause);
}, pause);
function tick(elapsed) {
t.first = t.first === true ? elapsed : t.first;
t.time = elapsed;
if (elapsed < time) {
iterate(data);
r.update();
cycles++;
} else {
t.time -= t.first;
t.repaint = t.time / cycles;
t.fps = Math.min(60, 1000 / t.repaint);
t.pending = false;
r.destroy();
chart.update();
pack.update();
if (!stop && !single && (cursor < expanded.length)) {
results.update();
ui(true);
setTimeout(test, pause);
} else {
stop = false;
results.update(true);
ui(false);
}
return true;
}
}
}
}
Bench.list = [];
Bench.version = '0.1.0';
function BenchUtilsChartLines(chartElement, tests, grouped, outerWidth, outerHeight, margin, color) {
var svg;
function update() {
chart();
}
function chart() {
var innerWidth = outerWidth - margin * 2;
var innerHeight = outerHeight - margin * 2;
var y = d3.scale.linear()
.domain([0, 60])
.range([innerHeight, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.orient('left')
.tickSize(-innerWidth)
.tickPadding(8);
var x = d3.scale.linear()
.domain(d3.extent(tests))
.range([0, innerWidth]);
var xAxis = d3.svg.axis()
.scale(x)
.orient('bottom')
.tickSize(-innerHeight)
.tickValues(tests)
.tickPadding(8);
var path = d3.svg.line();
if (!svg) {
svg = chartElement
.attr('width', outerWidth)
.attr('height', outerHeight)
.append('g')
.attr('transform', 'translate(' + margin + ',' + margin + ')');
var gradient = svg.append('defs')
.append('linearGradient')
.attr('id', 'gradient')
.attr('x1', '0%')
.attr('y1', '100%')
.attr('x2', '0%')
.attr('y2', '0%')
.attr('spreadMethod', 'pad');
for (var i = 0; i <= 100; i += 20) {
gradient.append('stop')
.attr('offset', i + '%')
.attr('stop-color', color(i / 100))
.attr('stop-opacity', 0.33);
}
svg.append('rect')
.attr('fill', 'url(#gradient)')
.attr('width', innerWidth)
.attr('height', innerHeight);
svg.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(0,' + innerHeight + ')')
.call(xAxis)
.append('text')
.attr('transform', 'rotate(90)')
.attr('y', -innerWidth - 10)
.style('text-anchor', 'end')
.text('Objects');
svg.append('g')
.attr('class', 'axis')
.call(yAxis)
.append('text')
.attr('x', 0)
.attr('y', -10)
.text('FPS');
}
var line = svg.selectAll('g.line')
.data(grouped);
line.exit().remove();
var g = line.enter().append('g')
.attr('class', 'line');
g.append('path').attr('id', function (d, i) {
return 'line' + i;
});
line.selectAll('path')
.attr('d', function (d) {
var l = d3.svg.line().interpolate('monotone');
var r = d.data.filter(function (d) {
return d.pending === false;
}).map(function (d) {
return [x(d.count), y(Math.min(60, d.fps || 0))];
});
return l(r);
});
g.append('text')
.attr('dy', '-4px')
.attr('text-anchor', 'middle')
.append('textPath')
.attr('xlink:href', function (d, i) {
return '#line' + i;
})
.attr('startOffset', function (d, i) {
return (30 + 60 * (i / grouped.length)) + '%';
})
.text(function (d) {
return d.displayName;
});
line.selectAll('text').style('display', function (d) {
return (d.data.filter(function (d) {
return d.pending === false;
}).length > 1) ? null : 'none';
});
line.on('mouseenter', function (dd) {
line.classed('highlight', function (d) {
return d === dd;
});
line.classed('mute', function (d) {
return d !== dd;
});
});
svg.on('mouseleave', function () {
line.classed({highlight: false, mute: false});
});
}
return {
update: update
}
}
function BenchUtilsChartPack(packElement, filterObjectElement, filterCountElement,
grouped, expanded, width, height, hMargin, vMargin, color, duration, font, dy) {
var measureCanvas = document.createElement('canvas');
measureCanvas.width = 8;
measureCanvas.height = 8;
var measureContext = measureCanvas.getContext('2d');
var measureCache = {};
var objectFilter = {};
var countFilter = {};
var nestSum = d3.nest()
.key(function (d) {
return d.data.parent.name;
})
.rollup(function (leaves) {
return {
sum: d3.sum(leaves, function (d) {
return d.fps;
})
}
});
var nestAlign = d3.nest()
.key(function (d) {
return d.row;
})
.rollup(function (leaves) {
return {
sum: d3.sum(leaves, function (d) {
return d.minWidth;
}) + (leaves.length - 1) * hMargin,
cols: leaves
};
});
function update(animate) {
pack(width, height, animate);
}
function measure(text, font) {
measureCache[font] = measureCache[font] || {};
measureContext.font = font;
return measureCache[font][text] ||
(measureCache[font][text] = measureContext.measureText(text).width);
}
function bounding(group) {
var x = [];
var y = [];
group.children.forEach(function (d) {
x.push(d.x - d.r, d.x + d.r);
y.push(d.y - d.r, d.y + d.r);
});
group.ex = d3.extent(x);
group.ey = d3.extent(y);
group.width = group.ex[1] - group.ex[0];
group.height = group.ey[1] - group.ey[0];
group.cx = (group.ex[1] + group.ex[0]) / 2;
group.cy = (group.ey[1] + group.ey[0]) / 2;
}
function align(groups, width, margin) {
var rows = nestAlign.entries(groups);
rows.forEach(function (row) {
var shift = (width - row.values.sum) / 2 - margin;
row.values.cols.forEach(function (col) {
col.tx += shift;
col.children.forEach(function (child) {
child.tx += shift;
});
});
});
}
function tabularize(packedData, width) {
var groups = packedData.filter(function (d) {
return d.depth === 1;
});
groups.sort(function (a, b) {
return b.r - a.r;
});
var left = hMargin;
var top = vMargin * 2;
var first = 0;
var height = 0;
var col = 0;
var row = 0;
for (var i = 0; i < groups.length; i++) {
var d = groups[i];
bounding(d);
d.minWidth = Math.max(measure(d.key, font) + hMargin, d.width);
if ((col !== 0) && ((left + d.minWidth + 2 * hMargin) > width)) {
left = hMargin;
top += first + 2 * vMargin;
first = d.height;
col = 0;
row++;
}
first = Math.max(first, d.height);
height = top + first + vMargin;
d.col = col;
d.row = row;
col++;
d.tx = left + d.minWidth / 2;
d.ty = top + d.height / 2;
left += d.minWidth + hMargin;
var dx = d.tx - d.x;
var dy = d.ty - d.y;
d.children.forEach(function (c) {
c.tx = c.x + dx;
c.ty = c.y + dy;
});
}
align(groups, width, hMargin);
return height;
}
function ui(root, data, values) {
var ol = root.select('.list').selectAll('span.filter')
.data(d3.range(0, data.length));
var sp = ol.enter().append('span').attr('class', 'filter');
sp.append('a')
.attr('class', 'click');
sp.append('span');
root.selectAll('a')
.text(function (d) {
return data[d];
})
.classed('muted', function (d) {
return !values[data[d]]
})
.on('click', function (d) {
values[data[d]] = !values[data[d]];
d3.select(this).classed('muted', !values[data[d]]);
update(true);
});
ol.selectAll('span')
.text(function (d) {
return (d + 1) < data.length ? ', ' : null;
});
ol.exit().remove();
}
function filters(items) {
var objectList = {};
var countList = {};
items.forEach(function (d) {
countList[d.data.count] = true;
objectList[d.data.parent.object] = true;
countFilter[d.data.count] = countFilter[d.data.count] === undefined ?
true : countFilter[d.data.count];
objectFilter[d.data.parent.object] = objectFilter[d.data.parent.object] === undefined ?
true : objectFilter[d.data.parent.object];
});
objectList = Object.keys(objectList);
countList = Object.keys(countList);
countList = countList.map(function (d) {
return parseInt(d);
});
ui(filterObjectElement, objectList, objectFilter);
ui(filterCountElement, countList, countFilter);
}
function pack(width, height, animate) {
width -= 2 * hMargin;
var names = d3.map(grouped, function (d) {
return d.name;
}).keys();
var entries = expanded.filter(function (d) {
return d.fps;
})
.map(function (d) {
return {
fps: d.fps,
data: d
}
});
filters(entries);
var available = entries;
entries = entries.filter(function (d) {
return (countFilter[d.data.count] || (countFilter[d.data.count] === undefined)) &&
(objectFilter[d.data.parent.object] || (objectFilter[d.data.parent.object] === undefined));
});
var sum = nestSum.entries(entries);
var sums = {};
sum.forEach(function (d) {
sums[d.key] = d.values.sum;
});
names.sort(function (a, b) {
return (sums[a] || 0) - (sums[b] || 0);
});
var nested = d3.nest()
.key(function (d) {
return d.data.parent.framework + '/' + d.data.parent.name;
})
.entries(entries);
var pack = d3.layout.pack()
.sort(function (a, b) {
return b.value - a.value;
})
.size([width, height])
.children(function (d) {
return d.values;
})
.value(function (d) {
return d.fps;
});
var pd = pack.nodes({values: nested});
var newHeight = tabularize(pd, width + 2 * hMargin, hMargin);
packElement.style('display', newHeight ? null : 'none')
.transition().duration(animate ? duration : 0)
.attr('height', Math.max(height, newHeight));
filterObjectElement.style('display', available.length ? null : 'none');
filterCountElement.style('display', available.length ? null : 'none');
pd = pd.filter(function (d) {
return d.parent;
});
var groupColor = d3.scale.ordinal().range(d3.range(0, 1.001, 1 / names.length)).domain(names);
draw(pd, groupColor, animate);
}
function draw(pd, groupColor, animate) {
var fpsItems = pd.filter(function (d) {
return !d.children;
});
var groupItems = pd.filter(function (d) {
return d.children;
});
var nodes = packElement
.selectAll('.node')
.data(pd, function (d) {
return d.key || d.data.displayName;
});
nodes.exit().remove();
var newNodes = nodes.enter().append('g')
.attr('class', function (d) {
return d.children ? 'node' : 'leaf node';
})
.attr('transform', function (d) {
return 'translate(' + [d.tx, d.ty] + ')';
});
newNodes.filter(function (d) {
return !d.children;
})
.append('circle')
.style('fill', '#fff')
.attr('r', 0);
newNodes.filter(function (d) {
return d.children;
})
.append('text');
nodes.transition().duration(animate ? duration : 0)
.attr('transform', function (d) {
return 'translate(' + [d.tx, d.ty] + ')';
});
packElement.selectAll('circle')
.data(fpsItems, function (d) {
return d.key || d.data.displayName;
})
.transition().duration(animate ? duration : 0)
.style('fill', function (d) {
return d.data ? color(groupColor(d.data.parent.name)) : null;
})
.attr('r', function (d) {
return d.r || 0;
});
packElement.selectAll('text')
.data(groupItems, function (d) {
return d.key || d.data.displayName;
})
.transition().duration(animate ? duration : 0)
.attr('dy', function (d) {
return -d.height / 2 - dy;
})
.style('text-anchor', 'middle')
.text(function (d) {
return d.key;
});
}
return {
update: update
};
}
function BechUtilsTable(tableElement, versionElement, version, svg, tests, grouped, color, retest) {
function results(done) {
var f = d3.format('.1f');
versionElement.style('display', version ? null : 'none');
tableElement.select('.group').attr('colspan', tests.length);
tableElement.select('.objects').selectAll('th').data(tests).enter().append('th').text(function (d) {
return d
});
var b = tableElement.select('tbody').on('mouseleave', function () {
svg.selectAll('g.line').classed({mute: false, highlight: false});
});
var g = b.selectAll('tr').data(grouped);
g.enter().append('tr').on('mouseenter', function (dd) {
svg.selectAll('g.line').classed('mute', function (d) {
return d !== dd;
});
svg.selectAll('g.line').classed('highlight', function (d) {
return d === dd;
});
});
var ths = g.selectAll('th')
.data(function (d) {
return [d.framework, d.name, d.object, d.version];
});
ths.enter()
.append('th').style('text-align', function (d, i) {
return i ? 'center' : 'left'
})
.html(function (d, i) {
return i ? '<small>' + d + '</small>' : d;
});
ths.style('display', function (d, i) {
return ((i === 3) && !version) ? 'none' : null;
});
g.selectAll('td.fps').data(function (d) {
return d.data;
}).enter().append('td').attr('class', 'fps');
g.selectAll('td.fps').text(function (d, i) {
var ex = '';
if (!d.disabled && !d.pending &&
d.parent.data[i + 1] && (d.parent.data[i + 1].fps !== undefined) &&
(d3.round(d.parent.data[i + 1].fps, 1) > d3.round(d.fps, 1))) {
ex = '!';
}
return ex + (d.disabled ? 'n/a' : d.pending ? '?' : d.fps ? f(d.fps) : done ? '—' : '');
})
.style('background-color', function (d) {
if (d.pending === true) {
return '#333';
}
var c = d3.rgb(color((d.fps || 0) / 60));
return (d.pending === false) ? 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',0.33)' : null;
})
.style('color', function (d) {
if (d.pending === true) {
return '#fff';
}
})
.style('text-align', function (d) {
return (d.pending === true || !d.fps) ? 'center' : 'right';
})
.classed('click', done)
.on('click', !done ? null : retest);
var tl = g.selectAll('td.trend').data(function (d) {
return [d];
});
tl.enter().append('td').attr('class', 'trend line')
.style({
padding: 0,
width: '48px'
})
.append('svg')
.attr({width: 48, height: 15})
.style({display: 'block'})
.append('path');
var y = d3.scale.linear()
.domain([0, 60])
.range([13, 2]);
var x = d3.scale.linear()
.domain(d3.extent(tests))
.range([1, 47]);
g.selectAll('td.trend path')
.attr('d', function (d) {
var l = d3.svg.line().interpolate('linear');
var r = d.data.filter(function (d) {
return d.pending === false;
}).map(function (d) {
return [x(d.count), y(d.fps || 0)];
});
return l(r)
});
}
return {
update: results
}
}
function Path(){this._x0=this._y0=this._x1=this._y1=0,this._=[]}var pi=Math.PI,tau=2*pi,epsilon=1e-6;Path.prototype={moveTo:function(t,h){this._.push("M",this._x0=this._x1=+t,",",this._y0=this._y1=+h)},closePath:function(){this._x1=this._x0,this._y1=this._y0,this._.push("Z")},lineTo:function(t,h){this._.push("L",this._x1=+t,",",this._y1=+h)},quadraticCurveTo:function(t,h,i,s){this._.push("Q",+t,",",+h,",",this._x1=+i,",",this._y1=+s)},bezierCurveTo:function(t,h,i,s,_,n){this._.push("C",+t,",",+h,",",+i,",",+s,",",this._x1=+_,",",this._y1=+n)},arcTo:function(t,h,i,s,_){t=+t,h=+h,i=+i,s=+s,_=+_;var n=this._x1,a=this._y1,o=i-t,u=s-h,c=n-t,p=a-h,r=i-n,y=s-a,x=o*o+u*u,e=c*c+p*p,M=r*r+y*y,f=Math.sqrt(x),v=Math.sqrt(e),l=_*Math.tan((Math.PI-Math.acos((x+e-M)/(2*f*v)))/2);this._.push("L",t+l/v*c,",",h+l/v*p,"A",_,",",_,",0,0,",+(p*r>c*y),",",t+l/f*o,",",h+l/f*u,"L",this._x1=+i,",",this._y1=+s)},arc:function(t,h,i,s,_){t=+t,h=+h,i=+i;var n=i*Math.cos(s),a=i*Math.sin(s),o=t+n,u=h+a,c=Math.abs(_-s);this._.push(this._.length?"L":"M",o,",",u),c>=tau-epsilon?this._.push("A",i,",",i,",0,1,1,",t-n,",",h-a,"A",i,",",i,",0,1,1,",this._x1=o,",",this._y1=u):this._.push("A",i,",",i,",0,",+(c>=pi),",1,",this._x1=t+i*Math.cos(_),",",this._y1=h+i*Math.sin(_))},rect:function(t,h,i,s){this._.push("M",this._x0=this._x1=+t,",",this._y0=this._y1=+h,"h",+i,"v",+s,"h",-i,"Z")},toString:function(){return this._.join("")}};
<!DOCTYPE html>
<meta charset='UTF-8'>
<title>Benchmark</title>
<link rel="stylesheet" href="style.css">
<style>
.cloak {
display: none;
}
</style>
<style>
/* Animated arrow */
#arrow {
transform: rotate(30deg);
}
#arrow polyline {
animation-name: svg-arrow;
animation-duration: 3s;
animation-delay: 1s;
animation-iteration-count: infinite;
transform: translate(44px, 32px) rotate(90deg);
fill: #fff;
}
#arrow path {
animation-name: svg-path;
animation-duration: 3s;
animation-delay: 1s;
animation-iteration-count: infinite;
stroke-dasharray: 4, 4;
stroke-dashoffset: -2;
fill: none;
stroke: #fff;
stroke-width: 3;
stroke-linecap: round;
stroke-linejoin: round;
}
@keyframes svg-arrow {
0% {
fill: #fff;
transform: translate(44px, 0px) rotate(90deg);
}
33% {
transform: translate(44px, 32px) rotate(90deg);
fill: #333;
}
66% {
fill: #333;
}
100% {
fill: #fff;
}
}
@keyframes svg-path {
0% {
stroke: #fff;
stroke-dashoffset: -2;
transform: translateY(-32px);
}
33% {
transform: translateY(0px);
stroke-dashoffset: -34;
stroke: #333;
}
66% {
transform: translateY(0px);
stroke: #333;
stroke-dashoffset: -34;
}
100% {
stroke: #fff;
transform: translateY(32px);
stroke-dashoffset: -66;
}
}
/* Why? Why? Because MS Edge. Cry, cry. :-( */
_:-ms-lang(x), #arrow {
display: none;
}
</style>
<body>
<script src='//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/pixi.js/3.0.8/pixi.min.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/EaselJS/0.8.0/easeljs.min.js'></script>
<script>
// Backup requestAnimationFrame & restore after first call to disable two.js auto loop start
// https://github.com/jonobr1/two.js/issues/135
window._requestAnimationFrame = window.requestAnimationFrame;
window.requestAnimationFrame = function () {
window.requestAnimationFrame = window._requestAnimationFrame;
};
</script>
<script src='//cdnjs.cloudflare.com/ajax/libs/two.js/0.5.0/two.min.js'></script>
<script src='/darosh/raw/e5e4a3e2d9bece0f86e2/art-canvas.min.js'></script>
<script src='/darosh/raw/e5e4a3e2d9bece0f86e2/art-svg.min.js'></script>
<script src='three.renderers.min.js'></script>
<script src='d3-path.min.js'></script>
<script src='/darosh/raw/4360c8ac1dcaee373113/stackgl.min.js'></script>
<script src='bench.js'></script>
<script src='bench.utils.js'></script>
<script src='bench-all.js'></script>
<div>
<div class="cloak block pull-left">
<div id="container" class="container" style="position: relative">
<div id="message" class="block" style="padding: 0 8px">
<table class="table-inline">
<thead>
<tr>
<th rowspan="2">Framework</th>
<th colspan="5" class="down">API Compatibility</th>
</tr>
<tr>
<th class="up"><a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics" target="_blank">svg</a>
</th>
<th class="up"><a href="https://en.wikipedia.org/wiki/Canvas_element" target="_blank">canvas</a>
</th>
<th class="up"><a href="https://en.wikipedia.org/wiki/WebGL" target="_blank">webgl</a></th>
<th class="up"><a href="https://github.com/d3/d3-path" target="_blank">path</a></th>
<th class="up"><a
href="https://github.com/mrdoob/three.js/blob/8ed08e983fcc78a50b8ac4ee917a23754cc6fd55/examples/js/renderers/CSS3DRenderer.js"
target="_blank">css</a></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<svg id="arrow" width="64" height="64" style="position: absolute; left: -10px; bottom: -6px;">
<defs>
<clipPath id="clip-arrow">
<rect x="0" y="0" width="64" height="32"></rect>
</clipPath>
</defs>
<g clip-path="url(#clip-arrow)">
<path d="M 32 0 L 32 32"></path>
</g>
<polyline points="0,0 24,12 0,24"></polyline>
</svg>
</div>
<div class="cloak controls block-label bottom pull-left">
<span id="run" class="btn click">run</span>
<span id="stop" class="btn click">stop</span>
<span id="info" class="btn click">info</span>
</div>
<div id="name" class="block-label bottom test-name pull-right text-right"></div>
<div class="clear"></div>
</div>
<div class="cloak block pull-left aside">
<div class="controls block-label top">
<div id="filter-object">object: <span class="list"></span></div>
<div id="filter-count">count: <span class="list"></span></div>
</div>
<svg id="pack" width="413" height="400" class="container"></svg>
</div>
</div>
<div class="cloak block pull-right">
<table id="result">
<thead>
<tr>
<th rowspan="2">Framework</th>
<th rowspan="2">Renderer</th>
<th rowspan="2">Object</th>
<th id="version" rowspan="2">Version</th>
<th class="group">Count / FPS</th>
</tr>
<tr class="objects"></tr>
</thead>
<tbody></tbody>
</table>
<div class="controls block-label bottom pull-left">
<span id="reset" class="btn click">reset</span>
<a id="share" class="btn click" href="./" target="_blank">share</a>
</div>
<div id="link" class="controls block-label bottom pull-right"><a href="#" target="_parent">open in a new window</a>
</div>
<div id="note" class="block-label bottom pull-right">click FPS value to run single test</div>
<div class="clear"></div>
</div>
<div class="cloak pull-left">
<svg id="chart"></svg>
</div>
<script>
Bench({
time: 1300,
pause: 500,
width: 400,
height: 400,
tests: [60, 240, 720, 1440, 1920]
});
d3.select('#message tbody').selectAll('tr').data([
[{
title: 'art',
link: 'https://github.com/sebmarkbage/art/',
size: '18KB',
version: ArtCanvas.version
}, 1, 1, null, null, null],
[{
title: 'd3',
link: 'http://d3js.org/',
size: '53KB',
version: d3.version
}, 2, 3, null, 3, null],
[{
title: 'easel',
link: 'http://www.createjs.com/easeljs',
size: '24KB',
version: createjs.EaselJS.version
}, null, 4, null, null, null],
[{
title: 'pixi',
link: 'http://www.pixijs.com/',
size: '80KB',
version: PIXI.VERSION
}, null, 5, 5, null, null],
[{
title: 'stackgl',
link: 'http://stack.gl/',
size: '55KB',
version: stackgl.version
}, null, null, 6, null, null],
[{
title: 'three',
link: 'http://threejs.org/',
size: '157KB',
version: THREE.REVISION
}, 7, 7, 7, null, 8],
[{
title: 'two',
link: 'https://jonobr1.github.io/two.js/',
size: '28KB',
version: Two.Version.replace('v', '')
}, 9, 9, 9, null, null]
])
.enter().append('tr')
.selectAll('td').data(function (d) {
return d;
})
.enter().append('td')
.style('text-align', function (d, i) {
return i ? 'center' : null;
})
.html(function (d, i) {
var c;
return (d && d.title) ? ('<a href="' + d.link + '" target="_blank"><b>' + d.title + '</b></a>' +
'<small class="pull-right">' + d.size + '</small>' +
'<br><small>' + d.version + '</small>') :
(i > 0 && d > 0) ? '<span class="api" style="background-color: ' +
(c = d3.rgb(Bench.color(1 - d / 8)), 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',0.5)') +
'"><b>' + d + '</b></span>' :
'<small>' + (d || '&mdash;') + '</small>';
});
try {
d3.select(self.frameElement).style('height', document.body.getBoundingClientRect().height + 'px');
} catch (ign) {
}
</script>
</body>
/* Layout */
body {
font-family: monospace;
color: rgba(0, 0, 0, 0.87);
margin: 0;
padding: 0;
position: absolute;
}
.pull-left {
float: left;
}
.pull-right {
float: right;
}
.clear {
clear: both;
display: block;
}
.block {
padding: 48px 48px 0 48px;
}
.block.pull-left {
padding-right: 0;
}
.block.pull-right {
padding-left: 0;
}
.container {
border: 1px solid #888;
overflow: hidden;
display: block;
}
.container .block {
font-family: sans-serif;
font-size: 14px;
line-height: 18px;
}
.block.aside {
min-height: 436px;
}
.block-label {
font: 14px sans-serif;
line-height: 18px;
}
.block-label.top {
padding-bottom: 4px;
}
.block-label.bottom {
padding-top: 4px;
}
.test-name {
font: 14px monospace;
}
/* Style */
hr {
border: 0;
border-bottom: 1px solid #888;
margin: 32px 0 24px 0;
}
h2 {
margin: 0;
font-size: 18px;
line-height: 18px;
}
ul {
padding-left: 20px;
margin: 18px 0 18px 0;
list-style-type: square;
}
ul ul {
list-style: none;
padding-left: 0;
}
ul ul li:before {
content: '—';
margin-right: 8px;
}
a {
color: #299ae6;
text-decoration: none;
}
li small {
font-size: 11px;
font-style: italic;
}
.api {
width: 24px;
display: inline-block;
border-radius: 50%;
border: 1px solid rgba(0, 0, 0, 0.13);
}
/* Controls */
.click {
cursor: pointer;
}
.click:hover {
text-decoration: underline;
}
.btn {
margin-right: 8px;
color: #299ae6;
}
.click.muted {
color: #ccc;
}
/* Table */
table {
font-size: 15px;
line-height: 1;
border-collapse: collapse;
cursor: default;
}
tbody:hover {
color: rgba(0, 0, 0, 0.33);
}
tbody tr:hover {
color: rgba(0, 0, 0, 0.87);
}
td, th {
border: 1px solid #888;
padding: 0 4px;
}
.table-inline td, .table-inline th {
border-color: #ccc;
border-left: none;
border-right: none;
border-bottom: none;
height: 39px;
}
.table-inline th {
border-top: none;
border-bottom: none;
height: 26px;
}
.table-inline {
width: 100%;
max-width: 100%;
word-break: break-all;
font-size: 15px;
line-height: 24px;
font-family: monospace;
}
.table-inline .up {
vertical-align: top;
}
.table-inline .down {
vertical-align: bottom;
}
.table-inline tbody tr td:first-child {
line-height: 18px;
padding-right: 9px;
}
/* Line chart */
.axis path,
.axis line {
fill: none;
stroke: #888;
shape-rendering: crispEdges;
}
.axis text {
font: 10px sans-serif;
}
.line text {
font: bold 14px monospace;
cursor: default;
}
.line path {
fill: none;
stroke: rgba(0, 0, 0, 0.87);
stroke-width: 2;
stroke-linejoin: round;
stroke-linecap: round;
cursor: default;
}
.line {
stroke-opacity: 0.87;
fill-opacity: 0.50;
}
.line.mute {
stroke-opacity: 0.13;
fill-opacity: 0.13;
}
.line.mute path {
stroke: #555;
}
.line.mute text {
fill: #888;
}
.line.highlight {
stroke-opacity: 1;
fill-opacity: 1;
}
.line.highlight path {
stroke-width: 4;
}
.trend.line path {
stroke-width: 1;
}
/* Pack chart */
.node circle {
fill: none;
stroke: #444;
stroke-width: 0.5;
}
.leaf circle {
fill-opacity: 0.5;
}
.node text {
font-size: 14px;
}
THREE.RenderableObject=function(){this.id=0,this.object=null,this.z=0,this.renderOrder=0},THREE.RenderableFace=function(){this.id=0,this.v1=new THREE.RenderableVertex,this.v2=new THREE.RenderableVertex,this.v3=new THREE.RenderableVertex,this.normalModel=new THREE.Vector3,this.vertexNormalsModel=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3],this.vertexNormalsLength=0,this.color=new THREE.Color,this.material=null,this.uvs=[new THREE.Vector2,new THREE.Vector2,new THREE.Vector2],this.z=0,this.renderOrder=0},THREE.RenderableVertex=function(){this.position=new THREE.Vector3,this.positionWorld=new THREE.Vector3,this.positionScreen=new THREE.Vector4,this.visible=!0},THREE.RenderableVertex.prototype.copy=function(e){this.positionWorld.copy(e.positionWorld),this.positionScreen.copy(e.positionScreen)},THREE.RenderableLine=function(){this.id=0,this.v1=new THREE.RenderableVertex,this.v2=new THREE.RenderableVertex,this.vertexColors=[new THREE.Color,new THREE.Color],this.material=null,this.z=0,this.renderOrder=0},THREE.RenderableSprite=function(){this.id=0,this.object=null,this.x=0,this.y=0,this.z=0,this.rotation=0,this.scale=new THREE.Vector2,this.material=null,this.renderOrder=0},THREE.Projector=function(){function e(){if(l===R){var e=new THREE.RenderableObject;return v.push(e),R++,l++,e}return v[l++]}function t(){if(p===T){var e=new THREE.RenderableVertex;return x.push(e),T++,p++,e}return x[p++]}function r(){if(d===H){var e=new THREE.RenderableFace;return S.push(e),H++,d++,e}return S[d++]}function i(){if(h===w){var e=new THREE.RenderableLine;return g.push(e),w++,h++,e}return g[h++]}function n(){if(m===M){var e=new THREE.RenderableSprite;return b.push(e),M++,m++,e}return b[m++]}function o(e,t){return e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:e.id!==t.id?e.id-t.id:0}function a(e,t){var r=0,i=1,n=e.z+e.w,o=t.z+t.w,a=-e.z+e.w,s=-t.z+t.w;return n>=0&&o>=0&&a>=0&&s>=0?!0:0>n&&0>o||0>a&&0>s?!1:(0>n?r=Math.max(r,n/(n-o)):0>o&&(i=Math.min(i,n/(n-o))),0>a?r=Math.max(r,a/(a-s)):0>s&&(i=Math.min(i,a/(a-s))),r>i?!1:(e.lerp(t,r),t.lerp(e,1-i),!0))}var s,l,c,p,E,d,f,h,u,m,y,v=[],R=0,x=[],T=0,S=[],H=0,g=[],w=0,b=[],M=0,C={objects:[],lights:[],elements:[]},j=new THREE.Vector3,z=new THREE.Vector4,V=new THREE.Box3(new THREE.Vector3(-1,-1,-1),new THREE.Vector3(1,1,1)),O=new THREE.Box3,L=new Array(3),W=(new Array(4),new THREE.Matrix4),B=new THREE.Matrix4,P=new THREE.Matrix4,k=new THREE.Matrix3,N=new THREE.Frustum,A=new THREE.Vector4,D=new THREE.Vector4;this.projectVector=function(e,t){console.warn("THREE.Projector: .projectVector() is now vector.project()."),e.project(t)},this.unprojectVector=function(e,t){console.warn("THREE.Projector: .unprojectVector() is now vector.unproject()."),e.unproject(t)},this.pickingRay=function(e,t){console.error("THREE.Projector: .pickingRay() is now raycaster.setFromCamera().")};var F=function(){var e=[],n=[],o=null,a=null,s=new THREE.Matrix3,l=function(t){o=t,a=o.material,s.getNormalMatrix(o.matrixWorld),e.length=0,n.length=0},p=function(e){var t=e.position,r=e.positionWorld,i=e.positionScreen;r.copy(t).applyMatrix4(y),i.copy(r).applyMatrix4(B);var n=1/i.w;i.x*=n,i.y*=n,i.z*=n,e.visible=i.x>=-1&&i.x<=1&&i.y>=-1&&i.y<=1&&i.z>=-1&&i.z<=1},d=function(e,r,i){c=t(),c.position.set(e,r,i),p(c)},h=function(t,r,i){e.push(t,r,i)},u=function(e,t){n.push(e,t)},m=function(e,t,r){return e.visible===!0||t.visible===!0||r.visible===!0?!0:(L[0]=e.positionScreen,L[1]=t.positionScreen,L[2]=r.positionScreen,V.isIntersectionBox(O.setFromPoints(L)))},v=function(e,t,r){return(r.positionScreen.x-e.positionScreen.x)*(t.positionScreen.y-e.positionScreen.y)-(r.positionScreen.y-e.positionScreen.y)*(t.positionScreen.x-e.positionScreen.x)<0},R=function(e,t){var r=x[e],n=x[t];f=i(),f.id=o.id,f.v1.copy(r),f.v2.copy(n),f.z=(r.positionScreen.z+n.positionScreen.z)/2,f.renderOrder=o.renderOrder,f.material=o.material,C.elements.push(f)},T=function(t,i,l){var c=x[t],p=x[i],d=x[l];if(m(c,p,d)!==!1&&(a.side===THREE.DoubleSide||v(c,p,d)===!0)){E=r(),E.id=o.id,E.v1.copy(c),E.v2.copy(p),E.v3.copy(d),E.z=(c.positionScreen.z+p.positionScreen.z+d.positionScreen.z)/3,E.renderOrder=o.renderOrder,E.normalModel.fromArray(e,3*t),E.normalModel.applyMatrix3(s).normalize();for(var f=0;3>f;f++){var h=E.vertexNormalsModel[f];h.fromArray(e,3*arguments[f]),h.applyMatrix3(s).normalize();var u=E.uvs[f];u.fromArray(n,2*arguments[f])}E.vertexNormalsLength=3,E.material=o.material,C.elements.push(E)}};return{setObject:l,projectVertex:p,checkTriangleVisibility:m,checkBackfaceCulling:v,pushVertex:d,pushNormal:h,pushUv:u,pushLine:R,pushTriangle:T}},I=new F;this.projectScene=function(c,v,R,T){d=0,h=0,m=0,C.elements.length=0,c.autoUpdate===!0&&c.updateMatrixWorld(),null===v.parent&&v.updateMatrixWorld(),W.copy(v.matrixWorldInverse.getInverse(v.matrixWorld)),B.multiplyMatrices(v.projectionMatrix,W),N.setFromMatrix(B),l=0,C.objects.length=0,C.lights.length=0,c.traverseVisible(function(t){if(t instanceof THREE.Light)C.lights.push(t);else if(t instanceof THREE.Mesh||t instanceof THREE.Line||t instanceof THREE.Sprite){var r=t.material;if(r.visible===!1)return;(t.frustumCulled===!1||N.intersectsObject(t)===!0)&&(s=e(),s.id=t.id,s.object=t,j.setFromMatrixPosition(t.matrixWorld),j.applyProjection(B),s.z=j.z,s.renderOrder=t.renderOrder,C.objects.push(s))}}),R===!0&&C.objects.sort(o);for(var S=0,H=C.objects.length;H>S;S++){var g=C.objects[S].object,w=g.geometry;if(I.setObject(g),y=g.matrixWorld,p=0,g instanceof THREE.Mesh){if(w instanceof THREE.BufferGeometry){var b=w.attributes,M=w.groups;if(void 0===b.position)continue;for(var V=b.position.array,O=0,L=V.length;L>O;O+=3)I.pushVertex(V[O],V[O+1],V[O+2]);if(void 0!==b.normal)for(var F=b.normal.array,O=0,L=F.length;L>O;O+=3)I.pushNormal(F[O],F[O+1],F[O+2]);if(void 0!==b.uv)for(var G=b.uv.array,O=0,L=G.length;L>O;O+=2)I.pushUv(G[O],G[O+1]);if(null!==w.index){var U=w.index.array;if(M.length>0)for(var S=0;S<M.length;S++)for(var q=M[S],O=q.start,L=q.start+q.count;L>O;O+=3)I.pushTriangle(U[O],U[O+1],U[O+2]);else for(var O=0,L=U.length;L>O;O+=3)I.pushTriangle(U[O],U[O+1],U[O+2])}else for(var O=0,L=V.length/3;L>O;O+=3)I.pushTriangle(O,O+1,O+2)}else if(w instanceof THREE.Geometry){var J=w.vertices,Q=w.faces,K=w.faceVertexUvs[0];k.getNormalMatrix(y);for(var X=g.material,Y=X instanceof THREE.MeshFaceMaterial,Z=Y===!0?g.material:null,$=0,_=J.length;_>$;$++){var ee=J[$];if(j.copy(ee),X.morphTargets===!0)for(var te=w.morphTargets,re=g.morphTargetInfluences,ie=0,ne=te.length;ne>ie;ie++){var oe=re[ie];if(0!==oe){var ae=te[ie],se=ae.vertices[$];j.x+=(se.x-ee.x)*oe,j.y+=(se.y-ee.y)*oe,j.z+=(se.z-ee.z)*oe}}I.pushVertex(j.x,j.y,j.z)}for(var le=0,ce=Q.length;ce>le;le++){var pe=Q[le];if(X=Y===!0?Z.materials[pe.materialIndex]:g.material,void 0!==X){var Ee=X.side,de=x[pe.a],fe=x[pe.b],he=x[pe.c];if(I.checkTriangleVisibility(de,fe,he)!==!1){var ue=I.checkBackfaceCulling(de,fe,he);if(Ee!==THREE.DoubleSide){if(Ee===THREE.FrontSide&&ue===!1)continue;if(Ee===THREE.BackSide&&ue===!0)continue}E=r(),E.id=g.id,E.v1.copy(de),E.v2.copy(fe),E.v3.copy(he),E.normalModel.copy(pe.normal),ue!==!1||Ee!==THREE.BackSide&&Ee!==THREE.DoubleSide||E.normalModel.negate(),E.normalModel.applyMatrix3(k).normalize();for(var me=pe.vertexNormals,ye=0,ve=Math.min(me.length,3);ve>ye;ye++){var Re=E.vertexNormalsModel[ye];Re.copy(me[ye]),ue!==!1||Ee!==THREE.BackSide&&Ee!==THREE.DoubleSide||Re.negate(),Re.applyMatrix3(k).normalize()}E.vertexNormalsLength=me.length;var xe=K[le];if(void 0!==xe)for(var Te=0;3>Te;Te++)E.uvs[Te].copy(xe[Te]);E.color=pe.color,E.material=X,E.z=(de.positionScreen.z+fe.positionScreen.z+he.positionScreen.z)/3,E.renderOrder=g.renderOrder,C.elements.push(E)}}}}}else if(g instanceof THREE.Line){if(w instanceof THREE.BufferGeometry){var b=w.attributes;if(void 0!==b.position){for(var V=b.position.array,O=0,L=V.length;L>O;O+=3)I.pushVertex(V[O],V[O+1],V[O+2]);if(null!==w.index)for(var U=w.index.array,O=0,L=U.length;L>O;O+=2)I.pushLine(U[O],U[O+1]);else for(var Se=g instanceof THREE.LineSegments?2:1,O=0,L=V.length/3-1;L>O;O+=Se)I.pushLine(O,O+1)}}else if(w instanceof THREE.Geometry){P.multiplyMatrices(B,y);var J=g.geometry.vertices;if(0===J.length)continue;de=t(),de.positionScreen.copy(J[0]).applyMatrix4(P);for(var Se=g instanceof THREE.LineSegments?2:1,$=1,_=J.length;_>$;$++)de=t(),de.positionScreen.copy(J[$]).applyMatrix4(P),($+1)%Se>0||(fe=x[p-2],A.copy(de.positionScreen),D.copy(fe.positionScreen),a(A,D)===!0&&(A.multiplyScalar(1/A.w),D.multiplyScalar(1/D.w),f=i(),f.id=g.id,f.v1.positionScreen.copy(A),f.v2.positionScreen.copy(D),f.z=Math.max(A.z,D.z),f.renderOrder=g.renderOrder,f.material=g.material,g.material.vertexColors===THREE.VertexColors&&(f.vertexColors[0].copy(g.geometry.colors[$]),f.vertexColors[1].copy(g.geometry.colors[$-1])),C.elements.push(f)))}}else if(g instanceof THREE.Sprite){z.set(y.elements[12],y.elements[13],y.elements[14],1),z.applyMatrix4(B);var He=1/z.w;z.z*=He,z.z>=-1&&z.z<=1&&(u=n(),u.id=g.id,u.x=z.x*He,u.y=z.y*He,u.z=z.z,u.renderOrder=g.renderOrder,u.object=g,u.rotation=g.rotation,u.scale.x=g.scale.x*Math.abs(u.x-(z.x+v.projectionMatrix.elements[0])/(z.w+v.projectionMatrix.elements[12])),u.scale.y=g.scale.y*Math.abs(u.y-(z.y+v.projectionMatrix.elements[5])/(z.w+v.projectionMatrix.elements[13])),u.material=g.material,C.elements.push(u))}}return T===!0&&C.elements.sort(o),C}},THREE.SpriteCanvasMaterial=function(e){THREE.Material.call(this),this.type="SpriteCanvasMaterial",this.color=new THREE.Color(16777215),this.program=function(e,t){},this.setValues(e)},THREE.SpriteCanvasMaterial.prototype=Object.create(THREE.Material.prototype),THREE.SpriteCanvasMaterial.prototype.constructor=THREE.SpriteCanvasMaterial,THREE.SpriteCanvasMaterial.prototype.clone=function(){var e=new THREE.SpriteCanvasMaterial;return e.copy(this),e.color.copy(this.color),e.program=this.program,e},THREE.CanvasRenderer=function(e){function t(){ye.setRGB(0,0,0),ve.setRGB(0,0,0),Re.setRGB(0,0,0);for(var e=0,t=S.length;t>e;e++){var r=S[e],i=r.color;r instanceof THREE.AmbientLight?ye.add(i):r instanceof THREE.DirectionalLight?ve.add(i):r instanceof THREE.PointLight&&Re.add(i)}}function r(e,t,r){for(var i=0,n=S.length;n>i;i++){var o=S[i];if(de.copy(o.color),o instanceof THREE.DirectionalLight){var a=xe.setFromMatrixPosition(o.matrixWorld).normalize(),s=t.dot(a);if(0>=s)continue;s*=o.intensity,r.add(de.multiplyScalar(s))}else if(o instanceof THREE.PointLight){var a=xe.setFromMatrixPosition(o.matrixWorld),s=t.dot(xe.subVectors(a,e).normalize());if(0>=s)continue;if(s*=0==o.distance?1:1-Math.min(e.distanceTo(a)/o.distance,1),0==s)continue;s*=o.intensity,r.add(de.multiplyScalar(s))}}}function i(e,t,r){d(r.opacity),f(r.blending);var i=t.scale.x*q,n=t.scale.y*J,o=.5*Math.sqrt(i*i+n*n);if(me.min.set(e.x-o,e.y-o),me.max.set(e.x+o,e.y+o),r instanceof THREE.SpriteMaterial){var a=r.map;if(null!==a){var s=fe[a.id];if((void 0===s||s.version!==a.version)&&(s=c(a),fe[a.id]=s),void 0!==s.canvas){v(s.canvas);var l=a.image,p=l.width*a.offset.x,E=l.height*a.offset.y,h=l.width*a.repeat.x,u=l.height*a.repeat.y,m=i/h,R=n/u;$.save(),$.translate(e.x,e.y),0!==r.rotation&&$.rotate(r.rotation),$.translate(-i/2,-n/2),$.scale(m,R),$.translate(-p,-E),$.fillRect(p,E,h,u),$.restore()}}else v(r.color.getStyle()),$.save(),$.translate(e.x,e.y),0!==r.rotation&&$.rotate(r.rotation),$.scale(i,-n),$.fillRect(-.5,-.5,1,1),$.restore()}else r instanceof THREE.SpriteCanvasMaterial&&(y(r.color.getStyle()),v(r.color.getStyle()),$.save(),$.translate(e.x,e.y),0!==r.rotation&&$.rotate(r.rotation),$.scale(i,n),r.program($),$.restore())}function n(e,t,r,i){if(d(i.opacity),f(i.blending),$.beginPath(),$.moveTo(e.positionScreen.x,e.positionScreen.y),$.lineTo(t.positionScreen.x,t.positionScreen.y),i instanceof THREE.LineBasicMaterial){if(h(i.linewidth),u(i.linecap),m(i.linejoin),i.vertexColors!==THREE.VertexColors)y(i.color.getStyle());else{var n=r.vertexColors[0].getStyle(),o=r.vertexColors[1].getStyle();if(n===o)y(n);else{try{var a=$.createLinearGradient(e.positionScreen.x,e.positionScreen.y,t.positionScreen.x,t.positionScreen.y);a.addColorStop(0,n),a.addColorStop(1,o)}catch(s){a=n}y(a)}}$.stroke(),me.expandByScalar(2*i.linewidth)}else i instanceof THREE.LineDashedMaterial&&(h(i.linewidth),u(i.linecap),m(i.linejoin),y(i.color.getStyle()),R([i.dashSize,i.gapSize]),$.stroke(),me.expandByScalar(2*i.linewidth),R([]))}function o(e,t,i,n,o,c,E,h){if(D.info.render.vertices+=3,D.info.render.faces++,d(h.opacity),f(h.blending),M=e.positionScreen.x,C=e.positionScreen.y,j=t.positionScreen.x,z=t.positionScreen.y,V=i.positionScreen.x,O=i.positionScreen.y,a(M,C,j,z,V,O),(h instanceof THREE.MeshLambertMaterial||h instanceof THREE.MeshPhongMaterial)&&null===h.map)pe.copy(h.color),Ee.copy(h.emissive),h.vertexColors===THREE.FaceColors&&pe.multiply(E.color),ce.copy(ye),Te.copy(e.positionWorld).add(t.positionWorld).add(i.positionWorld).divideScalar(3),r(Te,E.normalModel,ce),ce.multiply(pe).add(Ee),h.wireframe===!0?s(ce,h.wireframeLinewidth,h.wireframeLinecap,h.wireframeLinejoin):l(ce);else if(h instanceof THREE.MeshBasicMaterial||h instanceof THREE.MeshLambertMaterial||h instanceof THREE.MeshPhongMaterial)if(null!==h.map){var u=h.map.mapping;u===THREE.UVMapping&&(L=E.uvs,p(M,C,j,z,V,O,L[n].x,L[n].y,L[o].x,L[o].y,L[c].x,L[c].y,h.map))}else null!==h.envMap?h.envMap.mapping===THREE.SphericalReflectionMapping&&(Se.copy(E.vertexNormalsModel[n]).applyMatrix3(He),W=.5*Se.x+.5,B=.5*Se.y+.5,Se.copy(E.vertexNormalsModel[o]).applyMatrix3(He),P=.5*Se.x+.5,k=.5*Se.y+.5,Se.copy(E.vertexNormalsModel[c]).applyMatrix3(He),N=.5*Se.x+.5,A=.5*Se.y+.5,p(M,C,j,z,V,O,W,B,P,k,N,A,h.envMap)):(ce.copy(h.color),h.vertexColors===THREE.FaceColors&&ce.multiply(E.color),h.wireframe===!0?s(ce,h.wireframeLinewidth,h.wireframeLinecap,h.wireframeLinejoin):l(ce));else h instanceof THREE.MeshNormalMaterial?(Se.copy(E.normalModel).applyMatrix3(He),ce.setRGB(Se.x,Se.y,Se.z).multiplyScalar(.5).addScalar(.5),h.wireframe===!0?s(ce,h.wireframeLinewidth,h.wireframeLinecap,h.wireframeLinejoin):l(ce)):(ce.setRGB(1,1,1),h.wireframe===!0?s(ce,h.wireframeLinewidth,h.wireframeLinecap,h.wireframeLinejoin):l(ce))}function a(e,t,r,i,n,o){$.beginPath(),$.moveTo(e,t),$.lineTo(r,i),$.lineTo(n,o),$.closePath()}function s(e,t,r,i){h(t),u(r),m(i),y(e.getStyle()),$.stroke(),me.expandByScalar(2*t)}function l(e){v(e.getStyle()),$.fill()}function c(e){if(0===e.version||e instanceof THREE.CompressedTexture||e instanceof THREE.DataTexture)return{canvas:void 0,version:e.version};var t=e.image,r=document.createElement("canvas");r.width=t.width,r.height=t.height;var i=r.getContext("2d");i.setTransform(1,0,0,-1,0,t.height),i.drawImage(t,0,0);var n=e.wrapS===THREE.RepeatWrapping,o=e.wrapT===THREE.RepeatWrapping,a="no-repeat";return n===!0&&o===!0?a="repeat":n===!0?a="repeat-x":o===!0&&(a="repeat-y"),{canvas:$.createPattern(r,a),version:e.version}}function p(e,t,r,i,n,o,a,s,l,p,E,d,f){var h=fe[f.id];if((void 0===h||h.version!==f.version)&&(h=c(f),fe[f.id]=h),void 0===h.canvas)return v("rgba( 0, 0, 0, 1)"),void $.fill();v(h.canvas);var u,m,y,R,x,T,S,H,g=f.offset.x/f.repeat.x,w=f.offset.y/f.repeat.y,b=f.image.width*f.repeat.x,M=f.image.height*f.repeat.y;a=(a+g)*b,s=(s+w)*M,l=(l+g)*b,p=(p+w)*M,E=(E+g)*b,d=(d+w)*M,r-=e,i-=t,n-=e,o-=t,l-=a,p-=s,E-=a,d-=s,S=l*d-E*p,0!==S&&(H=1/S,u=(d*r-p*n)*H,m=(d*i-p*o)*H,y=(l*n-E*r)*H,R=(l*o-E*i)*H,x=e-u*a-y*s,T=t-m*a-R*s,$.save(),$.transform(u,m,y,R,x,T),$.fill(),$.restore())}function E(e,t,r){var i,n=t.x-e.x,o=t.y-e.y,a=n*n+o*o;0!==a&&(i=r/Math.sqrt(a),n*=i,o*=i,t.x+=n,t.y+=o,e.x-=n,e.y-=o)}function d(e){te!==e&&($.globalAlpha=e,te=e)}function f(e){re!==e&&(e===THREE.NormalBlending?$.globalCompositeOperation="source-over":e===THREE.AdditiveBlending?$.globalCompositeOperation="lighter":e===THREE.SubtractiveBlending&&($.globalCompositeOperation="darker"),re=e)}function h(e){oe!==e&&($.lineWidth=e,oe=e)}function u(e){ae!==e&&($.lineCap=e,ae=e)}function m(e){se!==e&&($.lineJoin=e,se=e)}function y(e){ie!==e&&($.strokeStyle=e,ie=e)}function v(e){ne!==e&&($.fillStyle=e,ne=e)}function R(e){le.length!==e.length&&($.setLineDash(e),le=e)}console.log("THREE.CanvasRenderer",THREE.REVISION),e=e||{};var x,T,S,H,g,w,b,M,C,j,z,V,O,L,W,B,P,k,N,A,D=this,F=new THREE.Projector,I=void 0!==e.canvas?e.canvas:document.createElement("canvas"),G=I.width,U=I.height,q=Math.floor(G/2),J=Math.floor(U/2),Q=0,K=0,X=G,Y=U,Z=1,$=I.getContext("2d",{alpha:e.alpha===!0}),_=new THREE.Color(0),ee=e.alpha===!0?0:1,te=1,re=0,ie=null,ne=null,oe=null,ae=null,se=null,le=[],ce=(new THREE.RenderableVertex,new THREE.RenderableVertex,new THREE.Color),pe=(new THREE.Color,new THREE.Color,new THREE.Color,new THREE.Color,new THREE.Color),Ee=new THREE.Color,de=new THREE.Color,fe={},he=new THREE.Box2,ue=new THREE.Box2,me=new THREE.Box2,ye=new THREE.Color,ve=new THREE.Color,Re=new THREE.Color,xe=new THREE.Vector3,Te=new THREE.Vector3,Se=new THREE.Vector3,He=new THREE.Matrix3;void 0===$.setLineDash&&($.setLineDash=function(){}),this.domElement=I,this.autoClear=!0,this.sortObjects=!0,this.sortElements=!0,this.info={render:{vertices:0,faces:0}},this.supportsVertexTextures=function(){},this.setFaceCulling=function(){},this.getContext=function(){return $},this.getContextAttributes=function(){return $.getContextAttributes()},this.getPixelRatio=function(){return Z},this.setPixelRatio=function(e){void 0!==e&&(Z=e)},this.setSize=function(e,t,r){G=e*Z,U=t*Z,I.width=G,I.height=U,q=Math.floor(G/2),J=Math.floor(U/2),r!==!1&&(I.style.width=e+"px",I.style.height=t+"px"),he.min.set(-q,-J),he.max.set(q,J),ue.min.set(-q,-J),ue.max.set(q,J),te=1,re=0,ie=null,ne=null,oe=null,ae=null,se=null,this.setViewport(0,0,e,t)},this.setViewport=function(e,t,r,i){Q=e*Z,K=t*Z,X=r*Z,Y=i*Z},this.setScissor=function(){},this.enableScissorTest=function(){},this.setClearColor=function(e,t){_.set(e),ee=void 0!==t?t:1,ue.min.set(-q,-J),ue.max.set(q,J)},this.setClearColorHex=function(e,t){console.warn("THREE.CanvasRenderer: .setClearColorHex() is being removed. Use .setClearColor() instead."),this.setClearColor(e,t)},this.getClearColor=function(){return _},this.getClearAlpha=function(){return ee},this.getMaxAnisotropy=function(){return 0},this.clear=function(){ue.empty()===!1&&(ue.intersect(he),ue.expandByScalar(2),ue.min.x=ue.min.x+q,ue.min.y=-ue.min.y+J,ue.max.x=ue.max.x+q,ue.max.y=-ue.max.y+J,1>ee&&$.clearRect(0|ue.min.x,0|ue.max.y,ue.max.x-ue.min.x|0,ue.min.y-ue.max.y|0),ee>0&&(f(THREE.NormalBlending),d(1),v("rgba("+Math.floor(255*_.r)+","+Math.floor(255*_.g)+","+Math.floor(255*_.b)+","+ee+")"),$.fillRect(0|ue.min.x,0|ue.max.y,ue.max.x-ue.min.x|0,ue.min.y-ue.max.y|0)),ue.makeEmpty())},this.clearColor=function(){},this.clearDepth=function(){},this.clearStencil=function(){},this.render=function(e,r){if(r instanceof THREE.Camera==!1)return void console.error("THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.");this.autoClear===!0&&this.clear(),D.info.render.vertices=0,D.info.render.faces=0,$.setTransform(X/G,0,0,-Y/U,Q,U-K),$.translate(q,J),x=F.projectScene(e,r,this.sortObjects,this.sortElements),T=x.elements,S=x.lights,H=r,He.getNormalMatrix(r.matrixWorldInverse),t();for(var a=0,s=T.length;s>a;a++){var l=T[a],c=l.material;if(void 0!==c&&0!==c.opacity){if(me.makeEmpty(),l instanceof THREE.RenderableSprite)g=l,g.x*=q,g.y*=J,i(g,l,c);else if(l instanceof THREE.RenderableLine)g=l.v1,w=l.v2,g.positionScreen.x*=q,g.positionScreen.y*=J,w.positionScreen.x*=q,w.positionScreen.y*=J,me.setFromPoints([g.positionScreen,w.positionScreen]),he.isIntersectionBox(me)===!0&&n(g,w,l,c);else if(l instanceof THREE.RenderableFace){if(g=l.v1,w=l.v2,b=l.v3,g.positionScreen.z<-1||g.positionScreen.z>1)continue;if(w.positionScreen.z<-1||w.positionScreen.z>1)continue;if(b.positionScreen.z<-1||b.positionScreen.z>1)continue;g.positionScreen.x*=q,g.positionScreen.y*=J,w.positionScreen.x*=q,w.positionScreen.y*=J,b.positionScreen.x*=q,b.positionScreen.y*=J,c.overdraw>0&&(E(g.positionScreen,w.positionScreen,c.overdraw),E(w.positionScreen,b.positionScreen,c.overdraw),E(b.positionScreen,g.positionScreen,c.overdraw)),me.setFromPoints([g.positionScreen,w.positionScreen,b.positionScreen]),he.isIntersectionBox(me)===!0&&o(g,w,b,0,1,2,l,c)}ue.union(me)}}$.setTransform(1,0,0,1,0,0)}},THREE.CSS3DObject=function(e){THREE.Object3D.call(this),this.element=e,this.element.style.position="absolute",this.addEventListener("removed",function(e){null!==this.element.parentNode&&this.element.parentNode.removeChild(this.element)})},THREE.CSS3DObject.prototype=Object.create(THREE.Object3D.prototype),THREE.CSS3DObject.prototype.constructor=THREE.CSS3DObject,THREE.CSS3DSprite=function(e){THREE.CSS3DObject.call(this,e)},THREE.CSS3DSprite.prototype=Object.create(THREE.CSS3DObject.prototype),THREE.CSS3DSprite.prototype.constructor=THREE.CSS3DSprite,THREE.CSS3DRenderer=function(){console.log("THREE.CSS3DRenderer",THREE.REVISION);var e,t,r,i,n=new THREE.Matrix4,o={camera:{fov:0,style:""},objects:{}},a=document.createElement("div");a.style.overflow="hidden",a.style.WebkitTransformStyle="preserve-3d",a.style.MozTransformStyle="preserve-3d",a.style.oTransformStyle="preserve-3d",a.style.transformStyle="preserve-3d",this.domElement=a;var s=document.createElement("div");s.style.WebkitTransformStyle="preserve-3d",s.style.MozTransformStyle="preserve-3d",s.style.oTransformStyle="preserve-3d",s.style.transformStyle="preserve-3d",a.appendChild(s),this.setClearColor=function(){},this.getSize=function(){return{width:e,height:t}},this.setSize=function(n,o){e=n,t=o,r=e/2,i=t/2,a.style.width=n+"px",a.style.height=o+"px",s.style.width=n+"px",s.style.height=o+"px"};var l=function(e){return Math.abs(e)<Number.EPSILON?0:e},c=function(e){var t=e.elements;return"matrix3d("+l(t[0])+","+l(-t[1])+","+l(t[2])+","+l(t[3])+","+l(t[4])+","+l(-t[5])+","+l(t[6])+","+l(t[7])+","+l(t[8])+","+l(-t[9])+","+l(t[10])+","+l(t[11])+","+l(t[12])+","+l(-t[13])+","+l(t[14])+","+l(t[15])+")"},p=function(e){var t=e.elements;return"translate3d(-50%,-50%,0) matrix3d("+l(t[0])+","+l(t[1])+","+l(t[2])+","+l(t[3])+","+l(-t[4])+","+l(-t[5])+","+l(-t[6])+","+l(-t[7])+","+l(t[8])+","+l(t[9])+","+l(t[10])+","+l(t[11])+","+l(t[12])+","+l(t[13])+","+l(t[14])+","+l(t[15])+")"},E=function(e,t){if(e instanceof THREE.CSS3DObject){var r;e instanceof THREE.CSS3DSprite?(n.copy(t.matrixWorldInverse),n.transpose(),n.copyPosition(e.matrixWorld),n.scale(e.scale),n.elements[3]=0,n.elements[7]=0,n.elements[11]=0,n.elements[15]=1,r=p(n)):r=p(e.matrixWorld);var i=e.element,a=o.objects[e.id];(void 0===a||a!==r)&&(i.style.WebkitTransform=r,i.style.MozTransform=r,i.style.oTransform=r,i.style.transform=r,o.objects[e.id]=r),i.parentNode!==s&&s.appendChild(i)}for(var l=0,c=e.children.length;c>l;l++)E(e.children[l],t)};this.render=function(e,n){var l=.5/Math.tan(THREE.Math.degToRad(.5*n.fov))*t;o.camera.fov!==l&&(a.style.WebkitPerspective=l+"px",a.style.MozPerspective=l+"px",a.style.oPerspective=l+"px",a.style.perspective=l+"px",o.camera.fov=l),e.updateMatrixWorld(),null===n.parent&&n.updateMatrixWorld(),n.matrixWorldInverse.getInverse(n.matrixWorld);var p="translate3d(0,0,"+l+"px)"+c(n.matrixWorldInverse)+" translate3d("+r+"px,"+i+"px, 0)";o.camera.style!==p&&(s.style.WebkitTransform=p,s.style.MozTransform=p,s.style.oTransform=p,s.style.transform=p,o.camera.style=p),E(e,n)}},THREE.SVGObject=function(e){THREE.Object3D.call(this),this.node=e},THREE.SVGObject.prototype=Object.create(THREE.Object3D.prototype),THREE.SVGObject.prototype.constructor=THREE.SVGObject,THREE.SVGRenderer=function(){function e(e){b.setRGB(0,0,0),M.setRGB(0,0,0),C.setRGB(0,0,0);for(var t=0,r=e.length;r>t;t++){var i=e[t],n=i.color;i instanceof THREE.AmbientLight?(b.r+=n.r,b.g+=n.g,b.b+=n.b):i instanceof THREE.DirectionalLight?(M.r+=n.r,M.g+=n.g,M.b+=n.b):i instanceof THREE.PointLight&&(C.r+=n.r,C.g+=n.g,C.b+=n.b)}}function t(e,t,r,i){for(var n=0,o=e.length;o>n;n++){var a=e[n],s=a.color;if(a instanceof THREE.DirectionalLight){var l=V.setFromMatrixPosition(a.matrixWorld).normalize(),c=r.dot(l);if(0>=c)continue;c*=a.intensity,i.r+=s.r*c,i.g+=s.g*c,i.b+=s.b*c}else if(a instanceof THREE.PointLight){var l=V.setFromMatrixPosition(a.matrixWorld),c=r.dot(V.subVectors(l,t).normalize());if(0>=c)continue;if(c*=0==a.distance?1:1-Math.min(t.distanceTo(l)/a.distance,1),0==c)continue;c*=a.intensity,i.r+=s.r*c,i.g+=s.g*c,i.b+=s.b*c}}}function r(e,t,r){var i=t.scale.x*f,n=t.scale.y*h;v=s(I++),v.setAttribute("x",e.x-.5*i),v.setAttribute("y",e.y-.5*n),v.setAttribute("width",i),v.setAttribute("height",n),r instanceof THREE.SpriteMaterial&&v.setAttribute("style","fill: "+r.color.getStyle()),T.appendChild(v)}function i(e,t,r,i){v=o(F++),v.setAttribute("x1",e.positionScreen.x),v.setAttribute("y1",e.positionScreen.y),v.setAttribute("x2",t.positionScreen.x),v.setAttribute("y2",t.positionScreen.y),i instanceof THREE.LineBasicMaterial&&(v.setAttribute("style","fill: none; stroke: "+i.color.getStyle()+"; stroke-width: "+i.linewidth+"; stroke-opacity: "+i.opacity+"; stroke-linecap: "+i.linecap+"; stroke-linejoin: "+i.linejoin),T.appendChild(v))}function n(e,r,i,n,o){R.info.render.vertices+=3,R.info.render.faces++,v=a(D++),v.setAttribute("d","M "+e.positionScreen.x+" "+e.positionScreen.y+" L "+r.positionScreen.x+" "+r.positionScreen.y+" L "+i.positionScreen.x+","+i.positionScreen.y+"z"),o instanceof THREE.MeshBasicMaterial?(g.copy(o.color),o.vertexColors===THREE.FaceColors&&g.multiply(n.color)):o instanceof THREE.MeshLambertMaterial||o instanceof THREE.MeshPhongMaterial?(w.copy(o.color),o.vertexColors===THREE.FaceColors&&w.multiply(n.color),g.copy(b),O.copy(e.positionWorld).add(r.positionWorld).add(i.positionWorld).divideScalar(3),t(p,O,n.normalModel,g),g.multiply(w).add(o.emissive)):o instanceof THREE.MeshNormalMaterial&&(L.copy(n.normalModel).applyMatrix3(W),g.setRGB(L.x,L.y,L.z).multiplyScalar(.5).addScalar(.5)),o.wireframe?v.setAttribute("style","fill: none; stroke: "+g.getStyle()+"; stroke-width: "+o.wireframeLinewidth+"; stroke-opacity: "+o.opacity+"; stroke-linecap: "+o.wireframeLinecap+"; stroke-linejoin: "+o.wireframeLinejoin):v.setAttribute("style","fill: "+g.getStyle()+"; fill-opacity: "+o.opacity),T.appendChild(v)}function o(e){return null==N[e]?(N[e]=document.createElementNS("http://www.w3.org/2000/svg","line"),0==G&&N[e].setAttribute("shape-rendering","crispEdges"),N[e]):N[e]}function a(e){return null==k[e]?(k[e]=document.createElementNS("http://www.w3.org/2000/svg","path"),0==G&&k[e].setAttribute("shape-rendering","crispEdges"),k[e]):k[e]}function s(e){return null==A[e]?(A[e]=document.createElementNS("http://www.w3.org/2000/svg","rect"),0==G&&A[e].setAttribute("shape-rendering","crispEdges"),A[e]):A[e]}console.log("THREE.SVGRenderer",THREE.REVISION);var l,c,p,E,d,f,h,u,m,y,v,R=this,x=new THREE.Projector,T=document.createElementNS("http://www.w3.org/2000/svg","svg"),S=new THREE.Box2,H=new THREE.Box2,g=new THREE.Color,w=new THREE.Color,b=new THREE.Color,M=new THREE.Color,C=new THREE.Color,j=new THREE.Color,z=1,V=new THREE.Vector3,O=new THREE.Vector3,L=new THREE.Vector3,W=new THREE.Matrix3,B=new THREE.Matrix4,P=new THREE.Matrix4,k=[],N=[],A=[],D=0,F=0,I=0,G=1;this.domElement=T,this.autoClear=!0,this.sortObjects=!0,this.sortElements=!0,this.info={render:{vertices:0,faces:0}},this.setQuality=function(e){switch(e){case"high":G=1;break;case"low":G=0}},this.supportsVertexTextures=function(){},this.setFaceCulling=function(){},this.setClearColor=function(e,t){j.set(e),z=void 0!==t?t:1},this.setPixelRatio=function(){},this.setSize=function(e,t){E=e,d=t,f=E/2,h=d/2,T.setAttribute("viewBox",-f+" "+-h+" "+E+" "+d),T.setAttribute("width",E),T.setAttribute("height",d),S.min.set(-f,-h),S.max.set(f,h)},this.clear=function(){for(D=0,F=0,I=0;T.childNodes.length>0;)T.removeChild(T.childNodes[0]);T.style.backgroundColor="rgba("+(255*j.r|0)+","+(255*j.g|0)+","+(255*j.b|0)+","+z+")"},this.render=function(t,o){if(o instanceof THREE.Camera==!1)return void console.error("THREE.SVGRenderer.render: camera is not an instance of THREE.Camera.");this.autoClear===!0&&this.clear(),R.info.render.vertices=0,R.info.render.faces=0,B.copy(o.matrixWorldInverse.getInverse(o.matrixWorld)),P.multiplyMatrices(o.projectionMatrix,B),l=x.projectScene(t,o,this.sortObjects,this.sortElements),c=l.elements,p=l.lights,W.getNormalMatrix(o.matrixWorldInverse),e(p);for(var a=0,s=c.length;s>a;a++){var E=c[a],d=E.material;if(void 0!==d&&0!==d.opacity)if(H.makeEmpty(),E instanceof THREE.RenderableSprite)u=E,u.x*=f,u.y*=-h,r(u,E,d);else if(E instanceof THREE.RenderableLine)u=E.v1,m=E.v2,u.positionScreen.x*=f,u.positionScreen.y*=-h,m.positionScreen.x*=f,m.positionScreen.y*=-h,H.setFromPoints([u.positionScreen,m.positionScreen]),S.isIntersectionBox(H)===!0&&i(u,m,E,d);else if(E instanceof THREE.RenderableFace){if(u=E.v1,m=E.v2,y=E.v3,u.positionScreen.z<-1||u.positionScreen.z>1)continue;if(m.positionScreen.z<-1||m.positionScreen.z>1)continue;if(y.positionScreen.z<-1||y.positionScreen.z>1)continue;u.positionScreen.x*=f,u.positionScreen.y*=-h,m.positionScreen.x*=f,m.positionScreen.y*=-h,y.positionScreen.x*=f,y.positionScreen.y*=-h,H.setFromPoints([u.positionScreen,m.positionScreen,y.positionScreen]),S.isIntersectionBox(H)===!0&&n(u,m,y,E,d)}}t.traverseVisible(function(e){if(e instanceof THREE.SVGObject){V.setFromMatrixPosition(e.matrixWorld),V.applyProjection(P);var t=V.x*f,r=-V.y*h,i=e.node;i.setAttribute("transform","translate("+t+","+r+")"),T.appendChild(i)}})}};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment