sigmajs-react
Version:
Lightweight but powerful library for drawing network graphs built on top of SigmaJS
1,270 lines (1,086 loc) • 59.3 kB
JavaScript
var Sigma =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 93);
/******/ })
/************************************************************************/
/******/ ({
/***/ 61:
/***/ (function(module, exports) {
/*** IMPORTS FROM imports-loader ***/
(function () {
;(function (global) {
'use strict';
if (typeof sigma === 'undefined') throw 'sigma is not declared';
// Initialize packages:
sigma.utils.pkg('sigma.renderers');
// Check if WebGL is enabled:
var canvas,
webgl = !!global.WebGLRenderingContext;
if (webgl) {
canvas = document.createElement('canvas');
try {
webgl = !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
} catch (e) {
webgl = false;
}
}
// Copy the good renderer:
sigma.renderers.def = webgl ? sigma.renderers.webgl : sigma.renderers.canvas;
})(this);
}).call(window);
/***/ }),
/***/ 63:
/***/ (function(module, exports) {
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
/*** IMPORTS FROM imports-loader ***/
(function () {
;(function (undefined) {
'use strict';
if (typeof sigma === 'undefined') throw 'sigma is not declared';
// Initialize packages:
sigma.utils.pkg('sigma.renderers');
/**
* This function is the constructor of the canvas sigma's renderer.
*
* @param {sigma.classes.graph} graph The graph to render.
* @param {sigma.classes.camera} camera The camera.
* @param {configurable} settings The sigma instance settings
* function.
* @param {object} object The options object.
* @return {sigma.renderers.canvas} The renderer instance.
*/
sigma.renderers.webgl = function (graph, camera, settings, options) {
if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) !== 'object') throw 'sigma.renderers.webgl: Wrong arguments.';
if (!(options.container instanceof HTMLElement)) throw 'Container not found.';
var k,
i,
l,
a,
fn,
_self = this;
sigma.classes.dispatcher.extend(this);
// Conrad related attributes:
this.jobs = {};
Object.defineProperty(this, 'conradId', {
value: sigma.utils.id()
});
// Initialize main attributes:
this.graph = graph;
this.camera = camera;
this.contexts = {};
this.domElements = {};
this.options = options;
this.container = this.options.container;
this.settings = _typeof(options.settings) === 'object' && options.settings ? settings.embedObjects(options.settings) : settings;
// Find the prefix:
this.options.prefix = this.camera.readPrefix;
// Initialize programs hash
Object.defineProperty(this, 'nodePrograms', {
value: {}
});
Object.defineProperty(this, 'edgePrograms', {
value: {}
});
Object.defineProperty(this, 'nodeFloatArrays', {
value: {}
});
Object.defineProperty(this, 'edgeFloatArrays', {
value: {}
});
Object.defineProperty(this, 'edgeIndicesArrays', {
value: {}
});
// Initialize the DOM elements:
if (this.settings(options, 'batchEdgesDrawing')) {
this.initDOM('canvas', 'edges', true);
this.initDOM('canvas', 'nodes', true);
} else {
this.initDOM('canvas', 'scene', true);
this.contexts.nodes = this.contexts.scene;
this.contexts.edges = this.contexts.scene;
}
this.initDOM('canvas', 'labels');
this.initDOM('canvas', 'mouse');
this.contexts.hover = this.contexts.mouse;
// Initialize captors:
this.captors = [];
a = this.options.captors || [sigma.captors.mouse, sigma.captors.touch];
for (i = 0, l = a.length; i < l; i++) {
fn = typeof a[i] === 'function' ? a[i] : sigma.captors[a[i]];
this.captors.push(new fn(this.domElements.mouse, this.camera, this.settings));
}
// Deal with sigma events:
sigma.misc.bindEvents.call(this, this.camera.prefix);
sigma.misc.drawHovers.call(this, this.camera.prefix);
this.resize();
};
/**
* This method will generate the nodes and edges float arrays. This step is
* separated from the "render" method, because to keep WebGL efficient, since
* all the camera and middlewares are modelised as matrices and they do not
* require the float arrays to be regenerated.
*
* Basically, when the user moves the camera or applies some specific linear
* transformations, this process step will be skipped, and the "render"
* method will efficiently refresh the rendering.
*
* And when the user modifies the graph colors or positions (applying a new
* layout or filtering the colors, for instance), this "process" step will be
* required to regenerate the float arrays.
*
* @return {sigma.renderers.webgl} Returns the instance itself.
*/
sigma.renderers.webgl.prototype.process = function () {
var a,
i,
l,
k,
type,
renderer,
graph = this.graph,
options = sigma.utils.extend(options, this.options),
defaultEdgeType = this.settings(options, 'defaultEdgeType'),
defaultNodeType = this.settings(options, 'defaultNodeType');
// Empty float arrays:
for (k in this.nodeFloatArrays) {
delete this.nodeFloatArrays[k];
}for (k in this.edgeFloatArrays) {
delete this.edgeFloatArrays[k];
}for (k in this.edgeIndicesArrays) {
delete this.edgeIndicesArrays[k];
} // Sort edges and nodes per types:
for (a = graph.edges(), i = 0, l = a.length; i < l; i++) {
type = a[i].type || defaultEdgeType;
k = type && sigma.webgl.edges[type] ? type : 'def';
if (!this.edgeFloatArrays[k]) this.edgeFloatArrays[k] = {
edges: []
};
this.edgeFloatArrays[k].edges.push(a[i]);
}
for (a = graph.nodes(), i = 0, l = a.length; i < l; i++) {
type = a[i].type || defaultNodeType;
k = type && sigma.webgl.nodes[type] ? type : 'def';
if (!this.nodeFloatArrays[k]) this.nodeFloatArrays[k] = {
nodes: []
};
this.nodeFloatArrays[k].nodes.push(a[i]);
}
// Push edges:
for (k in this.edgeFloatArrays) {
renderer = sigma.webgl.edges[k];
a = this.edgeFloatArrays[k].edges;
// Creating the necessary arrays
this.edgeFloatArrays[k].array = new Float32Array(a.length * renderer.POINTS * renderer.ATTRIBUTES);
for (i = 0, l = a.length; i < l; i++) {
// Just check that the edge and both its extremities are visible:
if (!a[i].hidden && !graph.nodes(a[i].source).hidden && !graph.nodes(a[i].target).hidden) renderer.addEdge(a[i], graph.nodes(a[i].source), graph.nodes(a[i].target), this.edgeFloatArrays[k].array, i * renderer.POINTS * renderer.ATTRIBUTES, options.prefix, this.settings);
}
if (typeof renderer.computeIndices === 'function') this.edgeIndicesArrays[k] = renderer.computeIndices(this.edgeFloatArrays[k].array);
}
// Push nodes:
for (k in this.nodeFloatArrays) {
renderer = sigma.webgl.nodes[k];
a = this.nodeFloatArrays[k].nodes;
// Creating the necessary arrays
this.nodeFloatArrays[k].array = new Float32Array(a.length * renderer.POINTS * renderer.ATTRIBUTES);
for (i = 0, l = a.length; i < l; i++) {
if (!this.nodeFloatArrays[k].array) this.nodeFloatArrays[k].array = new Float32Array(a.length * renderer.POINTS * renderer.ATTRIBUTES);
// Just check that the edge and both its extremities are visible:
if (!a[i].hidden) renderer.addNode(a[i], this.nodeFloatArrays[k].array, i * renderer.POINTS * renderer.ATTRIBUTES, options.prefix, this.settings);
}
}
return this;
};
/**
* This method renders the graph. It basically calls each program (and
* generate them if they do not exist yet) to render nodes and edges, batched
* per renderer.
*
* As in the canvas renderer, it is possible to display edges, nodes and / or
* labels in batches, to make the whole thing way more scalable.
*
* @param {?object} params Eventually an object of options.
* @return {sigma.renderers.webgl} Returns the instance itself.
*/
sigma.renderers.webgl.prototype.render = function (params) {
var a,
i,
l,
k,
o,
program,
renderer,
self = this,
graph = this.graph,
nodesGl = this.contexts.nodes,
edgesGl = this.contexts.edges,
matrix = this.camera.getMatrix(),
options = sigma.utils.extend(params, this.options),
drawLabels = this.settings(options, 'drawLabels'),
drawEdges = this.settings(options, 'drawEdges'),
drawNodes = this.settings(options, 'drawNodes');
// Call the resize function:
this.resize(false);
// Check the 'hideEdgesOnMove' setting:
if (this.settings(options, 'hideEdgesOnMove')) if (this.camera.isAnimated || this.camera.isMoving) drawEdges = false;
// Clear canvases:
this.clear();
// Translate matrix to [width/2, height/2]:
matrix = sigma.utils.matrices.multiply(matrix, sigma.utils.matrices.translation(this.width / 2, this.height / 2));
// Kill running jobs:
for (k in this.jobs) {
if (conrad.hasJob(k)) conrad.killJob(k);
}if (drawEdges) {
if (this.settings(options, 'batchEdgesDrawing')) (function () {
var a, k, i, id, job, arr, end, start, indices, renderer, batchSize, currentProgram;
id = 'edges_' + this.conradId;
batchSize = this.settings(options, 'webglEdgesBatchSize');
a = Object.keys(this.edgeFloatArrays);
if (!a.length) return;
i = 0;
renderer = sigma.webgl.edges[a[i]];
arr = this.edgeFloatArrays[a[i]].array;
indices = this.edgeIndicesArrays[a[i]];
start = 0;
end = Math.min(start + batchSize * renderer.POINTS, arr.length / renderer.ATTRIBUTES);
job = function job() {
// Check program:
if (!this.edgePrograms[a[i]]) this.edgePrograms[a[i]] = renderer.initProgram(edgesGl);
if (start < end) {
edgesGl.useProgram(this.edgePrograms[a[i]]);
renderer.render(edgesGl, this.edgePrograms[a[i]], arr, {
settings: this.settings,
matrix: matrix,
width: this.width,
height: this.height,
ratio: this.camera.ratio,
scalingRatio: this.settings(options, 'webglOversamplingRatio'),
start: start,
count: end - start,
indicesData: indices
});
}
// Catch job's end:
if (end >= arr.length / renderer.ATTRIBUTES && i === a.length - 1) {
delete this.jobs[id];
return false;
}
if (end >= arr.length / renderer.ATTRIBUTES) {
i++;
arr = this.edgeFloatArrays[a[i]].array;
renderer = sigma.webgl.edges[a[i]];
start = 0;
end = Math.min(start + batchSize * renderer.POINTS, arr.length / renderer.ATTRIBUTES);
} else {
start = end;
end = Math.min(start + batchSize * renderer.POINTS, arr.length / renderer.ATTRIBUTES);
}
return true;
};
this.jobs[id] = job;
conrad.addJob(id, job.bind(this));
}).call(this);else {
for (k in this.edgeFloatArrays) {
renderer = sigma.webgl.edges[k];
// Check program:
if (!this.edgePrograms[k]) this.edgePrograms[k] = renderer.initProgram(edgesGl);
// Render
if (this.edgeFloatArrays[k]) {
edgesGl.useProgram(this.edgePrograms[k]);
renderer.render(edgesGl, this.edgePrograms[k], this.edgeFloatArrays[k].array, {
settings: this.settings,
matrix: matrix,
width: this.width,
height: this.height,
ratio: this.camera.ratio,
scalingRatio: this.settings(options, 'webglOversamplingRatio'),
indicesData: this.edgeIndicesArrays[k]
});
}
}
}
}
if (drawNodes) {
// Enable blending:
nodesGl.blendFunc(nodesGl.SRC_ALPHA, nodesGl.ONE_MINUS_SRC_ALPHA);
nodesGl.enable(nodesGl.BLEND);
for (k in this.nodeFloatArrays) {
renderer = sigma.webgl.nodes[k];
// Check program:
if (!this.nodePrograms[k]) this.nodePrograms[k] = renderer.initProgram(nodesGl);
// Render
if (this.nodeFloatArrays[k]) {
nodesGl.useProgram(this.nodePrograms[k]);
renderer.render(nodesGl, this.nodePrograms[k], this.nodeFloatArrays[k].array, {
settings: this.settings,
matrix: matrix,
width: this.width,
height: this.height,
ratio: this.camera.ratio,
scalingRatio: this.settings(options, 'webglOversamplingRatio')
});
}
}
}
if (drawLabels) {
a = this.camera.quadtree.area(this.camera.getRectangle(this.width, this.height));
// Apply camera view to these nodes:
this.camera.applyView(undefined, undefined, {
nodes: a,
edges: [],
width: this.width,
height: this.height
});
o = function o(key) {
return self.settings({
prefix: self.camera.prefix
}, key);
};
for (i = 0, l = a.length; i < l; i++) {
if (!a[i].hidden) (sigma.canvas.labels[a[i].type || this.settings(options, 'defaultNodeType')] || sigma.canvas.labels.def)(a[i], this.contexts.labels, o);
}
}
this.dispatchEvent('render');
return this;
};
/**
* This method creates a DOM element of the specified type, switches its
* position to "absolute", references it to the domElements attribute, and
* finally appends it to the container.
*
* @param {string} tag The label tag.
* @param {string} id The id of the element (to store it in
* "domElements").
* @param {?boolean} webgl Will init the WebGL context if true.
*/
sigma.renderers.webgl.prototype.initDOM = function (tag, id, webgl) {
var gl,
dom = document.createElement(tag),
self = this;
dom.style.position = 'absolute';
dom.setAttribute('class', 'sigma-' + id);
this.domElements[id] = dom;
this.container.appendChild(dom);
if (tag.toLowerCase() === 'canvas') {
this.contexts[id] = dom.getContext(webgl ? 'experimental-webgl' : '2d', {
preserveDrawingBuffer: true
});
// Adding webgl context loss listeners
if (webgl) {
dom.addEventListener('webglcontextlost', function (e) {
e.preventDefault();
}, false);
dom.addEventListener('webglcontextrestored', function (e) {
self.render();
}, false);
}
}
};
/**
* This method resizes each DOM elements in the container and stores the new
* dimensions. Then, it renders the graph.
*
* @param {?number} width The new width of the container.
* @param {?number} height The new height of the container.
* @return {sigma.renderers.webgl} Returns the instance itself.
*/
sigma.renderers.webgl.prototype.resize = function (w, h) {
var k,
oldWidth = this.width,
oldHeight = this.height,
pixelRatio = sigma.utils.getPixelRatio();
if (w !== undefined && h !== undefined) {
this.width = w;
this.height = h;
} else {
this.width = this.container.offsetWidth;
this.height = this.container.offsetHeight;
w = this.width;
h = this.height;
}
if (oldWidth !== this.width || oldHeight !== this.height) {
for (k in this.domElements) {
this.domElements[k].style.width = w + 'px';
this.domElements[k].style.height = h + 'px';
if (this.domElements[k].tagName.toLowerCase() === 'canvas') {
// If simple 2D canvas:
if (this.contexts[k] && this.contexts[k].scale) {
this.domElements[k].setAttribute('width', w * pixelRatio + 'px');
this.domElements[k].setAttribute('height', h * pixelRatio + 'px');
if (pixelRatio !== 1) this.contexts[k].scale(pixelRatio, pixelRatio);
} else {
this.domElements[k].setAttribute('width', w * this.settings('webglOversamplingRatio') + 'px');
this.domElements[k].setAttribute('height', h * this.settings('webglOversamplingRatio') + 'px');
}
}
}
}
// Scale:
for (k in this.contexts) {
if (this.contexts[k] && this.contexts[k].viewport) this.contexts[k].viewport(0, 0, this.width * this.settings('webglOversamplingRatio'), this.height * this.settings('webglOversamplingRatio'));
}return this;
};
/**
* This method clears each canvas.
*
* @return {sigma.renderers.webgl} Returns the instance itself.
*/
sigma.renderers.webgl.prototype.clear = function () {
this.contexts.labels.clearRect(0, 0, this.width, this.height);
this.contexts.nodes.clear(this.contexts.nodes.COLOR_BUFFER_BIT);
this.contexts.edges.clear(this.contexts.edges.COLOR_BUFFER_BIT);
return this;
};
/**
* This method kills contexts and other attributes.
*/
sigma.renderers.webgl.prototype.kill = function () {
var k, captor;
// Kill captors:
while (captor = this.captors.pop()) {
captor.kill();
}delete this.captors;
// Kill contexts:
for (k in this.domElements) {
this.domElements[k].parentNode.removeChild(this.domElements[k]);
delete this.domElements[k];
delete this.contexts[k];
}
delete this.domElements;
delete this.contexts;
};
/**
* The object "sigma.webgl.nodes" contains the different WebGL node
* renderers. The default one draw nodes as discs. Here are the attributes
* any node renderer must have:
*
* {number} POINTS The number of points required to draw a node.
* {number} ATTRIBUTES The number of attributes needed to draw one point.
* {function} addNode A function that adds a node to the data stack that
* will be given to the buffer. Here is the arguments:
* > {object} node
* > {number} index The node index in the
* nodes array.
* > {Float32Array} data The stack.
* > {object} options Some options.
* {function} render The function that will effectively render the nodes
* into the buffer.
* > {WebGLRenderingContext} gl
* > {WebGLProgram} program
* > {Float32Array} data The stack to give to the
* buffer.
* > {object} params An object containing some
* options, like width,
* height, the camera ratio.
* {function} initProgram The function that will initiate the program, with
* the relevant shaders and parameters. It must return
* the newly created program.
*
* Check sigma.webgl.nodes.def or sigma.webgl.nodes.fast to see how it
* works more precisely.
*/
sigma.utils.pkg('sigma.webgl.nodes');
/**
* The object "sigma.webgl.edges" contains the different WebGL edge
* renderers. The default one draw edges as direct lines. Here are the
* attributes any edge renderer must have:
*
* {number} POINTS The number of points required to draw an edge.
* {number} ATTRIBUTES The number of attributes needed to draw one point.
* {function} addEdge A function that adds an edge to the data stack that
* will be given to the buffer. Here is the arguments:
* > {object} edge
* > {object} source
* > {object} target
* > {Float32Array} data The stack.
* > {object} options Some options.
* {function} render The function that will effectively render the edges
* into the buffer.
* > {WebGLRenderingContext} gl
* > {WebGLProgram} program
* > {Float32Array} data The stack to give to the
* buffer.
* > {object} params An object containing some
* options, like width,
* height, the camera ratio.
* {function} initProgram The function that will initiate the program, with
* the relevant shaders and parameters. It must return
* the newly created program.
*
* Check sigma.webgl.edges.def or sigma.webgl.edges.fast to see how it
* works more precisely.
*/
sigma.utils.pkg('sigma.webgl.edges');
/**
* The object "sigma.canvas.labels" contains the different
* label renderers for the WebGL renderer. Since displaying texts in WebGL is
* definitely painful and since there a way less labels to display than nodes
* or edges, the default renderer simply renders them in a canvas.
*
* A labels renderer is a simple function, taking as arguments the related
* node, the renderer and a settings function.
*/
sigma.utils.pkg('sigma.canvas.labels');
}).call(this);
}).call(window);
/***/ }),
/***/ 70:
/***/ (function(module, exports) {
/*** IMPORTS FROM imports-loader ***/
(function () {
;(function () {
'use strict';
sigma.utils.pkg('sigma.webgl.edges');
/**
* This edge renderer will display edges as arrows going from the source node
* to the target node. To deal with edge thicknesses, the lines are made of
* three triangles: two forming rectangles, with the gl.TRIANGLES drawing
* mode.
*
* It is expensive, since drawing a single edge requires 9 points, each
* having a lot of attributes.
*/
sigma.webgl.edges.arrow = {
POINTS: 9,
ATTRIBUTES: 11,
addEdge: function addEdge(edge, source, target, data, i, prefix, settings) {
var w = (edge[prefix + 'size'] || 1) / 2,
x1 = source[prefix + 'x'],
y1 = source[prefix + 'y'],
x2 = target[prefix + 'x'],
y2 = target[prefix + 'y'],
targetSize = target[prefix + 'size'],
color = edge.color;
if (!color) switch (settings('edgeColor')) {
case 'source':
color = source.color || settings('defaultNodeColor');
break;
case 'target':
color = target.color || settings('defaultNodeColor');
break;
default:
color = settings('defaultEdgeColor');
break;
}
// Normalize color:
color = sigma.utils.floatColor(color);
data[i++] = x1;
data[i++] = y1;
data[i++] = x2;
data[i++] = y2;
data[i++] = w;
data[i++] = targetSize;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = color;
data[i++] = x2;
data[i++] = y2;
data[i++] = x1;
data[i++] = y1;
data[i++] = w;
data[i++] = targetSize;
data[i++] = 1.0;
data[i++] = 1.0;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = color;
data[i++] = x2;
data[i++] = y2;
data[i++] = x1;
data[i++] = y1;
data[i++] = w;
data[i++] = targetSize;
data[i++] = 1.0;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = color;
data[i++] = x2;
data[i++] = y2;
data[i++] = x1;
data[i++] = y1;
data[i++] = w;
data[i++] = targetSize;
data[i++] = 1.0;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = color;
data[i++] = x1;
data[i++] = y1;
data[i++] = x2;
data[i++] = y2;
data[i++] = w;
data[i++] = targetSize;
data[i++] = 0.0;
data[i++] = 1.0;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = color;
data[i++] = x1;
data[i++] = y1;
data[i++] = x2;
data[i++] = y2;
data[i++] = w;
data[i++] = targetSize;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = 0.0;
data[i++] = color;
// Arrow head:
data[i++] = x2;
data[i++] = y2;
data[i++] = x1;
data[i++] = y1;
data[i++] = w;
data[i++] = targetSize;
data[i++] = 1.0;
data[i++] = 0.0;
data[i++] = 1.0;
data[i++] = -1.0;
data[i++] = color;
data[i++] = x2;
data[i++] = y2;
data[i++] = x1;
data[i++] = y1;
data[i++] = w;
data[i++] = targetSize;
data[i++] = 1.0;
data[i++] = 0.0;
data[i++] = 1.0;
data[i++] = 0.0;
data[i++] = color;
data[i++] = x2;
data[i++] = y2;
data[i++] = x1;
data[i++] = y1;
data[i++] = w;
data[i++] = targetSize;
data[i++] = 1.0;
data[i++] = 0.0;
data[i++] = 1.0;
data[i++] = 1.0;
data[i++] = color;
},
render: function render(gl, program, data, params) {
var buffer;
// Define attributes:
var positionLocation1 = gl.getAttribLocation(program, 'a_pos1'),
positionLocation2 = gl.getAttribLocation(program, 'a_pos2'),
thicknessLocation = gl.getAttribLocation(program, 'a_thickness'),
targetSizeLocation = gl.getAttribLocation(program, 'a_tSize'),
delayLocation = gl.getAttribLocation(program, 'a_delay'),
minusLocation = gl.getAttribLocation(program, 'a_minus'),
headLocation = gl.getAttribLocation(program, 'a_head'),
headPositionLocation = gl.getAttribLocation(program, 'a_headPosition'),
colorLocation = gl.getAttribLocation(program, 'a_color'),
resolutionLocation = gl.getUniformLocation(program, 'u_resolution'),
matrixLocation = gl.getUniformLocation(program, 'u_matrix'),
matrixHalfPiLocation = gl.getUniformLocation(program, 'u_matrixHalfPi'),
matrixHalfPiMinusLocation = gl.getUniformLocation(program, 'u_matrixHalfPiMinus'),
ratioLocation = gl.getUniformLocation(program, 'u_ratio'),
nodeRatioLocation = gl.getUniformLocation(program, 'u_nodeRatio'),
arrowHeadLocation = gl.getUniformLocation(program, 'u_arrowHead'),
scaleLocation = gl.getUniformLocation(program, 'u_scale');
buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
gl.uniform2f(resolutionLocation, params.width, params.height);
gl.uniform1f(ratioLocation, params.ratio / Math.pow(params.ratio, params.settings('edgesPowRatio')));
gl.uniform1f(nodeRatioLocation, Math.pow(params.ratio, params.settings('nodesPowRatio')) / params.ratio);
gl.uniform1f(arrowHeadLocation, 5.0);
gl.uniform1f(scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
gl.uniformMatrix2fv(matrixHalfPiLocation, false, sigma.utils.matrices.rotation(Math.PI / 2, true));
gl.uniformMatrix2fv(matrixHalfPiMinusLocation, false, sigma.utils.matrices.rotation(-Math.PI / 2, true));
gl.enableVertexAttribArray(positionLocation1);
gl.enableVertexAttribArray(positionLocation2);
gl.enableVertexAttribArray(thicknessLocation);
gl.enableVertexAttribArray(targetSizeLocation);
gl.enableVertexAttribArray(delayLocation);
gl.enableVertexAttribArray(minusLocation);
gl.enableVertexAttribArray(headLocation);
gl.enableVertexAttribArray(headPositionLocation);
gl.enableVertexAttribArray(colorLocation);
gl.vertexAttribPointer(positionLocation1, 2, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(positionLocation2, 2, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(thicknessLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
gl.vertexAttribPointer(targetSizeLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 20);
gl.vertexAttribPointer(delayLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 24);
gl.vertexAttribPointer(minusLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 28);
gl.vertexAttribPointer(headLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 32);
gl.vertexAttribPointer(headPositionLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 36);
gl.vertexAttribPointer(colorLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 40);
gl.drawArrays(gl.TRIANGLES, params.start || 0, params.count || data.length / this.ATTRIBUTES);
},
initProgram: function initProgram(gl) {
var vertexShader, fragmentShader, program;
vertexShader = sigma.utils.loadShader(gl, ['attribute vec2 a_pos1;', 'attribute vec2 a_pos2;', 'attribute float a_thickness;', 'attribute float a_tSize;', 'attribute float a_delay;', 'attribute float a_minus;', 'attribute float a_head;', 'attribute float a_headPosition;', 'attribute float a_color;', 'uniform vec2 u_resolution;', 'uniform float u_ratio;', 'uniform float u_nodeRatio;', 'uniform float u_arrowHead;', 'uniform float u_scale;', 'uniform mat3 u_matrix;', 'uniform mat2 u_matrixHalfPi;', 'uniform mat2 u_matrixHalfPiMinus;', 'varying vec4 color;', 'void main() {',
// Find the good point:
'vec2 pos = normalize(a_pos2 - a_pos1);', 'mat2 matrix = (1.0 - a_head) *', '(', 'a_minus * u_matrixHalfPiMinus +', '(1.0 - a_minus) * u_matrixHalfPi', ') + a_head * (', 'a_headPosition * u_matrixHalfPiMinus * 0.6 +', '(a_headPosition * a_headPosition - 1.0) * mat2(1.0)', ');', 'pos = a_pos1 + (',
// Deal with body:
'(1.0 - a_head) * a_thickness * u_ratio * matrix * pos +',
// Deal with head:
'a_head * u_arrowHead * a_thickness * u_ratio * matrix * pos +',
// Deal with delay:
'a_delay * pos * (', 'a_tSize / u_nodeRatio +', 'u_arrowHead * a_thickness * u_ratio', ')', ');',
// Scale from [[-1 1] [-1 1]] to the container:
'gl_Position = vec4(', '((u_matrix * vec3(pos, 1)).xy /', 'u_resolution * 2.0 - 1.0) * vec2(1, -1),', '0,', '1', ');',
// Extract the color:
'float c = a_color;', 'color.b = mod(c, 256.0); c = floor(c / 256.0);', 'color.g = mod(c, 256.0); c = floor(c / 256.0);', 'color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;', 'color.a = 1.0;', '}'].join('\n'), gl.VERTEX_SHADER);
fragmentShader = sigma.utils.loadShader(gl, ['precision mediump float;', 'varying vec4 color;', 'void main(void) {', 'gl_FragColor = color;', '}'].join('\n'), gl.FRAGMENT_SHADER);
program = sigma.utils.loadProgram(gl, [vertexShader, fragmentShader]);
return program;
}
};
})();
}).call(window);
/***/ }),
/***/ 71:
/***/ (function(module, exports) {
/*** IMPORTS FROM imports-loader ***/
(function () {
;(function () {
'use strict';
sigma.utils.pkg('sigma.webgl.edges');
/**
* This edge renderer will display edges as lines going from the source node
* to the target node. To deal with edge thicknesses, the lines are made of
* two triangles forming rectangles, with the gl.TRIANGLES drawing mode.
*
* It is expensive, since drawing a single edge requires 6 points, each
* having 7 attributes (source position, target position, thickness, color
* and a flag indicating which vertice of the rectangle it is).
*/
sigma.webgl.edges.def = {
POINTS: 6,
ATTRIBUTES: 7,
addEdge: function addEdge(edge, source, target, data, i, prefix, settings) {
var w = (edge[prefix + 'size'] || 1) / 2,
x1 = source[prefix + 'x'],
y1 = source[prefix + 'y'],
x2 = target[prefix + 'x'],
y2 = target[prefix + 'y'],
color = edge.color;
if (!color) switch (settings('edgeColor')) {
case 'source':
color = source.color || settings('defaultNodeColor');
break;
case 'target':
color = target.color || settings('defaultNodeColor');
break;
default:
color = settings('defaultEdgeColor');
break;
}
// Normalize color:
color = sigma.utils.floatColor(color);
data[i++] = x1;
data[i++] = y1;
data[i++] = x2;
data[i++] = y2;
data[i++] = w;
data[i++] = 0.0;
data[i++] = color;
data[i++] = x2;
data[i++] = y2;
data[i++] = x1;
data[i++] = y1;
data[i++] = w;
data[i++] = 1.0;
data[i++] = color;
data[i++] = x2;
data[i++] = y2;
data[i++] = x1;
data[i++] = y1;
data[i++] = w;
data[i++] = 0.0;
data[i++] = color;
data[i++] = x2;
data[i++] = y2;
data[i++] = x1;
data[i++] = y1;
data[i++] = w;
data[i++] = 0.0;
data[i++] = color;
data[i++] = x1;
data[i++] = y1;
data[i++] = x2;
data[i++] = y2;
data[i++] = w;
data[i++] = 1.0;
data[i++] = color;
data[i++] = x1;
data[i++] = y1;
data[i++] = x2;
data[i++] = y2;
data[i++] = w;
data[i++] = 0.0;
data[i++] = color;
},
render: function render(gl, program, data, params) {
var buffer;
// Define attributes:
var colorLocation = gl.getAttribLocation(program, 'a_color'),
positionLocation1 = gl.getAttribLocation(program, 'a_position1'),
positionLocation2 = gl.getAttribLocation(program, 'a_position2'),
thicknessLocation = gl.getAttribLocation(program, 'a_thickness'),
minusLocation = gl.getAttribLocation(program, 'a_minus'),
resolutionLocation = gl.getUniformLocation(program, 'u_resolution'),
matrixLocation = gl.getUniformLocation(program, 'u_matrix'),
matrixHalfPiLocation = gl.getUniformLocation(program, 'u_matrixHalfPi'),
matrixHalfPiMinusLocation = gl.getUniformLocation(program, 'u_matrixHalfPiMinus'),
ratioLocation = gl.getUniformLocation(program, 'u_ratio'),
scaleLocation = gl.getUniformLocation(program, 'u_scale');
buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
gl.uniform2f(resolutionLocation, params.width, params.height);
gl.uniform1f(ratioLocation, params.ratio / Math.pow(params.ratio, params.settings('edgesPowRatio')));
gl.uniform1f(scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
gl.uniformMatrix2fv(matrixHalfPiLocation, false, sigma.utils.matrices.rotation(Math.PI / 2, true));
gl.uniformMatrix2fv(matrixHalfPiMinusLocation, false, sigma.utils.matrices.rotation(-Math.PI / 2, true));
gl.enableVertexAttribArray(colorLocation);
gl.enableVertexAttribArray(positionLocation1);
gl.enableVertexAttribArray(positionLocation2);
gl.enableVertexAttribArray(thicknessLocation);
gl.enableVertexAttribArray(minusLocation);
gl.vertexAttribPointer(positionLocation1, 2, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(positionLocation2, 2, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(thicknessLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
gl.vertexAttribPointer(minusLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 20);
gl.vertexAttribPointer(colorLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 24);
gl.drawArrays(gl.TRIANGLES, params.start || 0, params.count || data.length / this.ATTRIBUTES);
},
initProgram: function initProgram(gl) {
var vertexShader, fragmentShader, program;
vertexShader = sigma.utils.loadShader(gl, ['attribute vec2 a_position1;', 'attribute vec2 a_position2;', 'attribute float a_thickness;', 'attribute float a_minus;', 'attribute float a_color;', 'uniform vec2 u_resolution;', 'uniform float u_ratio;', 'uniform float u_scale;', 'uniform mat3 u_matrix;', 'uniform mat2 u_matrixHalfPi;', 'uniform mat2 u_matrixHalfPiMinus;', 'varying vec4 color;', 'void main() {',
// Find the good point:
'vec2 position = a_thickness * u_ratio *', 'normalize(a_position2 - a_position1);', 'mat2 matrix = a_minus * u_matrixHalfPiMinus +', '(1.0 - a_minus) * u_matrixHalfPi;', 'position = matrix * position + a_position1;',
// Scale from [[-1 1] [-1 1]] to the container:
'gl_Position = vec4(', '((u_matrix * vec3(position, 1)).xy /', 'u_resolution * 2.0 - 1.0) * vec2(1, -1),', '0,', '1', ');',
// Extract the color:
'float c = a_color;', 'color.b = mod(c, 256.0); c = floor(c / 256.0);', 'color.g = mod(c, 256.0); c = floor(c / 256.0);', 'color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;', 'color.a = 1.0;', '}'].join('\n'), gl.VERTEX_SHADER);
fragmentShader = sigma.utils.loadShader(gl, ['precision mediump float;', 'varying vec4 color;', 'void main(void) {', 'gl_FragColor = color;', '}'].join('\n'), gl.FRAGMENT_SHADER);
program = sigma.utils.loadProgram(gl, [vertexShader, fragmentShader]);
return program;
}
};
})();
}).call(window);
/***/ }),
/***/ 72:
/***/ (function(module, exports) {
/*** IMPORTS FROM imports-loader ***/
(function () {
;(function () {
'use strict';
sigma.utils.pkg('sigma.webgl.edges');
/**
* This edge renderer will display edges as lines with the gl.LINES display
* mode. Since this mode does not support well thickness, edges are all drawn
* with the same thickness (3px), independantly of the edge attributes or the
* zooming ratio.
*/
sigma.webgl.edges.fast = {
POINTS: 2,
ATTRIBUTES: 3,
addEdge: function addEdge(edge, source, target, data, i, prefix, settings) {
var w = (edge[prefix + 'size'] || 1) / 2,
x1 = source[prefix + 'x'],
y1 = source[prefix + 'y'],
x2 = target[prefix + 'x'],
y2 = target[prefix + 'y'],
color = edge.color;
if (!color) switch (settings('edgeColor')) {
case 'source':
color = source.color || settings('defaultNodeColor');
break;
case 'target':
color = target.color || settings('defaultNodeColor');
break;
default:
color = settings('defaultEdgeColor');
break;
}
// Normalize color:
color = sigma.utils.floatColor(color);
data[i++] = x1;
data[i++] = y1;
data[i++] = color;
data[i++] = x2;
data[i++] = y2;
data[i++] = color;
},
render: function render(gl, program, data, params) {
var buffer;
// Define attributes:
var colorLocation = gl.getAttribLocation(program, 'a_color'),
positionLocation = gl.getAttribLocation(program, 'a_position'),
resolutionLocation = gl.getUniformLocation(program, 'u_resolution'),
matrixLocation = gl.getUniformLocation(program, 'u_matrix');
buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
gl.uniform2f(resolutionLocation, params.width, params.height);
gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
gl.enableVertexAttribArray(positionLocation);
gl.enableVertexAttribArray(colorLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(colorLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.lineWidth(3);
gl.drawArrays(gl.LINES, params.start || 0, params.count || data.length / this.ATTRIBUTES);
},
initProgram: function initProgram(gl) {
var vertexShader, fragmentShader, program;
vertexShader = sigma.utils.loadShader(gl, ['attribute vec2 a_position;', 'attribute float a_color;', 'uniform vec2 u_resolution;', 'uniform mat3 u_matrix;', 'varying vec4 color;', 'void main() {',
// Scale from [[-1 1] [-1 1]] to the container:
'gl_Position = vec4(', '((u_matrix * vec3(a_position, 1)).xy /', 'u_resolution * 2.0 - 1.0) * vec2(1, -1),', '0,', '1', ');',
// Extract the color:
'float c = a_color;', 'color.b = mod(c, 256.0); c = floor(c / 256.0);', 'color.g = mod(c, 256.0); c = floor(c / 256.0);', 'color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;', 'color.a = 1.0;', '}'].join('\n'), gl.VERTEX_SHADER);
fragmentShader = sigma.utils.loadShader(gl, ['precision mediump float;', 'varying vec4 color;', 'void main(void) {', 'gl_FragColor = color;', '}'].join('\n'), gl.FRAGMENT_SHADER);
program = sigma.utils.loadProgram(gl, [vertexShader, fragmentShader]);
return program;
}
};
})();
}).call(window);
/***/ }),
/***/ 73:
/***/ (function(module, exports) {
/*** IMPORTS FROM imports-loader ***/
(function () {
;(function () {
'use strict';
sigma.utils.pkg('sigma.webgl.nodes');
/**
* This node renderer will display nodes as discs, shaped in triangles with
* the gl.TRIANGLES display mode. So, to be more precise, to draw one node,
* it will store three times the center of node, with the color and the size,
* and an angle indicating which "corner" of the triangle to draw.
*
* The fragment shader does not deal with anti-aliasing, so make sure that
* you deal with it somewhere else in the code (by default, the WebGL
* renderer will oversample the rendering through the webglOversamplingRatio
* value).
*/
sigma.webgl.nodes.def = {
POINTS: 3,
ATTRIBUTES: 5,
addNode: function addNode(node, data, i, prefix, settings) {
var color = sigma.utils.floatColor(node.color || settings('defaultNodeColor'));
data[i++] = node[prefix + 'x'];
data[i++] = node[prefix + 'y'];
data[i++] = node[prefix + 'size'];
data[i++] = color;
data[i++] = 0;
data[i++] = node[prefix + 'x'];
data[i++] = node[prefix + 'y'];
data[i++] = node[prefix + 'size'];
data[i++] = color;
data[i++] = 2 * Math.PI / 3;
data[i++] = node[prefix + 'x'];
data[i++] = node[prefix + 'y'];
data[i++] = node[prefix + 'size'];
data[i++] = color;
data[i++] = 4 * Math.PI / 3;
},
render: function render(gl, program, data, params) {
var buffer;
// Define attributes:
var positionLocation = gl.getAttribLocation(program, 'a_position'),
sizeLocation = gl.getAttribLocation(program, 'a_size'),
colorLocation = gl.getAttribLocation(program, 'a_color'),
angleLocation = gl.getAttribLocation(program, 'a_angle'),
resolutionLocation = gl.getUniformLocation(program, 'u_resolution'),
matrixLocation = gl.getUniformLocation(program, 'u_matrix'),
ratioLocation = gl.getUniformLocation(program, 'u_ratio'),
scaleLocation = gl.getUniformLocation(program, 'u_scale');
buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
gl.uniform2f(resolutionLocation, params.width, params.height);
gl.uniform1f(ratioLocation, 1 / Math.pow(params.ratio, params.settings('nodesPowRatio')));
gl.uniform1f(scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
gl.enableVertexAttribArray(positionLocation);
gl.enableVertexAttribArray(sizeLocation);
gl.enableVertexAttribArray(colorLocation);
gl.enableVertexAttribArray(angleLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(sizeLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(colorLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 12);
gl.vertexAttribPointer(angleLocation, 1, gl.FLOAT, false, this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
gl.drawArrays(gl.TRIANGLES, params.start || 0, params.count || data.length / this.ATTRIBUTES);
},
initProgram: function initProgram(gl) {
var vertexShader, fragmentShader, program;
vertexShader = sigma.utils.loadShader(gl, ['attribute vec2 a_position;', 'attribute float a_size;', 'attribute float a_color;', 'attribute float a_angle;', 'uniform vec2 u_resolution;', 'u