New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

sigma

Package Overview
Dependencies
Maintainers
2
Versions
117
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sigma - npm Package Compare versions

Comparing version 2.0.0-alpha4 to 2.0.0-alpha40

.idea/codeStyles/codeStyleConfig.xml

559

camera.js

@@ -1,47 +0,52 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _events = require('events');
var _easings = require('./easings');
var easings = _interopRequireWildcard(_easings);
var _utils = require('./utils');
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Sigma.js Camera Class
* ======================
*
* Class designed to store camera information & used to update it.
*/
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sigma.js Camera Class
* ======================
*
* Class designed to store camera information & used to update it.
*/
var events_1 = require("events");
var easings = __importStar(require("./easings"));
var utils_1 = require("./utils");
/**
* Defaults.
*/
var ANIMATE_DEFAULTS = {
easing: 'quadraticInOut',
duration: 150
easing: "quadraticInOut",
duration: 150,
};
var DEFAULT_ZOOMING_RATIO = 1.5;
// TODO: animate options = number polymorphism?
// TODO: pan, zoom, unzoom, reset, rotate, zoomTo
// TODO: add width / height to camera and add #.resize
// TODO: bind camera to renderer rather than sigma
// TODO: add #.graphToDisplay, #.displayToGraph, batch methods later
/**

@@ -52,42 +57,26 @@ * Camera class

*/
var Camera = function (_EventEmitter) {
_inherits(Camera, _EventEmitter);
function Camera(dimensions) {
_classCallCheck(this, Camera);
dimensions = dimensions || {};
// Properties
var _this = _possibleConstructorReturn(this, (Camera.__proto__ || Object.getPrototypeOf(Camera)).call(this));
_this.x = 0;
_this.y = 0;
_this.angle = 0;
_this.ratio = 1;
_this.width = dimensions.width || 0;
_this.height = dimensions.height || 0;
// State
_this.nextFrame = null;
_this.enabled = true;
return _this;
}
/**
* Method used to enable the camera.
*
* @return {Camera}
*/
_createClass(Camera, [{
key: 'enable',
value: function enable() {
this.enabled = true;
return this;
var Camera = /** @class */ (function (_super) {
__extends(Camera, _super);
function Camera() {
var _this = _super.call(this) || this;
_this.x = 0.5;
_this.y = 0.5;
_this.angle = 0;
_this.ratio = 1;
_this.nextFrame = null;
_this.enabled = true;
// State
_this.previousState = _this.getState();
return _this;
}
/**
* Method used to enable the camera.
*
* @return {Camera}
*/
Camera.prototype.enable = function () {
this.enabled = true;
return this;
};
/**
* Method used to disable the camera.

@@ -97,10 +86,6 @@ *

*/
}, {
key: 'disable',
value: function disable() {
this.enabled = false;
return this;
}
Camera.prototype.disable = function () {
this.enabled = false;
return this;
};
/**

@@ -111,29 +96,24 @@ * Method used to retrieve the camera's current state.

*/
}, {
key: 'getState',
value: function getState() {
return {
x: this.x,
y: this.y,
angle: this.angle,
ratio: this.ratio
};
}
Camera.prototype.getState = function () {
return {
x: this.x,
y: this.y,
angle: this.angle,
ratio: this.ratio,
};
};
/**
* Method used to retrieve the camera's dimensions.
* Method used to retrieve the camera's previous state.
*
* @return {object}
*/
}, {
key: 'getDimensions',
value: function getDimensions() {
return {
width: this.width,
height: this.height
};
}
Camera.prototype.getPreviousState = function () {
var state = this.previousState;
return {
x: state.x,
y: state.y,
angle: state.angle,
ratio: state.ratio,
};
};
/**

@@ -144,80 +124,63 @@ * Method used to check whether the camera is currently being animated.

*/
}, {
key: 'isAnimated',
value: function isAnimated() {
return !!this.nextFrame;
}
Camera.prototype.isAnimated = function () {
return !!this.nextFrame;
};
/**
* Method returning the coordinates of a point from the display frame to the
* graph one but ignores the offset and dimensions of the container.
* Method returning the coordinates of a point from the graph frame to the
* viewport.
*
* @param {number} x The X coordinate.
* @param {number} y The Y coordinate.
* @return {object} The point coordinates in the frame of the graph.
* @param {object} dimensions - Dimensions of the viewport.
* @param {number} x - The X coordinate.
* @param {number} y - The Y coordinate.
* @return {object} - The point coordinates in the viewport.
*/
}, {
key: 'abstractDisplayToGraph',
value: function abstractDisplayToGraph(x, y) {
var cos = Math.cos(this.angle),
sin = Math.sin(this.angle);
return {
x: (x * cos - y * sin) * this.ratio,
y: (y * cos + x * sin) * this.ratio
};
}
// TODO: assign to gain one object
// TODO: angles
Camera.prototype.graphToViewport = function (dimensions, x, y) {
var smallestDimension = Math.min(dimensions.width, dimensions.height);
var dx = smallestDimension / dimensions.width, dy = smallestDimension / dimensions.height;
// TODO: we keep on the upper left corner!
// TODO: how to normalize sizes?
return {
x: (x - this.x + this.ratio / 2 / dx) * (smallestDimension / this.ratio),
y: (this.y - y + this.ratio / 2 / dy) * (smallestDimension / this.ratio),
};
};
/**
* Method returning the coordinates of a point from the display frame to the
* graph one.
* Method returning the coordinates of a point from the viewport frame to the
* graph frame.
*
* @param {number} x The X coordinate.
* @param {number} y The Y coordinate.
* @return {object} The point coordinates in the frame of the graph.
* @param {object} dimensions - Dimensions of the viewport.
* @param {number} x - The X coordinate.
* @param {number} y - The Y coordinate.
* @return {object} - The point coordinates in the graph frame.
*/
}, {
key: 'displayToGraph',
value: function displayToGraph(x, y) {
var cos = Math.cos(this.angle),
sin = Math.sin(this.angle);
var xOffset = this.width / 2 - (this.x * cos + this.y * sin) / this.ratio,
yOffset = this.height / 2 - (this.y * cos - this.x * sin) / this.ratio;
var X = x - xOffset,
Y = y - yOffset;
return {
x: (X * cos - Y * sin) * this.ratio,
y: (Y * cos + X * sin) * this.ratio
};
}
// TODO: angles
Camera.prototype.viewportToGraph = function (dimensions, x, y) {
var smallestDimension = Math.min(dimensions.width, dimensions.height);
var dx = smallestDimension / dimensions.width, dy = smallestDimension / dimensions.height;
return {
x: (this.ratio / smallestDimension) * x + this.x - this.ratio / 2 / dx,
y: -((this.ratio / smallestDimension) * y - this.y - this.ratio / 2 / dy),
};
};
/**
* Method returning the coordinates of a point from the graph frame to the
* display one.
* Method returning the abstract rectangle containing the graph according
* to the camera's state.
*
* @param {number} x The X coordinate.
* @param {number} y The Y coordinate.
* @return {object} The point coordinates in the frame of the display.
* @return {object} - The view's rectangle.
*/
}, {
key: 'graphToDisplay',
value: function graphToDisplay(x, y) {
var relCos = Math.cos(this.angle) / this.ratio,
relSin = Math.sin(this.angle) / this.ratio,
xOffset = this.width / 2 - this.x * relCos - this.y * relSin,
yOffset = this.height / 2 - this.y * relCos + this.x * relSin;
return {
x: x * relCos + y * relSin + xOffset,
y: y * relCos - x * relSin + yOffset
};
}
// TODO: angle
Camera.prototype.viewRectangle = function (dimensions) {
// TODO: reduce relative margin?
var marginX = (0 * dimensions.width) / 8, marginY = (0 * dimensions.height) / 8;
var p1 = this.viewportToGraph(dimensions, 0 - marginX, 0 - marginY), p2 = this.viewportToGraph(dimensions, dimensions.width + marginX, 0 - marginY), h = this.viewportToGraph(dimensions, 0, dimensions.height + marginY);
return {
x1: p1.x,
y1: p1.y,
x2: p2.x,
y2: p2.y,
height: p2.y - h.y,
};
};
/**

@@ -229,50 +192,23 @@ * Method used to set the camera's state.

*/
}, {
key: 'setState',
value: function setState(state) {
if (!this.enabled) return this;
// TODO: validations
// TODO: update by function
if ('x' in state) this.x = state.x;
if ('y' in state) this.y = state.y;
if ('angle' in state) this.angle = state.angle;
if ('ratio' in state) this.ratio = state.ratio;
// Emitting
// TODO: don't emit if nothing changed?
this.emit('updated', this.getState());
return this;
}
Camera.prototype.setState = function (state) {
if (!this.enabled)
return this;
// TODO: validations
// TODO: update by function
// Keeping track of last state
this.previousState = this.getState();
if ("x" in state)
this.x = state.x;
if ("y" in state)
this.y = state.y;
if ("angle" in state)
this.angle = state.angle;
if ("ratio" in state)
this.ratio = state.ratio;
// Emitting
// TODO: don't emit if nothing changed?
this.emit("updated", this.getState());
return this;
};
/**
* Method used to resize the camera's dimensions.
*
* @param {object} dimensions - New dimensions.
* @return {Camera}
*/
}, {
key: 'resize',
value: function resize(dimensions) {
if (!this.enabled) return this;
if ('width' in dimensions) this.width = dimensions.width;
if ('height' in dimensions) this.height = dimensions.height;
this.emit('resized', this.getDimensions());
return this;
}
/**
* Method used to animate the camera.

@@ -286,57 +222,46 @@ *

*/
}, {
key: 'animate',
value: function animate(state, options /*, callback */) {
var _this2 = this;
if (!this.enabled) return this;
// TODO: validation
options = (0, _utils.assign)({}, ANIMATE_DEFAULTS, options);
var easing = typeof options.easing === 'function' ? options.easing : easings[options.easing];
// Canceling previous animation if needed
if (this.nextFrame) cancelAnimationFrame(this.nextFrame);
// State
var start = Date.now(),
initialState = this.getState();
// Function performing the animation
var fn = function fn() {
var t = (Date.now() - start) / options.duration;
// The animation is over:
if (t >= 1) {
_this2.nextFrame = null;
_this2.setState(state);
return;
Camera.prototype.animate = function (state, options, callback) {
var _this = this;
if (!this.enabled)
return this;
// TODO: validation
options = utils_1.assign({}, ANIMATE_DEFAULTS, options);
var easing = typeof options.easing === "function" ? options.easing : easings[options.easing];
// Canceling previous animation if needed
if (this.nextFrame)
cancelAnimationFrame(this.nextFrame);
// State
var start = Date.now(), initialState = this.getState();
// Function performing the animation
var fn = function () {
var t = (Date.now() - start) / options.duration;
// The animation is over:
if (t >= 1) {
_this.nextFrame = null;
_this.setState(state);
if (typeof callback === "function")
callback();
return;
}
var coefficient = easing(t);
var newState = {};
if ("x" in state)
newState.x = initialState.x + (state.x - initialState.x) * coefficient;
if ("y" in state)
newState.y = initialState.y + (state.y - initialState.y) * coefficient;
if ("angle" in state)
newState.angle = initialState.angle + (state.angle - initialState.angle) * coefficient;
if ("ratio" in state)
newState.ratio = initialState.ratio + (state.ratio - initialState.ratio) * coefficient;
_this.setState(newState);
_this.nextFrame = requestAnimationFrame(fn);
};
if (this.nextFrame) {
cancelAnimationFrame(this.nextFrame);
this.nextFrame = requestAnimationFrame(fn);
}
var coefficient = easing(t);
var newState = {};
if ('x' in state) newState.x = initialState.x + (state.x - initialState.x) * coefficient;
if ('y' in state) newState.y = initialState.y + (state.y - initialState.y) * coefficient;
if ('angle' in state) newState.angle = initialState.angle + (state.angle - initialState.angle) * coefficient;
if ('ratio' in state) newState.ratio = initialState.ratio + (state.ratio - initialState.ratio) * coefficient;
_this2.setState(newState);
_this2.nextFrame = requestAnimationFrame(fn);
};
if (this.nextFrame) {
cancelAnimationFrame(this.nextFrame);
this.nextFrame = requestAnimationFrame(fn);
} else {
fn();
}
}
else {
fn();
}
};
/**

@@ -348,14 +273,15 @@ * Method used to zoom the camera.

*/
}, {
key: 'animatedZoom',
value: function animatedZoom(factorOrOptions) {
if (!factorOrOptions) {
return this.animate({ ratio: this.ratio / DEFAULT_ZOOMING_RATIO });
} else {
if (typeof factorOrOptions === 'number') return this.animate({ ratio: this.ratio / factorOrOptions });else return this.animate({ ratio: this.ratio / (factorOrOptions.factor || DEFAULT_ZOOMING_RATIO) }, factorOrOptions);
}
}
Camera.prototype.animatedZoom = function (factorOrOptions) {
if (!factorOrOptions) {
return this.animate({ ratio: this.ratio / DEFAULT_ZOOMING_RATIO });
}
else {
if (typeof factorOrOptions === "number")
return this.animate({ ratio: this.ratio / factorOrOptions });
else
return this.animate({
ratio: this.ratio / (factorOrOptions.factor || DEFAULT_ZOOMING_RATIO),
}, factorOrOptions);
}
};
/**

@@ -367,14 +293,15 @@ * Method used to unzoom the camera.

*/
}, {
key: 'animatedUnzoom',
value: function animatedUnzoom(factorOrOptions) {
if (!factorOrOptions) {
return this.animate({ ratio: this.ratio * DEFAULT_ZOOMING_RATIO });
} else {
if (typeof factorOrOptions === 'number') return this.animate({ ratio: this.ratio * factorOrOptions });else return this.animate({ ratio: this.ratio * (factorOrOptions.factor || DEFAULT_ZOOMING_RATIO) }, factorOrOptions);
}
}
Camera.prototype.animatedUnzoom = function (factorOrOptions) {
if (!factorOrOptions) {
return this.animate({ ratio: this.ratio * DEFAULT_ZOOMING_RATIO });
}
else {
if (typeof factorOrOptions === "number")
return this.animate({ ratio: this.ratio * factorOrOptions });
else
return this.animate({
ratio: this.ratio * (factorOrOptions.factor || DEFAULT_ZOOMING_RATIO),
}, factorOrOptions);
}
};
/**

@@ -386,18 +313,12 @@ * Method used to reset the camera.

*/
}, {
key: 'animatedReset',
value: function animatedReset(options) {
return this.animate({
x: 0,
y: 0,
ratio: 1,
angle: 0
}, options);
}
}]);
return Camera;
}(_events.EventEmitter);
exports.default = Camera;
Camera.prototype.animatedReset = function (options) {
return this.animate({
x: 0.5,
y: 0.5,
ratio: 1,
angle: 0,
}, options);
};
return Camera;
}(events_1.EventEmitter));
exports.default = Camera;

@@ -1,38 +0,34 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _events = require('events');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Sigma.js Captor Class
* ======================
*
* Abstract class representing a captor like the user's mouse or touch controls.
*/
var Captor = function (_EventEmitter) {
_inherits(Captor, _EventEmitter);
function Captor(container, camera) {
_classCallCheck(this, Captor);
// Properties
var _this = _possibleConstructorReturn(this, (Captor.__proto__ || Object.getPrototypeOf(Captor)).call(this));
_this.container = container;
_this.camera = camera;
return _this;
}
return Captor;
}(_events.EventEmitter);
exports.default = Captor;
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sigma.js Captor Class
* ======================
*
* Abstract class representing a captor like the user's mouse or touch controls.
*/
var events_1 = require("events");
var Captor = /** @class */ (function (_super) {
__extends(Captor, _super);
function Captor(container, camera) {
var _this = _super.call(this) || this;
// Properties
_this.container = container;
_this.camera = camera;
return _this;
}
return Captor;
}(events_1.EventEmitter));
exports.default = Captor;

@@ -1,41 +0,39 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _captor = require('../captor');
var _captor2 = _interopRequireDefault(_captor);
var _utils = require('./utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Sigma.js Mouse Captor
* ======================
*
* Sigma's captor dealing with the user's mouse.
*/
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sigma.js Mouse Captor
* ======================
*
* Sigma's captor dealing with the user's mouse.
*/
var camera_1 = __importDefault(require("../camera"));
var captor_1 = __importDefault(require("../captor"));
var utils_1 = require("./utils");
/**
* Constants.
*/
var DRAG_TIMEOUT = 200,
MOUSE_INERTIA_DURATION = 200,
MOUSE_INERTIA_RATIO = 3,
MOUSE_ZOOM_DURATION = 200,
ZOOMING_RATIO = 1.7,
DOUBLE_CLICK_TIMEOUT = 300,
DOUBLE_CLICK_ZOOMING_RATIO = 2.2,
DOUBLE_CLICK_ZOOMING_DURATION = 200;
var DRAG_TIMEOUT = 200;
var MOUSE_INERTIA_DURATION = 200;
var MOUSE_INERTIA_RATIO = 3;
var MOUSE_ZOOM_DURATION = 200;
var ZOOMING_RATIO = 1.7;
var DOUBLE_CLICK_TIMEOUT = 300;
var DOUBLE_CLICK_ZOOMING_RATIO = 2.2;
var DOUBLE_CLICK_ZOOMING_DURATION = 200;
/**

@@ -46,262 +44,242 @@ * Mouse captor class.

*/
var MouseCaptor = function (_Captor) {
_inherits(MouseCaptor, _Captor);
function MouseCaptor(container, camera) {
_classCallCheck(this, MouseCaptor);
// Properties
var _this = _possibleConstructorReturn(this, (MouseCaptor.__proto__ || Object.getPrototypeOf(MouseCaptor)).call(this, container, camera));
_this.container = container;
_this.camera = camera;
// State
_this.enabled = true;
_this.hasDragged = false;
_this.downStartTime = null;
_this.startMouseX = null;
_this.startMouseY = null;
_this.isMouseDown = false;
_this.isMoving = true;
_this.movingTimeout = null;
_this.startCameraState = null;
_this.lastCameraState = null;
_this.clicks = 0;
_this.doubleClickTimeout = null;
_this.wheelLock = false;
// Binding methods
_this.handleClick = _this.handleClick.bind(_this);
_this.handleDown = _this.handleDown.bind(_this);
_this.handleUp = _this.handleUp.bind(_this);
_this.handleMove = _this.handleMove.bind(_this);
_this.handleWheel = _this.handleWheel.bind(_this);
_this.handleOut = _this.handleOut.bind(_this);
// Binding events
container.addEventListener('click', _this.handleClick, false);
container.addEventListener('mousedown', _this.handleDown, false);
container.addEventListener('mousemove', _this.handleMove, false);
container.addEventListener('DOMMouseScroll', _this.handleWheel, false);
container.addEventListener('mousewheel', _this.handleWheel, false);
container.addEventListener('mouseout', _this.handleOut, false);
document.addEventListener('mouseup', _this.handleUp, false);
return _this;
}
_createClass(MouseCaptor, [{
key: 'handleClick',
value: function handleClick(e) {
var _this2 = this;
if (!this.enabled) return;
this.clicks++;
if (this.clicks === 2) {
this.clicks = 0;
clearTimeout(this.doubleClickTimeout);
this.doubleClickTimeout = null;
return this.handleDoubleClick(e);
}
setTimeout(function () {
_this2.clicks = 0;
_this2.doubleClickTimeout = null;
}, DOUBLE_CLICK_TIMEOUT);
this.emit('click', (0, _utils.getMouseCoords)(e, this.container.offsetLeft, this.container.offsetTop));
var MouseCaptor = /** @class */ (function (_super) {
__extends(MouseCaptor, _super);
function MouseCaptor(container, camera) {
var _this = _super.call(this, container, camera) || this;
// State
_this.enabled = true;
_this.hasDragged = false;
_this.downStartTime = null;
_this.lastMouseX = null;
_this.lastMouseY = null;
_this.isMouseDown = false;
_this.isMoving = null;
_this.movingTimeout = null;
_this.startCameraState = null;
_this.lastCameraState = null;
_this.clicks = 0;
_this.doubleClickTimeout = null;
_this.wheelLock = false;
// Binding methods
_this.handleClick = _this.handleClick.bind(_this);
_this.handleRightClick = _this.handleRightClick.bind(_this);
_this.handleDown = _this.handleDown.bind(_this);
_this.handleUp = _this.handleUp.bind(_this);
_this.handleMove = _this.handleMove.bind(_this);
_this.handleWheel = _this.handleWheel.bind(_this);
_this.handleOut = _this.handleOut.bind(_this);
// Binding events
container.addEventListener("click", _this.handleClick, false);
container.addEventListener("contextmenu", _this.handleRightClick, false);
container.addEventListener("mousedown", _this.handleDown, false);
container.addEventListener("mousemove", _this.handleMove, false);
container.addEventListener("DOMMouseScroll", _this.handleWheel, false);
container.addEventListener("mousewheel", _this.handleWheel, false);
container.addEventListener("mouseout", _this.handleOut, false);
document.addEventListener("mouseup", _this.handleUp, false);
return _this;
}
}, {
key: 'handleDoubleClick',
value: function handleDoubleClick(e) {
if (!this.enabled) return;
var ratio = 1 / DOUBLE_CLICK_ZOOMING_RATIO;
var center = (0, _utils.getCenter)(e);
var cameraState = this.camera.getState();
var position = this.camera.abstractDisplayToGraph((0, _utils.getX)(e) - center.x, (0, _utils.getY)(e) - center.y);
this.camera.animate({
x: position.x * (1 - ratio) + cameraState.x,
y: position.y * (1 - ratio) + cameraState.y,
ratio: ratio * cameraState.ratio
}, {
easing: 'quadraticInOut',
duration: DOUBLE_CLICK_ZOOMING_DURATION
});
if (e.preventDefault) e.preventDefault();else e.returnValue = false;
e.stopPropagation();
return false;
}
}, {
key: 'handleDown',
value: function handleDown(e) {
if (!this.enabled) return;
this.startCameraState = this.camera.getState();
this.lastCameraState = this.startCameraState;
this.startMouseX = (0, _utils.getX)(e);
this.startMouseY = (0, _utils.getY)(e);
this.hasDragged = false;
this.downStartTime = Date.now();
// TODO: dispatch events
switch (e.which) {
default:
// Left button pressed
this.isMouseDown = true;
this.emit('mousedown', (0, _utils.getMouseCoords)(e, this.container.offsetLeft, this.container.offsetTop));
}
}
}, {
key: 'handleUp',
value: function handleUp(e) {
if (!this.enabled || !this.isMouseDown) return;
this.isMouseDown = false;
if (this.movingTimeout) {
this.movingTimeout = null;
clearTimeout(this.movingTimeout);
}
var x = (0, _utils.getX)(e),
y = (0, _utils.getY)(e);
var cameraState = this.camera.getState();
if (this.isMoving) {
MouseCaptor.prototype.kill = function () {
var container = this.container;
container.removeEventListener("click", this.handleClick);
container.removeEventListener("contextmenu", this.handleRightClick);
container.removeEventListener("mousedown", this.handleDown);
container.removeEventListener("mousemove", this.handleMove);
container.removeEventListener("DOMMouseScroll", this.handleWheel);
container.removeEventListener("mousewheel", this.handleWheel);
container.removeEventListener("mouseout", this.handleOut);
document.removeEventListener("mouseup", this.handleUp);
};
MouseCaptor.prototype.handleClick = function (e) {
var _this = this;
if (!this.enabled)
return;
this.clicks++;
if (this.clicks === 2) {
this.clicks = 0;
clearTimeout(this.doubleClickTimeout);
this.doubleClickTimeout = null;
return this.handleDoubleClick(e);
}
setTimeout(function () {
_this.clicks = 0;
_this.doubleClickTimeout = null;
}, DOUBLE_CLICK_TIMEOUT);
// NOTE: this is here to prevent click events on drag
if (!this.hasDragged)
this.emit("click", utils_1.getMouseCoords(e));
};
MouseCaptor.prototype.handleRightClick = function (e) {
if (!this.enabled)
return;
this.emit("rightClick", utils_1.getMouseCoords(e));
};
MouseCaptor.prototype.handleDoubleClick = function (e) {
if (!this.enabled)
return;
var center = utils_1.getCenter(e);
var cameraState = this.camera.getState();
var newRatio = cameraState.ratio / DOUBLE_CLICK_ZOOMING_RATIO;
// TODO: factorize
var dimensions = {
width: this.container.offsetWidth,
height: this.container.offsetHeight,
};
var clickX = utils_1.getX(e), clickY = utils_1.getY(e);
// TODO: baaaad we mustn't mutate the camera, create a Camera.from or #.copy
// TODO: factorize pan & zoomTo
var cameraWithNewRatio = new camera_1.default();
cameraWithNewRatio.ratio = newRatio;
cameraWithNewRatio.x = cameraState.x;
cameraWithNewRatio.y = cameraState.y;
var clickGraph = this.camera.viewportToGraph(dimensions, clickX, clickY), centerGraph = this.camera.viewportToGraph(dimensions, center.x, center.y);
var clickGraphNew = cameraWithNewRatio.viewportToGraph(dimensions, clickX, clickY), centerGraphNew = cameraWithNewRatio.viewportToGraph(dimensions, center.x, center.y);
var deltaX = clickGraphNew.x - centerGraphNew.x - clickGraph.x + centerGraph.x, deltaY = clickGraphNew.y - centerGraphNew.y - clickGraph.y + centerGraph.y;
this.camera.animate({
x: cameraState.x + MOUSE_INERTIA_RATIO * (cameraState.x - this.lastCameraState.x),
y: cameraState.y + MOUSE_INERTIA_RATIO * (cameraState.y - this.lastCameraState.y)
x: cameraState.x - deltaX,
y: cameraState.y - deltaY,
ratio: newRatio,
}, {
duration: MOUSE_INERTIA_DURATION,
easing: 'quadraticOut'
easing: "quadraticInOut",
duration: DOUBLE_CLICK_ZOOMING_DURATION,
});
} else if (this.startMouseX !== x || this.startMouseY !== y) {
this.camera.setState({
x: cameraState.x,
y: cameraState.y
});
}
this.emit('mouseup', (0, _utils.getMouseCoords)(e, this.container.offsetLeft, this.container.offsetTop));
this.isMoving = false;
}
}, {
key: 'handleMove',
value: function handleMove(e) {
var _this3 = this;
if (!this.enabled) return;
this.emit('mousemove', (0, _utils.getMouseCoords)(e, this.container.offsetLeft, this.container.offsetTop));
if (this.isMouseDown) {
if (e.preventDefault)
e.preventDefault();
else
e.returnValue = false;
e.stopPropagation();
return false;
};
MouseCaptor.prototype.handleDown = function (e) {
if (!this.enabled)
return;
this.startCameraState = this.camera.getState();
this.lastCameraState = this.startCameraState;
this.lastMouseX = utils_1.getX(e);
this.lastMouseY = utils_1.getY(e);
this.hasDragged = false;
this.downStartTime = Date.now();
// TODO: dispatch events
this.isMoving = true;
this.hasDragged = true;
if (this.movingTimeout) clearTimeout(this.movingTimeout);
this.movingTimeout = setTimeout(function () {
_this3.movingTimeout = null;
_this3.isMoving = false;
}, DRAG_TIMEOUT);
var position = this.camera.abstractDisplayToGraph((0, _utils.getX)(e) - this.startMouseX, (0, _utils.getY)(e) - this.startMouseY);
var x = this.startCameraState.x - position.x,
y = this.startCameraState.y - position.y;
switch (e.which) {
default:
// Left button pressed
this.isMouseDown = true;
this.emit("mousedown", utils_1.getMouseCoords(e));
}
};
MouseCaptor.prototype.handleUp = function (e) {
var _this = this;
if (!this.enabled || !this.isMouseDown)
return;
this.isMouseDown = false;
if (this.movingTimeout) {
this.movingTimeout = null;
clearTimeout(this.movingTimeout);
}
var x = utils_1.getX(e), y = utils_1.getY(e);
var cameraState = this.camera.getState(), previousCameraState = this.camera.getPreviousState();
if (this.isMoving) {
this.camera.animate({
x: cameraState.x + MOUSE_INERTIA_RATIO * (cameraState.x - previousCameraState.x),
y: cameraState.y + MOUSE_INERTIA_RATIO * (cameraState.y - previousCameraState.y),
}, {
duration: MOUSE_INERTIA_DURATION,
easing: "quadraticOut",
});
}
else if (this.lastMouseX !== x || this.lastMouseY !== y) {
this.camera.setState({
x: cameraState.x,
y: cameraState.y,
});
}
this.isMoving = false;
setImmediate(function () { return (_this.hasDragged = false); });
this.emit("mouseup", utils_1.getMouseCoords(e));
};
MouseCaptor.prototype.handleMove = function (e) {
var _this = this;
if (!this.enabled)
return;
this.emit("mousemove", utils_1.getMouseCoords(e));
if (this.isMouseDown) {
// TODO: dispatch events
this.isMoving = true;
this.hasDragged = true;
if (this.movingTimeout)
clearTimeout(this.movingTimeout);
this.movingTimeout = window.setTimeout(function () {
_this.movingTimeout = null;
_this.isMoving = false;
}, DRAG_TIMEOUT);
var dimensions = {
width: this.container.offsetWidth,
height: this.container.offsetHeight,
};
var eX = utils_1.getX(e), eY = utils_1.getY(e);
var lastMouse = this.camera.viewportToGraph(dimensions, this.lastMouseX, this.lastMouseY);
var mouse = this.camera.viewportToGraph(dimensions, eX, eY);
var offsetX = lastMouse.x - mouse.x, offsetY = lastMouse.y - mouse.y;
var cameraState = this.camera.getState();
var x = cameraState.x + offsetX, y = cameraState.y + offsetY;
this.camera.setState({ x: x, y: y });
this.lastMouseX = eX;
this.lastMouseY = eY;
}
if (e.preventDefault)
e.preventDefault();
else
e.returnValue = false;
e.stopPropagation();
return false;
};
MouseCaptor.prototype.handleWheel = function (e) {
var _this = this;
if (e.preventDefault)
e.preventDefault();
else
e.returnValue = false;
e.stopPropagation();
if (!this.enabled)
return false;
var delta = utils_1.getWheelDelta(e);
if (!delta)
return false;
if (this.wheelLock)
return false;
this.wheelLock = true;
// TODO: handle max zoom
var ratio = delta > 0 ? 1 / ZOOMING_RATIO : ZOOMING_RATIO;
var cameraState = this.camera.getState();
if (cameraState.x !== x || cameraState.y !== y) {
this.lastCameraState = cameraState;
this.camera.setState({
x: x,
y: y
});
}
}
if (e.preventDefault) e.preventDefault();else e.returnValue = false;
e.stopPropagation();
return false;
}
}, {
key: 'handleWheel',
value: function handleWheel(e) {
var _this4 = this;
if (!this.enabled) return false;
var delta = (0, _utils.getWheelDelta)(e);
if (!delta) return false;
if (this.wheelLock) return false;
this.wheelLock = true;
setTimeout(function () {
return _this4.wheelLock = false;
}, 30);
// TODO: handle max zoom
var ratio = delta > 0 ? 1 / ZOOMING_RATIO : ZOOMING_RATIO;
var cameraState = this.camera.getState();
var newRatio = ratio * cameraState.ratio;
var center = (0, _utils.getCenter)(e);
var position = this.camera.abstractDisplayToGraph((0, _utils.getX)(e) - center.x, (0, _utils.getY)(e) - center.y);
this.camera.animate({
x: position.x * (1 - ratio) + cameraState.x,
y: position.y * (1 - ratio) + cameraState.y,
ratio: newRatio
}, {
easing: this.camera.isAnimated() ? 'quadraticOut' : 'quadraticInOut',
duration: MOUSE_ZOOM_DURATION
});
if (e.preventDefault) e.preventDefault();else e.returnValue = false;
e.stopPropagation();
return false;
}
}, {
key: 'handleOut',
value: function handleOut() {
// TODO: dispatch event
}
}]);
return MouseCaptor;
}(_captor2.default);
exports.default = MouseCaptor;
var newRatio = ratio * cameraState.ratio;
var center = utils_1.getCenter(e);
var dimensions = {
width: this.container.offsetWidth,
height: this.container.offsetHeight,
};
var clickX = utils_1.getX(e), clickY = utils_1.getY(e);
// TODO: baaaad we mustn't mutate the camera, create a Camera.from or #.copy
// TODO: factorize pan & zoomTo
var cameraWithNewRatio = new camera_1.default();
cameraWithNewRatio.ratio = newRatio;
cameraWithNewRatio.x = cameraState.x;
cameraWithNewRatio.y = cameraState.y;
var clickGraph = this.camera.viewportToGraph(dimensions, clickX, clickY), centerGraph = this.camera.viewportToGraph(dimensions, center.x, center.y);
var clickGraphNew = cameraWithNewRatio.viewportToGraph(dimensions, clickX, clickY), centerGraphNew = cameraWithNewRatio.viewportToGraph(dimensions, center.x, center.y);
var deltaX = clickGraphNew.x - centerGraphNew.x - clickGraph.x + centerGraph.x, deltaY = clickGraphNew.y - centerGraphNew.y - clickGraph.y + centerGraph.y;
this.camera.animate({
x: cameraState.x - deltaX,
y: cameraState.y - deltaY,
ratio: newRatio,
}, {
easing: "linear",
duration: MOUSE_ZOOM_DURATION,
}, function () { return (_this.wheelLock = false); });
return false;
};
MouseCaptor.prototype.handleOut = function () {
// TODO: dispatch event
};
return MouseCaptor;
}(captor_1.default));
exports.default = MouseCaptor;

@@ -1,26 +0,12 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
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; }; /**
* Sigma.js Captor Utils
* ======================
*
* Miscellenous helper functions related to the captors.
*/
exports.getX = getX;
exports.getY = getY;
exports.getWidth = getWidth;
exports.getHeight = getHeight;
exports.getCenter = getCenter;
exports.getMouseCoords = getMouseCoords;
exports.getWheelDelta = getWheelDelta;
var _utils = require('../renderers/utils');
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getWheelDelta = exports.getMouseCoords = exports.getCenter = exports.getHeight = exports.getWidth = exports.getY = exports.getX = void 0;
/**
* Sigma.js Captor Utils
* ======================
*
* Miscellenous helper functions related to the captors.
*/
var utils_1 = require("../renderers/utils");
/**
* Extract the local X position from a mouse or touch event.

@@ -32,11 +18,9 @@ *

function getX(e) {
if (typeof e.offsetX !== 'undefined') return e.offsetX;
if (typeof e.layerX !== 'undefined') return e.layerX;
if (typeof e.clientX !== 'undefined') return e.clientX;
throw new Error('sigma/captors/utils.getX: could not extract x from event.');
if (typeof e.offsetX !== "undefined")
return e.offsetX;
if (typeof e.clientX !== "undefined")
return e.clientX;
throw new Error("sigma/captors/utils.getX: could not extract x from event.");
}
exports.getX = getX;
/**

@@ -49,11 +33,9 @@ * Extract the local Y position from a mouse or touch event.

function getY(e) {
if (typeof e.offsetY !== 'undefined') return e.offsetY;
if (typeof e.layerY !== 'undefined') return e.layerY;
if (typeof e.clientY !== 'undefined') return e.clientY;
throw new Error('sigma/captors/utils.getY: could not extract y from event.');
if (typeof e.offsetY !== "undefined")
return e.offsetY;
if (typeof e.clientY !== "undefined")
return e.clientY;
throw new Error("sigma/captors/utils.getY: could not extract y from event.");
}
exports.getY = getY;
/**

@@ -66,11 +48,8 @@ * Extract the width from a mouse or touch event.

function getWidth(e) {
var w = !e.target.ownerSVGElement ? e.target.width : e.target.ownerSVGElement.width;
if (typeof w === 'number') return w;
if (w !== undefined && w.baseVal !== undefined) return w.baseVal.value;
throw new Error('sigma/captors/utils.getWidth: could not extract width from event.');
var w = e.target.width;
if (typeof w === "number")
return w;
throw new Error("sigma/captors/utils.getWidth: could not extract width from event.");
}
exports.getWidth = getWidth;
/**

@@ -83,11 +62,8 @@ * Extract the height from a mouse or touch event.

function getHeight(e) {
var w = !e.target.ownerSVGElement ? e.target.height : e.target.ownerSVGElement.height;
if (typeof w === 'number') return w;
if (w !== undefined && w.baseVal !== undefined) return w.baseVal.value;
throw new Error('sigma/captors/utils.getHeight: could not extract height from event.');
var w = e.target.height;
if (typeof w === "number")
return w;
throw new Error("sigma/captors/utils.getHeight: could not extract height from event.");
}
exports.getHeight = getHeight;
/**

@@ -100,10 +76,9 @@ * Extract the center from a mouse or touch event.

function getCenter(e) {
var ratio = e.target.namespaceURI.indexOf('svg') !== -1 ? 1 : (0, _utils.getPixelRatio)();
return {
x: getWidth(e) / (2 * ratio),
y: getHeight(e) / (2 * ratio)
};
var ratio = utils_1.getPixelRatio();
return {
x: getWidth(e) / (2 * ratio),
y: getHeight(e) / (2 * ratio),
};
}
exports.getCenter = getCenter;
/**

@@ -118,21 +93,18 @@ * Convert mouse coords to sigma coords.

*/
function getMouseCoords(e, x, y) {
if (arguments.length < 2) {
x = getX(e);
y = getY(e);
}
// const center = getCenter(e);
return {
x: e.clientX - x,
y: e.clientY - y,
clientX: e.clientX,
clientY: e.clientY,
ctrlKey: e.ctrlKey,
metaKey: e.metaKey,
altKey: e.altKey,
shiftKey: e.shiftKey
};
function getMouseCoords(e) {
return {
x: getX(e),
y: getY(e),
clientX: e.clientX,
clientY: e.clientY,
ctrlKey: e.ctrlKey,
metaKey: e.metaKey,
altKey: e.altKey,
shiftKey: e.shiftKey,
// TODO: this is not ideal... But I am wondering why we don't just pass the event through
preventDefault: e.preventDefault.bind(e),
original: e,
};
}
exports.getMouseCoords = getMouseCoords;
/**

@@ -145,7 +117,9 @@ * Extract the wheel delta from a mouse or touch event.

function getWheelDelta(e) {
if (_typeof(e.wheelDelta) !== undefined) return e.wheelDelta;
if (_typeof(e.detail) !== undefined) return -e.detail;
throw new Error('sigma/captors/utils.getDelta: could not extract delta from event.');
}
// TODO: check those ratios again to ensure a clean Chrome/Firefox compat
if (typeof e.deltaY !== "undefined")
return (e.deltaY * -3) / 360;
if (typeof e.detail !== "undefined")
return e.detail / -9;
throw new Error("sigma/captors/utils.getDelta: could not extract delta from event.");
}
exports.getWheelDelta = getWheelDelta;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "__esModule", { value: true });
exports.cubicInOut = exports.cubicOut = exports.cubicIn = exports.quadraticInOut = exports.quadraticOut = exports.quadraticIn = exports.linear = void 0;
/**

@@ -12,30 +10,16 @@ * Sigma.js Easings

*/
var linear = exports.linear = function linear(k) {
return k;
exports.linear = function (k) { return k; };
exports.quadraticIn = function (k) { return k * k; };
exports.quadraticOut = function (k) { return k * (2 - k); };
exports.quadraticInOut = function (k) {
if ((k *= 2) < 1)
return 0.5 * k * k;
return -0.5 * (--k * (k - 2) - 1);
};
var quadraticIn = exports.quadraticIn = function quadraticIn(k) {
return k * k;
exports.cubicIn = function (k) { return k * k * k; };
exports.cubicOut = function (k) { return --k * k * k + 1; };
exports.cubicInOut = function (k) {
if ((k *= 2) < 1)
return 0.5 * k * k * k;
return 0.5 * ((k -= 2) * k * k + 2);
};
var quadraticOut = exports.quadraticOut = function quadraticOut(k) {
return k * (2 - k);
};
var quadraticInOut = exports.quadraticInOut = function quadraticInOut(k) {
if ((k *= 2) < 1) return 0.5 * k * k;
return -0.5 * (--k * (k - 2) - 1);
};
var cubicIn = exports.cubicIn = function cubicIn(k) {
return k * k * k;
};
var cubicOut = exports.cubicOut = function cubicOut(k) {
return --k * k * k + 1;
};
var cubicInOut = exports.cubicInOut = function cubicInOut(k) {
if ((k *= 2) < 1) return 0.5 * k * k * k;
return 0.5 * ((k -= 2) * k * k + 2);
};

@@ -1,29 +0,7 @@

'use strict';
var _sigma = require('./sigma');
var _sigma2 = _interopRequireDefault(_sigma);
var _renderer = require('./renderer');
var _renderer2 = _interopRequireDefault(_renderer);
var _camera = require('./camera');
var _camera2 = _interopRequireDefault(_camera);
var _quadtree = require('./quadtree');
var _quadtree2 = _interopRequireDefault(_quadtree);
var _mouse = require('./captors/mouse');
var _mouse2 = _interopRequireDefault(_mouse);
var _webgl = require('./renderers/webgl');
var _webgl2 = _interopRequireDefault(_webgl);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebGLRenderer = exports.MouseCaptor = exports.QuadTree = exports.Camera = exports.Renderer = void 0;
/**

@@ -35,13 +13,11 @@ * Sigma.js Library Endpoint

*/
var library = {
Sigma: _sigma2.default,
Renderer: _renderer2.default,
Camera: _camera2.default,
QuadTree: _quadtree2.default,
MouseCaptor: _mouse2.default,
WebGLRenderer: _webgl2.default
};
for (var k in library) {
_sigma2.default[k] = library[k];
}module.exports = _sigma2.default;
var renderer_1 = __importDefault(require("./renderer"));
exports.Renderer = renderer_1.default;
var camera_1 = __importDefault(require("./camera"));
exports.Camera = camera_1.default;
var quadtree_1 = __importDefault(require("./quadtree"));
exports.QuadTree = quadtree_1.default;
var mouse_1 = __importDefault(require("./captors/mouse"));
exports.MouseCaptor = mouse_1.default;
var webgl_1 = __importDefault(require("./renderers/webgl"));
exports.WebGLRenderer = webgl_1.default;

@@ -1,2 +0,2 @@

Copyright (C) 2013-2017, Alexis Jacomy, Guillaume Plique http://sigmajs.org
Copyright (C) 2013-2020, Alexis Jacomy, Guillaume Plique http://sigmajs.org

@@ -3,0 +3,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),

{
"name": "sigma",
"version": "2.0.0-alpha4",
"version": "2.0.0-alpha40",
"description": "A JavaScript library dedicated to graph drawing.",
"homepage": "http://sigmajs.org",
"bugs": "http://github.com/jacomyal/sigma.js/issues",
"main": "sigma.js",
"main": "endpoint.js",
"typings": "types/endpoint.d.ts",
"scripts": {
"build": "webpack --colors --progress && webpack --colors --progress -p",
"clean": "rimraf $npm_package_sigma_clean",
"dist": "npm run clean && babel src --out-dir . && webpack --config ./webpack.programs.config.js",
"transpile": "tsc -p ./tsconfig.dist.json -d --declarationDir types && replace '\\.glsl' '.glsl.js' renderers -r && webpack --config ./webpack.programs.config.js",
"examples": "webpack-dev-server --config ./examples/webpack.config.js --progress",
"lint": "eslint examples src test",
"gitignore": "jq -r '.sigma.clean' package.json | tr ' ' '\\n' >> .gitignore",
"lint": "eslint $npm_package_sigma_folders",
"postpublish": "npm run clean",
"prepublish": "npm run test && npm run dist && npm run build",
"test": "mocha --compilers js:babel-core/register ./test/endpoint.js"
"prettier": "prettier --write $npm_package_sigma_folders",
"prepublish": "echo \"Linter should go here...\" && npm run test && npm run clean && npm run transpile && npm run build",
"test": "mocha --require ts-node/register --recursive test --extension ts",
"types": "npx tsc --declaration --emitDeclarationOnly --outDir lib"
},
"sigma": {
"clean": "camera.js captor.js easings.js endpoint.js quadtree.js renderer.js sigma.js utils.js captors renderers"
"clean": "animate.js camera.js captor.js easings.js endpoint.js quadtree.js renderer.js sigma-graphology.js utils.js captors heuristics renderers types",
"folders": "examples src test"
},

@@ -36,23 +41,41 @@ "repository": {

"license": "MIT",
"dependencies": {
"@yomguithereal/helpers": "^1.0.0",
"events": "^3.0.0",
"graphology-metrics": "1.13.0",
"graphology-utils": "^1.4.0"
},
"devDependencies": {
"@yomguithereal/eslint-config": "^4.0.0",
"babel-cli": "^6.24.1",
"babel-core": "^6.14.0",
"babel-loader": "^7.0.0",
"babel-preset-es2015": "^6.14.0",
"chroma-js": "^1.3.3",
"eslint": "^4.0.0",
"@babel/core": "^7.9.6",
"@types/mocha": "^7.0.2",
"@typescript-eslint/eslint-plugin": "^3.3.0",
"@typescript-eslint/parser": "^3.3.0",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"chroma-js": "^2.1.0",
"d3-scale": "^3.2.1",
"eslint": "^7.3.0",
"faker": "^4.1.0",
"graphology": "^0.10.2",
"graphology-generators": "^0.6.1",
"graphology-gexf": "^0.3.1",
"graphology-layout": "0.0.1",
"graphology-layout-forceatlas2": "0.1.0",
"html-webpack-plugin": "^2.22.0",
"mocha": "^3.0.2",
"raw-loader": "^0.5.1",
"rimraf": "^2.6.1",
"webpack": "^2.5.1",
"webpack-dev-server": "^2.4.5",
"worker-loader": "^0.8.0"
"glob": "^7.1.3",
"graphology": "^0.17.1",
"graphology-communities-louvain": "^1.2.0",
"graphology-components": "^0.1.0",
"graphology-generators": "^0.10.1",
"graphology-gexf": "^0.5.0",
"graphology-layout": "0.3.1",
"graphology-layout-forceatlas2": "^0.4.4",
"html-webpack-plugin": "^3.2.0",
"mocha": "^8.0.1",
"pandemonium": "^1.4.1",
"prettier": "^2.0.5",
"raw-loader": "^4.0.1",
"replace": "^1.2.0",
"rimraf": "^3.0.0",
"simple-statistics": "^7.0.7",
"ts-loader": "^7.0.2",
"ts-node": "^8.10.1",
"typescript": "^3.8.3",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.9"
},

@@ -63,19 +86,18 @@ "keywords": [

"renderer",
"sigma",
"canvas",
"webgl",
"svg"
"webgl"
],
"babel": {
"presets": [
"es2015"
]
},
"eslintConfig": {
"extends": "@yomguithereal/eslint-config/es6"
},
"dependencies": {
"events": "^1.1.1",
"gl-matrix": "^2.3.2",
"graphology-utils": "^1.1.1"
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"extends": [
"plugin:@typescript-eslint/recommended"
],
"rules": {
"@typescript-eslint/camelcase": "off"
}
}
}
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint no-nested-ternary: 0 */
/* eslint no-constant-condition: 0 */
/**

@@ -20,14 +16,13 @@ * Sigma.js Quad Tree Class

*/
var extend_1 = __importDefault(require("@yomguithereal/helpers/extend"));
// TODO: should not ask the quadtree when the camera has the whole graph in
// sight.
// TODO: a square can be represented as topleft + width
// TODO: a square can be represented as topleft + width, saying for the quad blocks (reduce mem)
// TODO: jsdoc
// TODO: be sure we can handle cases overcoming boundaries (because of size) or use a max
// TODO: decide whether to store at leaf level or at medium levels (frustum vs. hover)
// TODO: be sure we can handle cases overcoming boundaries (because of size) or use a maxed size
// TODO: filtering unwanted labels beforehand through the filter function
// NOTE: this is basically a MX-CIF Quadtree at this point
// NOTE: need to explore R-Trees for edges
// NOTE: need to explore 2d segment tree for edges
// NOTE: probably can do faster using spatial hashing
/**

@@ -43,19 +38,8 @@ * Constants.

*/
var BLOCKS = 4,
MAX_LEVEL = 5;
var X_OFFSET = 0,
Y_OFFSET = 1,
WIDTH_OFFSET = 2,
HEIGHT_OFFSET = 3;
var TOP_LEFT = 1,
TOP_RIGHT = 2,
BOTTOM_LEFT = 3,
BOTTOM_RIGHT = 4;
var BLOCKS = 4, MAX_LEVEL = 5;
var X_OFFSET = 0, Y_OFFSET = 1, WIDTH_OFFSET = 2, HEIGHT_OFFSET = 3;
var TOP_LEFT = 1, TOP_RIGHT = 2, BOTTOM_LEFT = 3, BOTTOM_RIGHT = 4;
/**
* Geometry helpers.
*/
/**

@@ -71,18 +55,14 @@ * Function returning whether the given rectangle is axis-aligned.

function isAxisAligned(x1, y1, x2, y2) {
return x1 === x2 || y1 === y2;
return x1 === x2 || y1 === y2;
}
function rectangleCollidesWithQuad(x1, y1, w, qx, qy, qw, qh) {
return x1 < qx + qw && x1 + w > qx && y1 < qy + qh && y1 + w > qy;
function squareCollidesWithQuad(x1, y1, w, qx, qy, qw, qh) {
return x1 < qx + qw && x1 + w > qx && y1 < qy + qh && y1 + w > qy;
}
function rectangleCollidesWithQuad(x1, y1, w, h, qx, qy, qw, qh) {
return x1 < qx + qw && x1 + w > qx && y1 < qy + qh && y1 + h > qy;
}
function pointIsInQuad(x, y, qx, qy, qw, qh) {
var xmp = qx + qw / 2,
ymp = qy + qh / 2,
top = y < ymp,
left = x < xmp;
return top ? left ? TOP_LEFT : TOP_RIGHT : left ? BOTTOM_LEFT : BOTTOM_RIGHT;
var xmp = qx + qw / 2, ymp = qy + qh / 2, top = y < ymp, left = x < xmp;
return top ? (left ? TOP_LEFT : TOP_RIGHT) : left ? BOTTOM_LEFT : BOTTOM_RIGHT;
}
/**

@@ -93,114 +73,141 @@ * Helper functions that are not bound to the class so an external user

function buildQuadrants(maxLevel, data) {
// [block, level]
var stack = [0, 0];
while (stack.length) {
var level = stack.pop(),
block = stack.pop();
var topLeftBlock = 4 * block + BLOCKS,
topRightBlock = 4 * block + 2 * BLOCKS,
bottomLeftBlock = 4 * block + 3 * BLOCKS,
bottomRightBlock = 4 * block + 4 * BLOCKS;
var x = data[block + X_OFFSET],
y = data[block + Y_OFFSET],
width = data[block + WIDTH_OFFSET],
height = data[block + HEIGHT_OFFSET],
hw = width / 2,
hh = height / 2;
data[topLeftBlock + X_OFFSET] = x;
data[topLeftBlock + Y_OFFSET] = y;
data[topLeftBlock + WIDTH_OFFSET] = hw;
data[topLeftBlock + HEIGHT_OFFSET] = hh;
data[topRightBlock + X_OFFSET] = x + hw;
data[topRightBlock + Y_OFFSET] = y;
data[topRightBlock + WIDTH_OFFSET] = hw;
data[topRightBlock + HEIGHT_OFFSET] = hh;
data[bottomLeftBlock + X_OFFSET] = x;
data[bottomLeftBlock + Y_OFFSET] = y + hh;
data[bottomLeftBlock + WIDTH_OFFSET] = hw;
data[bottomLeftBlock + HEIGHT_OFFSET] = hh;
data[bottomRightBlock + X_OFFSET] = x + hw;
data[bottomRightBlock + Y_OFFSET] = y + hh;
data[bottomRightBlock + WIDTH_OFFSET] = hw;
data[bottomRightBlock + HEIGHT_OFFSET] = hh;
if (level < maxLevel - 1) {
stack.push(bottomRightBlock, level + 1);
stack.push(bottomLeftBlock, level + 1);
stack.push(topRightBlock, level + 1);
stack.push(topLeftBlock, level + 1);
// [block, level]
var stack = [0, 0];
while (stack.length) {
var level = stack.pop(), block = stack.pop();
var topLeftBlock = 4 * block + BLOCKS, topRightBlock = 4 * block + 2 * BLOCKS, bottomLeftBlock = 4 * block + 3 * BLOCKS, bottomRightBlock = 4 * block + 4 * BLOCKS;
var x = data[block + X_OFFSET], y = data[block + Y_OFFSET], width = data[block + WIDTH_OFFSET], height = data[block + HEIGHT_OFFSET], hw = width / 2, hh = height / 2;
data[topLeftBlock + X_OFFSET] = x;
data[topLeftBlock + Y_OFFSET] = y;
data[topLeftBlock + WIDTH_OFFSET] = hw;
data[topLeftBlock + HEIGHT_OFFSET] = hh;
data[topRightBlock + X_OFFSET] = x + hw;
data[topRightBlock + Y_OFFSET] = y;
data[topRightBlock + WIDTH_OFFSET] = hw;
data[topRightBlock + HEIGHT_OFFSET] = hh;
data[bottomLeftBlock + X_OFFSET] = x;
data[bottomLeftBlock + Y_OFFSET] = y + hh;
data[bottomLeftBlock + WIDTH_OFFSET] = hw;
data[bottomLeftBlock + HEIGHT_OFFSET] = hh;
data[bottomRightBlock + X_OFFSET] = x + hw;
data[bottomRightBlock + Y_OFFSET] = y + hh;
data[bottomRightBlock + WIDTH_OFFSET] = hw;
data[bottomRightBlock + HEIGHT_OFFSET] = hh;
if (level < maxLevel - 1) {
stack.push(bottomRightBlock, level + 1);
stack.push(bottomLeftBlock, level + 1);
stack.push(topRightBlock, level + 1);
stack.push(topLeftBlock, level + 1);
}
}
}
}
function insertNode(maxLevel, data, containers, key, x, y, size) {
var x1 = x - size,
y1 = y - size,
w = size * 2;
// [block, level]
// TODO: does not require a stack if sticking with mid-level containers
var stack = [0, 0];
while (stack.length) {
var level = stack.pop();
var block = stack.pop();
// If we reached max level
if (level >= maxLevel) {
containers[block] = containers[block] || [];
containers[block].push(key);
return;
var x1 = x - size, y1 = y - size, w = size * 2;
var level = 0, block = 0;
while (true) {
// If we reached max level
if (level >= maxLevel) {
containers[block] = containers[block] || [];
containers[block].push(key);
return;
}
var topLeftBlock = 4 * block + BLOCKS, topRightBlock = 4 * block + 2 * BLOCKS, bottomLeftBlock = 4 * block + 3 * BLOCKS, bottomRightBlock = 4 * block + 4 * BLOCKS;
var collidingWithTopLeft = squareCollidesWithQuad(x1, y1, w, data[topLeftBlock + X_OFFSET], data[topLeftBlock + Y_OFFSET], data[topLeftBlock + WIDTH_OFFSET], data[topLeftBlock + HEIGHT_OFFSET]);
var collidingWithTopRight = squareCollidesWithQuad(x1, y1, w, data[topRightBlock + X_OFFSET], data[topRightBlock + Y_OFFSET], data[topRightBlock + WIDTH_OFFSET], data[topRightBlock + HEIGHT_OFFSET]);
var collidingWithBottomLeft = squareCollidesWithQuad(x1, y1, w, data[bottomLeftBlock + X_OFFSET], data[bottomLeftBlock + Y_OFFSET], data[bottomLeftBlock + WIDTH_OFFSET], data[bottomLeftBlock + HEIGHT_OFFSET]);
var collidingWithBottomRight = squareCollidesWithQuad(x1, y1, w, data[bottomRightBlock + X_OFFSET], data[bottomRightBlock + Y_OFFSET], data[bottomRightBlock + WIDTH_OFFSET], data[bottomRightBlock + HEIGHT_OFFSET]);
var collisions = [
collidingWithTopLeft,
collidingWithTopRight,
collidingWithBottomLeft,
collidingWithBottomRight,
].reduce(function (acc, current) {
if (current)
return acc + 1;
else
return acc;
}, 0);
// If we don't have at least a collision, there is an issue
if (collisions === 0)
throw new Error("sigma/quadtree.insertNode: no collision (level: " + level + ", key: " + key + ", x: " + x + ", y: " + y + ", size: " + size + ").");
// If we have 3 collisions, we have a geometry problem obviously
if (collisions === 3)
throw new Error("sigma/quadtree.insertNode: 3 impossible collisions (level: " + level + ", key: " + key + ", x: " + x + ", y: " + y + ", size: " + size + ").");
// If we have more that one collision, we stop here and store the node
// in the relevant containers
if (collisions > 1) {
// NOTE: this is a nice way to optimize for hover, but not for frustum
// since it requires to uniq the collected nodes
// if (collisions < 4) {
// // If we intersect two quads, we place the node in those two
// if (collidingWithTopLeft) {
// containers[topLeftBlock] = containers[topLeftBlock] || [];
// containers[topLeftBlock].push(key);
// }
// if (collidingWithTopRight) {
// containers[topRightBlock] = containers[topRightBlock] || [];
// containers[topRightBlock].push(key);
// }
// if (collidingWithBottomLeft) {
// containers[bottomLeftBlock] = containers[bottomLeftBlock] || [];
// containers[bottomLeftBlock].push(key);
// }
// if (collidingWithBottomRight) {
// containers[bottomRightBlock] = containers[bottomRightBlock] || [];
// containers[bottomRightBlock].push(key);
// }
// }
// else {
// // Else we keep the node where it is to avoid more pointless computations
// containers[block] = containers[block] || [];
// containers[block].push(key);
// }
containers[block] = containers[block] || [];
containers[block].push(key);
return;
}
else {
level++;
}
// Else we recurse into the correct quads
if (collidingWithTopLeft)
block = topLeftBlock;
if (collidingWithTopRight)
block = topRightBlock;
if (collidingWithBottomLeft)
block = bottomLeftBlock;
if (collidingWithBottomRight)
block = bottomRightBlock;
}
var topLeftBlock = 4 * block + BLOCKS,
topRightBlock = 4 * block + 2 * BLOCKS,
bottomLeftBlock = 4 * block + 3 * BLOCKS,
bottomRightBlock = 4 * block + 4 * BLOCKS;
var collidingWithTopLeft = rectangleCollidesWithQuad(x1, y1, w, data[topLeftBlock + X_OFFSET], data[topLeftBlock + Y_OFFSET], data[topLeftBlock + WIDTH_OFFSET], data[topLeftBlock + HEIGHT_OFFSET]);
var collidingWithTopRight = rectangleCollidesWithQuad(x1, y1, w, data[topRightBlock + X_OFFSET], data[topRightBlock + Y_OFFSET], data[topRightBlock + WIDTH_OFFSET], data[topRightBlock + HEIGHT_OFFSET]);
var collidingWithBottomLeft = rectangleCollidesWithQuad(x1, y1, w, data[bottomLeftBlock + X_OFFSET], data[bottomLeftBlock + Y_OFFSET], data[bottomLeftBlock + WIDTH_OFFSET], data[bottomLeftBlock + HEIGHT_OFFSET]);
var collidingWithBottomRight = rectangleCollidesWithQuad(x1, y1, w, data[bottomRightBlock + X_OFFSET], data[bottomRightBlock + Y_OFFSET], data[bottomRightBlock + WIDTH_OFFSET], data[bottomRightBlock + HEIGHT_OFFSET]);
var collisions = collidingWithTopLeft + collidingWithTopRight + collidingWithBottomLeft + collidingWithBottomRight;
// If we don't have at least a collision, there is an issue
if (collisions === 0) throw new Error("sigma/quadtree.insertNode: no collision (level: " + level + ", key: " + key + ", x: " + x + ", y: " + y + ", size: " + size + ").");
// If we have 3 collisions, we have a geometry problem obviously
if (collisions === 3) throw new Error("sigma/quadtree.insertNode: 3 impossible collisions (level: " + level + ", key: " + key + ", x: " + x + ", y: " + y + ", size: " + size + ").");
// If we have more that one collision, we stop here and store the node
// in the relevant containers
if (collisions > 1) {
containers[block] = containers[block] || [];
containers[block].push(key);
return;
} else {
level++;
}
function getNodesInAxisAlignedRectangleArea(maxLevel, data, containers, x1, y1, w, h) {
// [block, level]
var stack = [0, 0];
var collectedNodes = [];
var container;
while (stack.length) {
var level = stack.pop(), block = stack.pop();
// Collecting nodes
container = containers[block];
if (container)
extend_1.default(collectedNodes, container);
// If we reached max level
if (level >= maxLevel)
continue;
var topLeftBlock = 4 * block + BLOCKS, topRightBlock = 4 * block + 2 * BLOCKS, bottomLeftBlock = 4 * block + 3 * BLOCKS, bottomRightBlock = 4 * block + 4 * BLOCKS;
var collidingWithTopLeft = rectangleCollidesWithQuad(x1, y1, w, h, data[topLeftBlock + X_OFFSET], data[topLeftBlock + Y_OFFSET], data[topLeftBlock + WIDTH_OFFSET], data[topLeftBlock + HEIGHT_OFFSET]);
var collidingWithTopRight = rectangleCollidesWithQuad(x1, y1, w, h, data[topRightBlock + X_OFFSET], data[topRightBlock + Y_OFFSET], data[topRightBlock + WIDTH_OFFSET], data[topRightBlock + HEIGHT_OFFSET]);
var collidingWithBottomLeft = rectangleCollidesWithQuad(x1, y1, w, h, data[bottomLeftBlock + X_OFFSET], data[bottomLeftBlock + Y_OFFSET], data[bottomLeftBlock + WIDTH_OFFSET], data[bottomLeftBlock + HEIGHT_OFFSET]);
var collidingWithBottomRight = rectangleCollidesWithQuad(x1, y1, w, h, data[bottomRightBlock + X_OFFSET], data[bottomRightBlock + Y_OFFSET], data[bottomRightBlock + WIDTH_OFFSET], data[bottomRightBlock + HEIGHT_OFFSET]);
if (collidingWithTopLeft)
stack.push(topLeftBlock, level + 1);
if (collidingWithTopRight)
stack.push(topRightBlock, level + 1);
if (collidingWithBottomLeft)
stack.push(bottomLeftBlock, level + 1);
if (collidingWithBottomRight)
stack.push(bottomRightBlock, level + 1);
}
// Else we recurse into the correct quads
if (collidingWithTopLeft) stack.push(topLeftBlock, level);
if (collidingWithTopRight) stack.push(topRightBlock, level);
if (collidingWithBottomLeft) stack.push(bottomLeftBlock, level);
if (collidingWithBottomRight) stack.push(bottomRightBlock, level);
}
return collectedNodes;
}
/**

@@ -210,69 +217,75 @@ * QuadTree class.

* @constructor
* @param {Graph} graph - A graph instance.
* @param {object} boundaries - The graph boundaries.
*/
var QuadTree = function () {
function QuadTree(boundaries) {
_classCallCheck(this, QuadTree);
// Allocating the underlying byte array
var L = Math.pow(4, MAX_LEVEL);
this.data = new Float32Array(BLOCKS * ((4 * L - 1) / 3));
this.containers = {};
if (boundaries) this.resize(boundaries);
}
_createClass(QuadTree, [{
key: "add",
value: function add(key, x, y, size) {
insertNode(MAX_LEVEL, this.data, this.containers, key, x, y, size);
return this;
var QuadTree = /** @class */ (function () {
function QuadTree(params) {
if (params === void 0) { params = {}; }
this.containers = {};
this.cache = null;
this.lastRectangle = null;
// Allocating the underlying byte array
var L = Math.pow(4, MAX_LEVEL);
this.data = new Float32Array(BLOCKS * ((4 * L - 1) / 3));
if (params.boundaries)
this.resize(params.boundaries);
else
this.resize({
x: 0,
y: 0,
width: 1,
height: 1,
});
if (typeof params.filter === "function")
this.nodeFilter = params.filter;
}
}, {
key: "resize",
value: function resize(boundaries) {
this.clear();
// Building the quadrants
this.data[X_OFFSET] = boundaries.x;
this.data[Y_OFFSET] = boundaries.y;
this.data[WIDTH_OFFSET] = boundaries.width;
this.data[HEIGHT_OFFSET] = boundaries.height;
buildQuadrants(MAX_LEVEL, this.data);
}
}, {
key: "clear",
value: function clear() {
this.containers = {};
return this;
}
}, {
key: "point",
value: function point(x, y) {
var nodes = [];
var block = 0,
level = 0;
do {
if (this.containers[block]) nodes.push.apply(nodes, this.containers[block]);
var quad = pointIsInQuad(x, y, this.data[block + X_OFFSET], this.data[block + Y_OFFSET], this.data[block + WIDTH_OFFSET], this.data[block + HEIGHT_OFFSET]);
block = 4 * block + quad * BLOCKS;
level++;
} while (level <= MAX_LEVEL);
return nodes;
}
}]);
return QuadTree;
}();
exports.default = QuadTree;
QuadTree.prototype.add = function (key, x, y, size) {
insertNode(MAX_LEVEL, this.data, this.containers, key, x, y, size);
return this;
};
QuadTree.prototype.resize = function (boundaries) {
this.clear();
// Building the quadrants
this.data[X_OFFSET] = boundaries.x;
this.data[Y_OFFSET] = boundaries.y;
this.data[WIDTH_OFFSET] = boundaries.width;
this.data[HEIGHT_OFFSET] = boundaries.height;
buildQuadrants(MAX_LEVEL, this.data);
};
QuadTree.prototype.clear = function () {
this.containers = {};
return this;
};
QuadTree.prototype.point = function (x, y) {
var nodes = [];
var block = 0, level = 0;
do {
if (this.containers[block])
nodes.push.apply(nodes, this.containers[block]);
var quad = pointIsInQuad(x, y, this.data[block + X_OFFSET], this.data[block + Y_OFFSET], this.data[block + WIDTH_OFFSET], this.data[block + HEIGHT_OFFSET]);
block = 4 * block + quad * BLOCKS;
level++;
} while (level <= MAX_LEVEL);
return nodes;
};
QuadTree.prototype.rectangle = function (x1, y1, x2, y2, height) {
var lr = this.lastRectangle;
if (lr && x1 === lr.x1 && x2 === lr.x2 && y1 === lr.y1 && y2 === lr.y2 && height === lr.height) {
return this.cache;
}
this.lastRectangle = {
x1: x1,
y1: y1,
x2: x2,
y2: y2,
height: height,
};
// Is the rectangle axis aligned?
if (!isAxisAligned(x1, y1, x2, y2))
throw new Error("sigma/quadtree.rectangle: shifted view is not yet implemented.");
var collectedNodes = getNodesInAxisAlignedRectangleArea(MAX_LEVEL, this.data, this.containers, x1, y1, Math.abs(x1 - x2) || Math.abs(y1 - y2), height);
this.cache = collectedNodes;
return this.cache;
};
return QuadTree;
}());
exports.default = QuadTree;
# Sigma v2
Nothing to see here...
Sigma is a JavaScript library dedicated to graph drawing, mainly developed by [@jacomyal](https://github.com/jacomyal) and [@Yomguithereal](https://github.com/Yomguithereal).
## Overview
[sigmajs.org website](http://sigmajs.org) provides a global overview of sigma.js v1.
As of version `v2`, `sigma` focuses on the management of graph display: layout, rendering, interaction... The graph model is managed in a separate library called [`graphology`](https://github.com/graphology/graphology), which is packed with convenience methods to manage graph data structures.
A set of demo examples contain various use-cases that might help you understand how to use sigma v2 (read further below).
### Status
Sigma.js v2 is a major refactoring and is currently in version alpha. The stable version is `v1.2.x`. Although not yet finalized and official, v2 is already in use in production in some organizations.
## Installation
Sigma is a javascript library, it is available in `npm` package manager.
npm install sigma
## Examples
A development server can be spawned locally to view the examples. Visit `localhost:8000` after executing the following commands:
npm install
npm run examples
You can play around with the files in directory `examples`, the web pages are live-reloaded whenever the code gets changed.
## Contributing
You can contribute by submitting [issues tickets](http://github.com/jacomyal/sigma.js/issues) and proposing [pull requests](http://github.com/jacomyal/sigma.js/pulls). Make sure that tests and linting pass before submitting any pull request.

@@ -1,22 +0,24 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _events = require('events');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Sigma.js Renderer Class
* ========================
*
* Abstract classes extended by all of sigma's renderers.
*/
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sigma.js Renderer Class
* ========================
*
* Abstract classes extended by all of sigma's renderers.
*/
var events_1 = require("events");
/**
* Renderer class.

@@ -26,14 +28,9 @@ *

*/
var Renderer = function (_EventEmitter) {
_inherits(Renderer, _EventEmitter);
function Renderer() {
_classCallCheck(this, Renderer);
return _possibleConstructorReturn(this, (Renderer.__proto__ || Object.getPrototypeOf(Renderer)).apply(this, arguments));
}
return Renderer;
}(_events.EventEmitter);
exports.default = Renderer;
var Renderer = /** @class */ (function (_super) {
__extends(Renderer, _super);
function Renderer() {
return _super !== null && _super.apply(this, arguments) || this;
}
return Renderer;
}(events_1.EventEmitter));
exports.default = Renderer;

@@ -1,18 +0,6 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = drawHover;
var _node = require('./node');
var _node2 = _interopRequireDefault(_node);
var _label = require('./label');
var _label2 = _interopRequireDefault(_label);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**

@@ -25,150 +13,34 @@ * Sigma.js Canvas Renderer Hover Component

*/
function drawHover(context, data) {
context.font = '14px arial';
// Then we draw the label background
context.beginPath();
context.fillStyle = '#fff';
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 8;
context.shadowColor = '#000';
var textWidth = context.measureText(data.label).width;
var x = Math.round(data.x - 14 / 2 - 2),
y = Math.round(data.y - 14 / 2 - 2),
w = Math.round(textWidth + 14 / 2 + data.size + 9),
h = Math.round(14 + 4),
e = Math.round(14 / 2 + 2);
context.moveTo(x, y + e);
context.moveTo(x, y + e);
context.arcTo(x, y, x + e, y, e);
context.lineTo(x + w, y);
context.lineTo(x + w, y + h);
context.lineTo(x + e, y + h);
context.arcTo(x, y + h, x, y + h - e, e);
context.lineTo(x, y + e);
context.closePath();
context.fill();
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 0;
// Then we need to draw the node
(0, _node2.default)(context, data);
// And finally we draw the label
(0, _label2.default)(context, data);
var node_1 = __importDefault(require("./node"));
var label_1 = __importDefault(require("./label"));
function drawHover(context, data, settings) {
var size = settings.labelSize, font = settings.labelFont, weight = settings.labelWeight;
context.font = weight + " " + size + "px " + font;
// Then we draw the label background
context.beginPath();
context.fillStyle = "#fff";
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 8;
context.shadowColor = "#000";
var textWidth = context.measureText(data.label).width;
var x = Math.round(data.x - size / 2 - 2), y = Math.round(data.y - size / 2 - 2), w = Math.round(textWidth + size / 2 + data.size + 9), h = Math.round(size + 4), e = Math.round(size / 2 + 2);
context.moveTo(x, y + e);
context.moveTo(x, y + e);
context.arcTo(x, y, x + e, y, e);
context.lineTo(x + w, y);
context.lineTo(x + w, y + h);
context.lineTo(x + e, y + h);
context.arcTo(x, y + h, x, y + h - e, e);
context.lineTo(x, y + e);
context.closePath();
context.fill();
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 0;
// Then we need to draw the node
node_1.default(context, data);
// And finally we draw the label
label_1.default(context, data, settings);
}
// ;(function(undefined) {
// 'use strict';
// if (typeof sigma === 'undefined')
// throw 'sigma is not declared';
// // Initialize packages:
// sigma.utils.pkg('sigma.canvas.hovers');
// /**
// * This hover renderer will basically display the label with a background.
// *
// * @param {object} node The node object.
// * @param {CanvasRenderingContext2D} context The canvas context.
// * @param {configurable} settings The settings function.
// */
// sigma.canvas.hovers.def = function(node, context, settings) {
// var x,
// y,
// w,
// h,
// e,
// fontStyle = settings('hoverFontStyle') || settings('fontStyle'),
// prefix = settings('prefix') || '',
// size = node[prefix + 'size'],
// fontSize = (settings('labelSize') === 'fixed') ?
// settings('defaultLabelSize') :
// settings('labelSizeRatio') * size;
// // Label background:
// context.font = (fontStyle ? fontStyle + ' ' : '') +
// fontSize + 'px ' + (settings('hoverFont') || settings('font'));
// context.beginPath();
// context.fillStyle = settings('labelHoverBGColor') === 'node' ?
// (node.color || settings('defaultNodeColor')) :
// settings('defaultHoverLabelBGColor');
// if (node.label && settings('labelHoverShadow')) {
// context.shadowOffsetX = 0;
// context.shadowOffsetY = 0;
// context.shadowBlur = 8;
// context.shadowColor = settings('labelHoverShadowColor');
// }
// if (node.label && typeof node.label === 'string') {
// x = Math.round(node[prefix + 'x'] - fontSize / 2 - 2);
// y = Math.round(node[prefix + 'y'] - fontSize / 2 - 2);
// w = Math.round(
// context.measureText(node.label).width + fontSize / 2 + size + 7
// );
// h = Math.round(fontSize + 4);
// e = Math.round(fontSize / 2 + 2);
// context.moveTo(x, y + e);
// context.arcTo(x, y, x + e, y, e);
// context.lineTo(x + w, y);
// context.lineTo(x + w, y + h);
// context.lineTo(x + e, y + h);
// context.arcTo(x, y + h, x, y + h - e, e);
// context.lineTo(x, y + e);
// context.closePath();
// context.fill();
// context.shadowOffsetX = 0;
// context.shadowOffsetY = 0;
// context.shadowBlur = 0;
// }
// // Node border:
// if (settings('borderSize') > 0) {
// context.beginPath();
// context.fillStyle = settings('nodeBorderColor') === 'node' ?
// (node.color || settings('defaultNodeColor')) :
// settings('defaultNodeBorderColor');
// context.arc(
// node[prefix + 'x'],
// node[prefix + 'y'],
// size + settings('borderSize'),
// 0,
// Math.PI * 2,
// true
// );
// context.closePath();
// context.fill();
// }
// // Node:
// var nodeRenderer = sigma.canvas.nodes[node.type] || sigma.canvas.nodes.def;
// nodeRenderer(node, context, settings);
// // Display the label:
// if (node.label && typeof node.label === 'string') {
// context.fillStyle = (settings('labelHoverColor') === 'node') ?
// (node.color || settings('defaultNodeColor')) :
// settings('defaultLabelHoverColor');
// context.fillText(
// node.label,
// Math.round(node[prefix + 'x'] + size + 3),
// Math.round(node[prefix + 'y'] + fontSize / 3)
// );
// }
// };
// }).call(this);
exports.default = drawHover;

@@ -1,7 +0,3 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = drawLabel;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**

@@ -13,7 +9,8 @@ * Sigma.js Canvas Renderer Label Component

*/
function drawLabel(context, data) {
context.fillStyle = '#000';
context.font = '14px arial';
context.fillText(data.label, data.x + data.size + 3, data.y + 14 / 3);
}
function drawLabel(context, data, settings) {
var size = settings.labelSize, font = settings.labelFont, weight = settings.labelWeight;
context.fillStyle = "#000";
context.font = weight + " " + size + "px " + font;
context.fillText(data.label, data.x + data.size + 3, data.y + size / 3);
}
exports.default = drawLabel;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = drawNode;
Object.defineProperty(exports, "__esModule", { value: true });
/**

@@ -14,11 +10,9 @@ * Sigma.js Canvas Renderer Node Component

var PI_TIMES_2 = Math.PI * 2;
function drawNode(context, data) {
context.fillStyle = data.color;
context.beginPath();
context.arc(data.x, data.y, data.size, 0, PI_TIMES_2, true);
context.closePath();
context.fill();
}
context.fillStyle = data.color;
context.beginPath();
context.arc(data.x, data.y, data.size, 0, PI_TIMES_2, true);
context.closePath();
context.fill();
}
exports.default = drawNode;

@@ -1,9 +0,2 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createElement = createElement;
exports.getPixelRatio = getPixelRatio;
exports.createNodeRescalingFunction = createNodeRescalingFunction;
"use strict";
/**

@@ -15,3 +8,20 @@ * Sigma.js Rendering Utils

*/
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createNormalizationFunction = exports.getPixelRatio = exports.createElement = void 0;
/**

@@ -25,19 +35,17 @@ * Function used to create DOM elements easily.

function createElement(tag, attributes) {
var element = document.createElement(tag);
if (!attributes) return element;
for (var k in attributes) {
if (k === 'style') {
for (var s in attributes[k]) {
element.style[s] = attributes[k][s];
}
} else {
element.setAttribute(k, attributes[k]);
var element = document.createElement(tag);
if (!attributes)
return element;
for (var k in attributes) {
if (k === "style") {
for (var s in attributes[k])
element.style[s] = attributes[k][s];
}
else {
element.setAttribute(k, attributes[k]);
}
}
}
return element;
return element;
}
exports.createElement = createElement;
/**

@@ -49,67 +57,39 @@ * Function returning the browser's pixel ratio.

function getPixelRatio() {
var screen = window.screen;
if (typeof screen.deviceXDPI !== 'undefined' && typeof screen.logicalXDPI !== 'undefined' && screen.deviceXDPI > screen.logicalXDPI) return screen.systemXDPI / screen.logicalXDPI;else if (typeof window.devicePixelRatio !== 'undefined') return window.devicePixelRatio;
return 1;
if (typeof window.devicePixelRatio !== "undefined")
return window.devicePixelRatio;
return 1;
}
exports.getPixelRatio = getPixelRatio;
/**
* Default rescale options.
*/
var DEFAULT_NODE_RESCALE_OPTIONS = {
mode: 'inside',
margin: 0,
minSize: 1,
maxSize: 8
};
var DEFAULT_EDGE_RESCALE_OPTIONS = {
minSize: 0.5,
maxSize: 1
};
// TODO: should we let the user handle size through, for instance, d3 scales?
// TODO: should we put the rescaling in the camera itself?
/**
* Factory returning a function rescaling the given node's position and/or size.
* Factory returning a function normalizing the given node's position & size.
*
* @param {object} options - Options.
* @param {object} extent - Extent of the graph.
* @return {function}
*/
function createNodeRescalingFunction(options, extent) {
options = options || {};
var mode = options.mode || DEFAULT_NODE_RESCALE_OPTIONS.mode,
height = options.height || 1,
width = options.width || 1;
var maxX = extent.maxX,
maxY = extent.maxY,
minX = extent.minX,
minY = extent.minY;
var hx = (maxX + minX) / 2,
hy = (maxY + minY) / 2;
var scale = mode === 'outside' ? Math.max(width / Math.max(maxX - minX, 1), height / Math.max(maxY - minY, 1)) : Math.min(width / Math.max(maxX - minX, 1), height / Math.max(maxY - minY, 1));
var fn = function fn(data) {
return {
x: (data.x - hx) * scale,
y: (data.y - hy) * scale
function createNormalizationFunction(extent) {
var _a = __read(extent.x, 2), minX = _a[0], maxX = _a[1], _b = __read(extent.y, 2), minY = _b[0], maxY = _b[1];
var ratio = Math.max(maxX - minX, maxY - minY);
if (ratio === 0)
ratio = 1;
var dX = (maxX + minX) / 2, dY = (maxY + minY) / 2;
var fn = function (data) {
return {
x: 0.5 + (data.x - dX) / ratio,
y: 0.5 + (data.y - dY) / ratio,
};
};
};
fn.inverse = function (data) {
return {
x: data.x / scale + hx,
y: data.y / scale + hy
// TODO: possibility to apply this in batch over array of indices
fn.applyTo = function (data) {
data.x = 0.5 + (data.x - dX) / ratio;
data.y = 0.5 + (data.y - dY) / ratio;
};
};
return fn;
}
fn.inverse = function (data) {
return {
x: dX + ratio * (data.x - 0.5),
y: dY + ratio * (data.y - 0.5),
};
};
fn.ratio = ratio;
return fn;
}
exports.createNormalizationFunction = createNormalizationFunction;

@@ -1,69 +0,44 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _glMatrix = require('gl-matrix');
var _renderer = require('../../renderer');
var _renderer2 = _interopRequireDefault(_renderer);
var _camera = require('../../camera');
var _camera2 = _interopRequireDefault(_camera);
var _mouse = require('../../captors/mouse');
var _mouse2 = _interopRequireDefault(_mouse);
var _quadtree = require('../../quadtree');
var _quadtree2 = _interopRequireDefault(_quadtree);
var _node = require('./programs/node');
var _node2 = _interopRequireDefault(_node);
var _edge = require('./programs/edge');
var _edge2 = _interopRequireDefault(_edge);
var _label = require('../canvas/components/label');
var _label2 = _interopRequireDefault(_label);
var _hover = require('../canvas/components/hover');
var _hover2 = _interopRequireDefault(_hover);
var _utils = require('../../utils');
var _utils2 = require('../utils');
var _utils3 = require('./utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Sigma.js WebGL Renderer
* ========================
*
* File implementing sigma's WebGL Renderer.
*/
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sigma.js WebGL Renderer
* ========================
*
* File implementing sigma's WebGL Renderer.
*/
var extent_1 = __importDefault(require("graphology-metrics/extent"));
var is_graph_1 = __importDefault(require("graphology-utils/is-graph"));
var renderer_1 = __importDefault(require("../../renderer"));
var camera_1 = __importDefault(require("../../camera"));
var mouse_1 = __importDefault(require("../../captors/mouse"));
var quadtree_1 = __importDefault(require("../../quadtree"));
var display_data_1 = require("../display-data");
var utils_1 = require("../../utils");
var utils_2 = require("../utils");
var utils_3 = require("./utils");
var labels_1 = require("../../heuristics/labels");
var z_index_1 = require("../../heuristics/z-index");
var settings_1 = require("./settings");
var nodeExtent = extent_1.default.nodeExtent, edgeExtent = extent_1.default.edgeExtent;
/**
* Constants.
*/
var PIXEL_RATIO = (0, _utils2.getPixelRatio)();
var WEBGL_OVERSAMPLING_RATIO = (0, _utils2.getPixelRatio)();
var PIXEL_RATIO = utils_2.getPixelRatio();
var WEBGL_OVERSAMPLING_RATIO = utils_2.getPixelRatio();
/**

@@ -73,124 +48,93 @@ * Main class.

* @constructor
* @param {HTMLElement} container - The graph's container.
* @param {Graph} graph - Graph to render.
* @param {HTMLElement} container - DOM container in which to render.
* @param {object} settings - Optional settings.
*/
var WebGLRenderer = function (_Renderer) {
_inherits(WebGLRenderer, _Renderer);
function WebGLRenderer(container) {
_classCallCheck(this, WebGLRenderer);
// Validating
var _this = _possibleConstructorReturn(this, (WebGLRenderer.__proto__ || Object.getPrototypeOf(WebGLRenderer)).call(this));
if (!(container instanceof HTMLElement)) throw new Error('sigma/renderers/webgl: container should be an html element.');
// Properties
_this.sigma = null;
_this.captors = {};
_this.container = container;
_this.elements = {};
_this.contexts = {};
_this.listeners = {};
_this.quadtree = new _quadtree2.default();
_this.nodeArray = null;
_this.nodeIndicesArray = null;
_this.nodeOrder = {};
// TODO: this could be improved by key => index => floatArray
_this.nodeDataCache = {};
_this.edgeArray = null;
_this.edgeIndicesArray = null;
_this.edgeOrder = {};
// TODO: if we drop size scaling => this should become "rescalingFunction"
_this.nodeRescalingFunction = null;
// Starting dimensions
_this.width = 0;
_this.height = 0;
// State
_this.highlightedNodes = new Set();
_this.hoveredNode = null;
_this.wasRenderedInThisFrame = false;
_this.renderFrame = null;
_this.renderHighlightedNodesFrame = null;
_this.needToProcess = false;
_this.needToSoftProcess = false;
_this.pixel = new Uint8Array(4);
// Initializing contexts
_this.createContext('edges');
_this.createContext('nodes');
_this.createContext('labels', false);
_this.createContext('hovers', false);
_this.createContext('mouse', false);
// Blending
var gl = _this.contexts.nodes;
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
gl = _this.contexts.edges;
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
// Loading programs
_this.nodePrograms = {
def: new _node2.default(_this.contexts.nodes)
};
_this.edgePrograms = {
def: new _edge2.default(_this.contexts.edges)
};
// Initial resize
_this.resize();
// Initializing the camera
_this.camera = new _camera2.default({
width: _this.width,
height: _this.height
});
// Binding camera events
_this.bindCameraHandlers();
// Initializing captors
_this.captors = {
mouse: new _mouse2.default(_this.elements.mouse, _this.camera)
};
// Binding event handlers
_this.bindEventHandlers();
return _this;
}
/**---------------------------------------------------------------------------
* Internal methods.
**---------------------------------------------------------------------------
*/
/**
* Method used to test a pixel of the given context.
*
* @param {WebGLContext} gl - Context.
* @param {number} x - Client x.
* @param {number} y - Client y.
* @return {boolean}
*/
_createClass(WebGLRenderer, [{
key: 'testPixel',
value: function testPixel(gl, x, y) {
(0, _utils3.extractPixel)(gl, x * WEBGL_OVERSAMPLING_RATIO, (this.height - y) * WEBGL_OVERSAMPLING_RATIO, this.pixel);
return this.pixel[3] !== 0;
var WebGLRenderer = /** @class */ (function (_super) {
__extends(WebGLRenderer, _super);
function WebGLRenderer(graph, container, settings) {
if (settings === void 0) { settings = {}; }
var _this = _super.call(this) || this;
_this.captors = {};
_this.elements = {};
_this.contexts = {};
_this.listeners = {};
_this.quadtree = new quadtree_1.default();
_this.nodeDataCache = {};
_this.edgeDataCache = {};
_this.nodeExtent = null;
_this.edgeExtent = null;
_this.normalizationFunction = null;
// Starting dimensions
_this.width = 0;
_this.height = 0;
// State
_this.highlightedNodes = new Set();
_this.displayedLabels = new Set();
_this.hoveredNode = null;
_this.wasRenderedInThisFrame = false;
_this.renderFrame = null;
_this.renderHighlightedNodesFrame = null;
_this.needToProcess = false;
_this.needToSoftProcess = false;
// programs
_this.nodePrograms = {};
_this.edgePrograms = {};
_this.settings = utils_1.assign({}, settings_1.WEBGL_RENDERER_DEFAULT_SETTINGS, settings);
settings_1.validateWebglRendererSettings(_this.settings);
// Validating
if (!is_graph_1.default(graph))
throw new Error("sigma/renderers/webgl: invalid graph instance.");
if (!(container instanceof HTMLElement))
throw new Error("sigma/renderers/webgl: container should be an html element.");
// Properties
_this.graph = graph;
_this.container = container;
_this.initializeCache();
// Initializing contexts
_this.createContext("edges");
_this.createContext("edgeLabels", false);
_this.createContext("nodes");
_this.createContext("labels", false);
_this.createContext("hovers", false);
_this.createContext("mouse", false);
// Blending
var gl = _this.contexts.nodes;
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
gl = _this.contexts.edges;
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
// Loading programs
for (var type in _this.settings.nodeProgramClasses) {
var NodeProgramClass = _this.settings.nodeProgramClasses[type];
_this.nodePrograms[type] = new NodeProgramClass(_this.contexts.nodes);
}
for (var type in _this.settings.edgeProgramClasses) {
var EdgeProgramClass = _this.settings.edgeProgramClasses[type];
_this.edgePrograms[type] = new EdgeProgramClass(_this.contexts.edges);
}
// Initial resize
_this.resize();
// Initializing the camera
_this.camera = new camera_1.default();
// Binding camera events
_this.bindCameraHandlers();
// Initializing captors
_this.captors = {
mouse: new mouse_1.default(_this.elements.mouse, _this.camera),
};
// Binding event handlers
_this.bindEventHandlers();
// Binding graph handlers
_this.bindGraphHandlers();
// Processing data for the first time & render
_this.process();
_this.render();
return _this;
}
/**---------------------------------------------------------------------------
* Internal methods.
**---------------------------------------------------------------------------
*/
/**

@@ -204,31 +148,48 @@ * Internal function used to create a canvas context and add the relevant

*/
}, {
key: 'createContext',
value: function createContext(id) {
var webgl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var element = (0, _utils2.createElement)('canvas', {
class: 'sigma-' + id,
style: {
position: 'absolute'
WebGLRenderer.prototype.createContext = function (id, webgl) {
if (webgl === void 0) { webgl = true; }
var element = utils_2.createElement("canvas", {
class: "sigma-" + id,
style: {
position: "absolute",
},
});
this.elements[id] = element;
this.container.appendChild(element);
var contextOptions = {
preserveDrawingBuffer: false,
antialias: false,
};
var context;
if (webgl) {
// First we try webgl2 for an easy performance boost
context = element.getContext("webgl2", contextOptions);
// Else we fall back to webgl
if (!context)
context = element.getContext("webgl", contextOptions);
// Edge, I am looking right at you...
if (!context)
context = element.getContext("experimental-webgl", contextOptions);
}
});
this.elements[id] = element;
this.container.appendChild(element);
var contextOptions = {
preserveDrawingBuffer: true,
antialias: false
};
var context = element.getContext(webgl ? 'webgl' : '2d', contextOptions);
this.contexts[id] = context;
return this;
}
else {
context = element.getContext("2d", contextOptions);
}
this.contexts[id] = context;
return this;
};
/**
* Method used to initialize display data cache.
*
* @return {WebGLRenderer}
*/
WebGLRenderer.prototype.initializeCache = function () {
var graph = this.graph;
var nodes = graph.nodes();
for (var i = 0, l = nodes.length; i < l; i++)
this.nodeDataCache[nodes[i]] = new display_data_1.NodeDisplayData(i, this.settings);
var edges = graph.edges();
for (var i = 0, l = edges.length; i < l; i++)
this.edgeDataCache[edges[i]] = new display_data_1.EdgeDisplayData(i, this.settings);
};
/**
* Method binding camera handlers.

@@ -238,17 +199,10 @@ *

*/
}, {
key: 'bindCameraHandlers',
value: function bindCameraHandlers() {
var _this2 = this;
this.listeners.camera = function () {
_this2.scheduleRender();
};
this.camera.on('updated', this.listeners.camera);
return this;
}
WebGLRenderer.prototype.bindCameraHandlers = function () {
var _this = this;
this.listeners.camera = function () {
_this.scheduleRender();
};
this.camera.on("updated", this.listeners.camera);
return this;
};
/**

@@ -259,122 +213,93 @@ * Method binding event handlers.

*/
}, {
key: 'bindEventHandlers',
value: function bindEventHandlers() {
var _this3 = this;
// Handling window resize
this.listeners.handleResize = function () {
_this3.needToSoftProcess = true;
_this3.scheduleRender();
};
window.addEventListener('resize', this.listeners.handleResize);
// Function checking if the mouse is on the given node
var mouseIsOnNode = function mouseIsOnNode(mouseX, mouseY, nodeX, nodeY, size) {
return mouseX > nodeX - size && mouseX < nodeX + size && mouseY > nodeY - size && mouseY < nodeY + size && Math.sqrt(Math.pow(mouseX - nodeX, 2) + Math.pow(mouseY - nodeY, 2)) < size;
};
// Function returning the nodes in the mouse's quad
var getQuadNodes = function getQuadNodes(mouseX, mouseY) {
var mouseGraphPosition = _this3.camera.displayToGraph(mouseX, mouseY);
return _this3.quadtree.point(mouseGraphPosition.x, mouseGraphPosition.y);
};
// Handling mouse move
this.listeners.handleMove = function (e) {
// NOTE: for the canvas renderer, testing the pixel's alpha should
// give some boost but this slows things down for WebGL empirically.
// TODO: this should be a method from the camera (or can be passed to graph to display somehow)
var sizeRatio = Math.pow(_this3.camera.getState().ratio, 0.5);
var quadNodes = getQuadNodes(e.x, e.y);
for (var i = 0, l = quadNodes.length; i < l; i++) {
var node = quadNodes[i];
var data = _this3.nodeDataCache[node];
var pos = _this3.camera.graphToDisplay(data.x, data.y);
var size = data.size / sizeRatio;
if (mouseIsOnNode(e.x, e.y, pos.x, pos.y, size)) {
_this3.hoveredNode = node;
_this3.emit('overNode', { node: node });
return _this3.scheduleHighlightedNodesRender();
}
}
// Checking if the hovered node is still hovered
if (_this3.hoveredNode) {
var _data = _this3.nodeDataCache[_this3.hoveredNode];
var _pos = _this3.camera.graphToDisplay(_data.x, _data.y);
var _size = _data.size / sizeRatio;
if (!mouseIsOnNode(e.x, e.y, _pos.x, _pos.y, _size)) {
_this3.hoveredNode = null;
_this3.emit('outNode', { node: _this3.hoveredNode });
return _this3.scheduleHighlightedNodesRender();
}
}
};
// Handling down
this.listeners.handleDown = function (e) {
var sizeRatio = Math.pow(_this3.camera.getState().ratio, 0.5);
var quadNodes = getQuadNodes(e.x, e.y);
for (var i = 0, l = quadNodes.length; i < l; i++) {
var node = quadNodes[i];
var data = _this3.nodeDataCache[node];
var pos = _this3.camera.graphToDisplay(data.x, data.y);
var size = data.size / sizeRatio;
if (mouseIsOnNode(e.x, e.y, pos.x, pos.y, size)) return _this3.emit('downNode', { node: node });
}
};
// Handling click
this.listeners.handleClick = function (e) {
var sizeRatio = Math.pow(_this3.camera.getState().ratio, 0.5);
var quadNodes = getQuadNodes(e.x, e.y);
for (var i = 0, l = quadNodes.length; i < l; i++) {
var node = quadNodes[i];
var data = _this3.nodeDataCache[node];
var pos = _this3.camera.graphToDisplay(data.x, data.y);
var size = data.size / sizeRatio;
if (mouseIsOnNode(e.x, e.y, pos.x, pos.y, size)) return _this3.emit('clickNode', { node: node });
}
return _this3.emit('clickStage');
};
// TODO: optimize, we don't need to repeat collisions
this.captors.mouse.on('mousemove', this.listeners.handleMove);
this.captors.mouse.on('mousedown', this.listeners.handleDown);
this.captors.mouse.on('click', this.listeners.handleClick);
return this;
}
WebGLRenderer.prototype.bindEventHandlers = function () {
var _this = this;
// Handling window resize
this.listeners.handleResize = function () {
_this.needToSoftProcess = true;
_this.scheduleRender();
};
window.addEventListener("resize", this.listeners.handleResize);
// Function checking if the mouse is on the given node
var mouseIsOnNode = function (mouseX, mouseY, nodeX, nodeY, size) {
return (mouseX > nodeX - size &&
mouseX < nodeX + size &&
mouseY > nodeY - size &&
mouseY < nodeY + size &&
Math.sqrt(Math.pow(mouseX - nodeX, 2) + Math.pow(mouseY - nodeY, 2)) < size);
};
// Function returning the nodes in the mouse's quad
var getQuadNodes = function (mouseX, mouseY) {
var mouseGraphPosition = _this.camera.viewportToGraph(_this, mouseX, mouseY);
// TODO: minus 1? lol
return _this.quadtree.point(mouseGraphPosition.x, 1 - mouseGraphPosition.y);
};
// Handling mouse move
this.listeners.handleMove = function (e) {
// NOTE: for the canvas renderer, testing the pixel's alpha should
// give some boost but this slows things down for WebGL empirically.
// TODO: this should be a method from the camera (or can be passed to graph to display somehow)
var sizeRatio = Math.pow(_this.camera.getState().ratio, 0.5);
var quadNodes = getQuadNodes(e.x, e.y);
// We will hover the node whose center is closest to mouse
var minDistance = Infinity, nodeToHover = null;
for (var i = 0, l = quadNodes.length; i < l; i++) {
var node = quadNodes[i];
var data = _this.nodeDataCache[node];
var pos = _this.camera.graphToViewport(_this, data.x, data.y);
var size = data.size / sizeRatio;
if (mouseIsOnNode(e.x, e.y, pos.x, pos.y, size)) {
var distance = Math.sqrt(Math.pow(e.x - pos.x, 2) + Math.pow(e.y - pos.y, 2));
// TODO: sort by min size also for cases where center is the same
if (distance < minDistance) {
minDistance = distance;
nodeToHover = node;
}
}
}
if (nodeToHover && _this.hoveredNode !== nodeToHover) {
// Handling passing from one node to the other directly
if (_this.hoveredNode !== null)
_this.emit("leaveNode", { node: _this.hoveredNode });
_this.hoveredNode = nodeToHover;
_this.emit("enterNode", { node: nodeToHover });
return _this.scheduleHighlightedNodesRender();
}
// Checking if the hovered node is still hovered
if (_this.hoveredNode) {
var data = _this.nodeDataCache[_this.hoveredNode];
var pos = _this.camera.graphToViewport(_this, data.x, data.y);
var size = data.size / sizeRatio;
if (!mouseIsOnNode(e.x, e.y, pos.x, pos.y, size)) {
var node = _this.hoveredNode;
_this.hoveredNode = null;
_this.emit("leaveNode", { node: node });
return _this.scheduleHighlightedNodesRender();
}
}
};
// Handling click
var createClickListener = function (eventType) {
return function (e) {
var sizeRatio = Math.pow(_this.camera.getState().ratio, 0.5);
var quadNodes = getQuadNodes(e.x, e.y);
for (var i = 0, l = quadNodes.length; i < l; i++) {
var node = quadNodes[i];
var data = _this.nodeDataCache[node];
var pos = _this.camera.graphToViewport(_this, data.x, data.y);
var size = data.size / sizeRatio;
if (mouseIsOnNode(e.x, e.y, pos.x, pos.y, size))
return _this.emit(eventType + "Node", { node: node, captor: e, event: e });
}
return _this.emit(eventType + "Stage", { event: e });
};
};
this.listeners.handleClick = createClickListener("click");
this.listeners.handleRightClick = createClickListener("rightClick");
this.listeners.handleDown = createClickListener("down");
this.captors.mouse.on("mousemove", this.listeners.handleMove);
this.captors.mouse.on("click", this.listeners.handleClick);
this.captors.mouse.on("rightClick", this.listeners.handleRightClick);
this.captors.mouse.on("mousedown", this.listeners.handleDown);
return this;
};
/**

@@ -385,34 +310,36 @@ * Method binding graph handlers

*/
}, {
key: 'bindGraphHandlers',
value: function bindGraphHandlers() {
var _this4 = this;
var graph = this.sigma.getGraph();
this.listeners.graphUpdate = function () {
_this4.needToProcess = true;
_this4.scheduleRender();
};
this.listeners.softGraphUpdate = function () {
_this4.needToSoftProcess = true;
_this4.scheduleRender();
};
// TODO: bind this on composed state events
// TODO: it could be possible to update only specific node etc. by holding
// a fixed-size pool of updated items
graph.on('nodeAdded', this.listeners.graphUpdate);
graph.on('nodeDropped', this.listeners.graphUpdate);
graph.on('nodeAttributesUpdated', this.listeners.softGraphUpdate);
graph.on('edgeAdded', this.listeners.graphUpdate);
graph.on('nodeDropped', this.listeners.graphUpdate);
graph.on('edgeAttributesUpdated', this.listeners.softGraphUpdate);
graph.on('cleared', this.listeners.graphUpdate);
return this;
}
WebGLRenderer.prototype.bindGraphHandlers = function () {
var _this = this;
var graph = this.graph;
this.listeners.graphUpdate = function () {
_this.needToProcess = true;
_this.scheduleRender();
};
this.listeners.softGraphUpdate = function () {
_this.needToSoftProcess = true;
_this.scheduleRender();
};
this.listeners.addNodeGraphUpdate = function (e) {
// Adding entry to cache
_this.nodeDataCache[e.key] = new display_data_1.NodeDisplayData(graph.order - 1, _this.settings);
_this.listeners.graphUpdate();
};
this.listeners.addEdgeGraphUpdate = function (e) {
// Adding entry to cache
_this.edgeDataCache[e.key] = new display_data_1.EdgeDisplayData(graph.size - 1, _this.settings);
_this.listeners.graphUpdate();
};
// TODO: clean cache on drop!
// TODO: bind this on composed state events
// TODO: it could be possible to update only specific node etc. by holding
// a fixed-size pool of updated items
graph.on("nodeAdded", this.listeners.addNodeGraphUpdate);
graph.on("nodeDropped", this.listeners.graphUpdate);
graph.on("nodeAttributesUpdated", this.listeners.softGraphUpdate);
graph.on("edgeAdded", this.listeners.addEdgeGraphUpdate);
graph.on("nodeDropped", this.listeners.graphUpdate);
graph.on("edgeAttributesUpdated", this.listeners.softGraphUpdate);
graph.on("cleared", this.listeners.graphUpdate);
return this;
};
/**

@@ -423,94 +350,64 @@ * Method used to process the whole graph's data.

*/
}, {
key: 'process',
value: function process() {
var keepArrays = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var graph = this.sigma.getGraph();
// TODO: possible to index this somehow using two byte arrays or so
var extent = this.sigma.getGraphExtent();
// Rescaling function
this.nodeRescalingFunction = (0, _utils2.createNodeRescalingFunction)({ width: this.width, height: this.height }, extent);
var minRescaled = this.nodeRescalingFunction({
x: extent.minX,
y: extent.minY
});
var maxRescaled = this.nodeRescalingFunction({
x: extent.maxX,
y: extent.maxY
});
this.quadtree.resize({
x: minRescaled.x,
y: minRescaled.y,
width: maxRescaled.x - minRescaled.x,
height: maxRescaled.y - minRescaled.y
});
this.nodeRescaleCache = {};
var nodeProgram = this.nodePrograms.def;
if (!keepArrays) {
this.nodeArray = new Float32Array(_node2.default.POINTS * _node2.default.ATTRIBUTES * graph.order);
this.nodeOrder = {};
}
var nodes = graph.nodes();
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
this.nodeOrder[node] = i;
var data = this.sigma.getNodeData(node);
var rescaledData = this.nodeRescalingFunction(data);
// TODO: Optimize this to be save a loop and one object
var displayData = (0, _utils.assign)({}, data, rescaledData);
this.quadtree.add(node, displayData.x, displayData.y, displayData.size);
this.nodeDataCache[node] = displayData;
nodeProgram.process(this.nodeArray, displayData, i * _node2.default.POINTS * _node2.default.ATTRIBUTES);
}
var edgeProgram = this.edgePrograms.def;
if (!keepArrays) {
this.edgeArray = new Float32Array(_edge2.default.POINTS * _edge2.default.ATTRIBUTES * graph.size);
this.edgeOrder = {};
}
var edges = graph.edges();
for (var _i = 0, _l = edges.length; _i < _l; _i++) {
var edge = edges[_i];
this.edgeOrder[edge] = _i;
var _data2 = this.sigma.getEdgeData(edge),
extremities = graph.extremities(edge),
sourceData = this.nodeDataCache[extremities[0]],
targetData = this.nodeDataCache[extremities[1]];
edgeProgram.process(this.edgeArray, sourceData, targetData, _data2, _i * _edge2.default.POINTS * _edge2.default.ATTRIBUTES);
}
// Computing edge indices if necessary
if (!keepArrays && typeof edgeProgram.computeIndices === 'function') this.edgeIndicesArray = edgeProgram.computeIndices(this.edgeArray);
return this;
}
WebGLRenderer.prototype.process = function (keepArrays) {
if (keepArrays === void 0) { keepArrays = false; }
var graph = this.graph, settings = this.settings;
// Clearing the quad
this.quadtree.clear();
// Computing extents
var nodeExtentProperties = ["x", "y"];
if (this.settings.zIndex) {
nodeExtentProperties.push("z");
this.edgeExtent = edgeExtent(graph, ["z"]);
}
this.nodeExtent = nodeExtent(graph, nodeExtentProperties);
// Rescaling function
this.normalizationFunction = utils_2.createNormalizationFunction(this.nodeExtent);
var nodeProgram = this.nodePrograms[this.settings.defaultNodeType];
if (!keepArrays)
nodeProgram.allocate(graph.order);
var nodes = graph.nodes();
// Handling node z-index
// TODO: z-index needs us to compute display data before hand
// TODO: remains to be seen if reducers are a good or bad thing and if we
// should store display data in flat byte arrays indices
if (this.settings.zIndex)
nodes = z_index_1.zIndexOrdering(this.edgeExtent.z, function (node) { return graph.getNodeAttribute(node, "z"); }, nodes);
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
var data = graph.getNodeAttributes(node);
var displayData = this.nodeDataCache[node];
if (settings.nodeReducer)
data = settings.nodeReducer(node, data);
// TODO: should assign default also somewhere here if there is a reducer
displayData.assign(data);
this.normalizationFunction.applyTo(displayData);
this.quadtree.add(node, displayData.x, 1 - displayData.y, displayData.size / this.width);
nodeProgram.process(displayData, i);
displayData.index = i;
}
nodeProgram.bufferData();
var edgeProgram = this.edgePrograms[this.settings.defaultEdgeType];
if (!keepArrays)
edgeProgram.allocate(graph.size);
var edges = graph.edges();
// Handling edge z-index
if (this.settings.zIndex)
edges = z_index_1.zIndexOrdering(this.edgeExtent.z, function (edge) { return graph.getEdgeAttribute(edge, "z"); }, edges);
for (var i = 0, l = edges.length; i < l; i++) {
var edge = edges[i];
var data = graph.getEdgeAttributes(edge);
var displayData = this.edgeDataCache[edge];
if (settings.edgeReducer)
data = settings.edgeReducer(edge, data);
displayData.assign(data);
var extremities = graph.extremities(edge), sourceData = this.nodeDataCache[extremities[0]], targetData = this.nodeDataCache[extremities[1]];
edgeProgram.process(sourceData, targetData, displayData, i);
displayData.index = i;
}
// Computing edge indices if necessary
if (!keepArrays && typeof edgeProgram.computeIndices === "function")
edgeProgram.computeIndices();
edgeProgram.bufferData();
return this;
};
/**

@@ -521,16 +418,8 @@ * Method used to process a single node.

*/
}, {
key: 'processNode',
value: function processNode(key) {
var nodeProgram = this.nodePrograms.def;
var data = this.sigma.getNodeData(key);
nodeProgram.process(this.nodeArray, data, this.nodeOrder[key] * _node2.default.POINTS * _node2.default.ATTRIBUTES);
return this;
}
WebGLRenderer.prototype.processNode = function (key) {
var nodeProgram = this.nodePrograms[this.settings.defaultNodeType];
var data = this.graph.getNodeAttributes(key);
nodeProgram.process(data, this.nodeDataCache[key].index);
return this;
};
/**

@@ -541,21 +430,9 @@ * Method used to process a single edge.

*/
}, {
key: 'processEdge',
value: function processEdge(key) {
var graph = this.sigma.getGraph();
var edgeProgram = this.edgePrograms.def;
var data = this.sigma.getEdgeData(key),
extremities = graph.extremities(key),
sourceData = this.sigma.getNodeData(extremities[0]),
targetData = this.sigma.getNodeData(extremities[1]);
edgeProgram.process(this.edgeArray, sourceData, targetData, data, this.edgeOrder[key] * _edge2.default.POINTS * _edge2.default.ATTRIBUTES);
return this;
}
WebGLRenderer.prototype.processEdge = function (key) {
var graph = this.graph;
var edgeProgram = this.edgePrograms[this.settings.defaultEdgeType];
var data = graph.getEdgeAttributes(key), extremities = graph.extremities(key), sourceData = graph.getNodeAttributes(extremities[0]), targetData = graph.getNodeAttributes(extremities[1]);
edgeProgram.process(sourceData, targetData, data, this.edgeDataCache[key].index);
return this;
};
/**---------------------------------------------------------------------------

@@ -565,26 +442,3 @@ * Public API.

*/
/**
* Method used to bind the renderer to a sigma instance.
*
* @param {Sigma} sigma - Target sigma instance.
* @return {WebGLRenderer}
*/
}, {
key: 'bind',
value: function bind(sigma) {
// Binding instance
this.sigma = sigma;
this.bindGraphHandlers();
// Processing initial data
this.process();
return this;
}
/**
* Method returning the renderer's camera.

@@ -594,9 +448,5 @@ *

*/
}, {
key: 'getCamera',
value: function getCamera() {
return this.camera;
}
WebGLRenderer.prototype.getCamera = function () {
return this.camera;
};
/**

@@ -607,9 +457,5 @@ * Method returning the mouse captor.

*/
}, {
key: 'getMouseCaptor',
value: function getMouseCaptor() {
return this.captors.mouse;
}
WebGLRenderer.prototype.getMouseCaptor = function () {
return this.captors.mouse;
};
/**

@@ -622,58 +468,46 @@ * Method used to resize the renderer.

*/
}, {
key: 'resize',
value: function resize(width, height) {
var previousWidth = this.width,
previousHeight = this.height;
if (arguments.length > 1) {
this.width = width;
this.height = height;
} else {
this.width = this.container.offsetWidth;
this.height = this.container.offsetHeight;
}
// If nothing has changed, we can stop right here
if (previousWidth === this.width && previousHeight === this.height) return this;
// Resizing camera
// TODO: maybe move this elsewhere
if (this.camera) this.camera.resize({ width: this.width, height: this.height });
// Sizing dom elements
for (var id in this.elements) {
var element = this.elements[id];
element.style.width = this.width + 'px';
element.style.height = this.height + 'px';
}
// Sizing contexts
for (var _id in this.contexts) {
var context = this.contexts[_id];
// Canvas contexts
if (context.scale) {
this.elements[_id].setAttribute('width', this.width * PIXEL_RATIO + 'px');
this.elements[_id].setAttribute('height', this.height * PIXEL_RATIO + 'px');
if (PIXEL_RATIO !== 1) context.scale(PIXEL_RATIO, PIXEL_RATIO);
WebGLRenderer.prototype.resize = function (width, height) {
var previousWidth = this.width, previousHeight = this.height;
if (arguments.length > 1) {
this.width = width;
this.height = height;
}
// WebGL contexts
else {
this.elements[_id].setAttribute('width', this.width * WEBGL_OVERSAMPLING_RATIO + 'px');
this.elements[_id].setAttribute('height', this.height * WEBGL_OVERSAMPLING_RATIO + 'px');
}
if (context.viewport) {
context.viewport(0, 0, this.width * WEBGL_OVERSAMPLING_RATIO, this.height * WEBGL_OVERSAMPLING_RATIO);
this.width = this.container.offsetWidth;
this.height = this.container.offsetHeight;
}
}
return this;
}
if (this.width === 0)
throw new Error("sigma/renderers/webgl: container has no width.");
if (this.height === 0)
throw new Error("sigma/renderers/webgl: container has no height.");
// If nothing has changed, we can stop right here
if (previousWidth === this.width && previousHeight === this.height)
return this;
// Sizing dom elements
for (var id in this.elements) {
var element = this.elements[id];
element.style.width = this.width + "px";
element.style.height = this.height + "px";
}
// Sizing contexts
for (var id in this.contexts) {
var context_1 = this.contexts[id];
// Canvas contexts
if (context_1.scale) {
this.elements[id].setAttribute("width", this.width * PIXEL_RATIO + "px");
this.elements[id].setAttribute("height", this.height * PIXEL_RATIO + "px");
if (PIXEL_RATIO !== 1)
context_1.scale(PIXEL_RATIO, PIXEL_RATIO);
}
// WebGL contexts
else {
this.elements[id].setAttribute("width", this.width * WEBGL_OVERSAMPLING_RATIO + "px");
this.elements[id].setAttribute("height", this.height * WEBGL_OVERSAMPLING_RATIO + "px");
}
if (context_1.viewport) {
context_1.viewport(0, 0, this.width * WEBGL_OVERSAMPLING_RATIO, this.height * WEBGL_OVERSAMPLING_RATIO);
}
}
return this;
};
/**

@@ -684,21 +518,10 @@ * Method used to clear the canvases.

*/
}, {
key: 'clear',
value: function clear() {
var context = this.contexts.nodes;
context.clear(context.COLOR_BUFFER_BIT);
context = this.contexts.edges;
context.clear(context.COLOR_BUFFER_BIT);
context = this.contexts.labels;
context.clearRect(0, 0, this.width, this.height);
context = this.contexts.hovers;
context.clearRect(0, 0, this.width, this.height);
return this;
}
WebGLRenderer.prototype.clear = function () {
this.contexts.nodes.clear(this.contexts.nodes.COLOR_BUFFER_BIT);
this.contexts.edges.clear(this.contexts.edges.COLOR_BUFFER_BIT);
this.contexts.labels.clearRect(0, 0, this.width, this.height);
this.contexts.hovers.clearRect(0, 0, this.width, this.height);
this.contexts.edgeLabels.clearRect(0, 0, this.width, this.height);
return this;
};
/**

@@ -709,194 +532,215 @@ * Method used to render.

*/
}, {
key: 'render',
value: function render() {
// If a render was scheduled, we cancel it
if (this.renderFrame) {
cancelAnimationFrame(this.renderFrame);
this.renderFrame = null;
this.needToProcess = false;
this.needToSoftProcess = false;
}
// First we need to resize
this.resize();
// Clearing the canvases
this.clear();
// Then we need to extract a matrix from the camera
var cameraState = this.camera.getState(),
cameraMatrix = (0, _utils3.matrixFromCamera)(cameraState);
var translation = _glMatrix.mat3.fromTranslation(_glMatrix.mat3.create(), [this.width / 2, this.height / 2]);
_glMatrix.mat3.multiply(cameraMatrix, translation, cameraMatrix);
var program = void 0,
gl = void 0;
// Drawing nodes
gl = this.contexts.nodes;
program = this.nodePrograms.def;
// TODO: should probably use another name for the `program` abstraction
program.render(gl, this.nodeArray, {
matrix: cameraMatrix,
width: this.width,
height: this.height,
ratio: cameraState.ratio,
nodesPowRatio: 0.5,
scalingRatio: WEBGL_OVERSAMPLING_RATIO
});
// Drawing edges
gl = this.contexts.edges;
program = this.edgePrograms.def;
program.render(gl, this.edgeArray, {
matrix: cameraMatrix,
width: this.width,
height: this.height,
ratio: cameraState.ratio,
edgesPowRatio: 0.5,
scalingRatio: WEBGL_OVERSAMPLING_RATIO,
indices: this.edgeIndicesArray
});
// Drawing labels
// TODO: POW RATIO is currently default 0.5 and harcoded
var nodes = this.sigma.getGraph().nodes(),
context = this.contexts.labels;
var sizeRatio = Math.pow(cameraState.ratio, 0.5);
for (var i = 0, l = nodes.length; i < l; i++) {
var data = this.nodeDataCache[nodes[i]];
var _camera$graphToDispla = this.camera.graphToDisplay(data.x, data.y),
x = _camera$graphToDispla.x,
y = _camera$graphToDispla.y;
// TODO: we can cache the labels we need to render until the camera's ratio changes
var size = data.size / sizeRatio;
// TODO: this is the label threshold hardcoded
if (size < 8) continue;
(0, _label2.default)(context, {
label: data.label,
size: size,
x: x,
y: y
WebGLRenderer.prototype.render = function () {
// If a render was scheduled, we cancel it
if (this.renderFrame) {
cancelAnimationFrame(this.renderFrame);
this.renderFrame = null;
this.needToProcess = false;
this.needToSoftProcess = false;
}
// First we need to resize
this.resize();
// Clearing the canvases
this.clear();
// If we have no nodes we can stop right there
if (!this.graph.order)
return this;
// TODO: improve this heuristic or move to the captor itself?
var moving = this.camera.isAnimated() ||
this.captors.mouse.isMoving ||
this.captors.mouse.hasDragged ||
this.captors.mouse.wheelLock;
// Then we need to extract a matrix from the camera
var cameraState = this.camera.getState(), cameraMatrix = utils_3.matrixFromCamera(cameraState, {
width: this.width,
height: this.height,
});
}
// Rendering highlighted nodes
this.renderHighlightedNodes();
return this;
}
var program;
// Drawing nodes
program = this.nodePrograms[this.settings.defaultNodeType];
program.render({
matrix: cameraMatrix,
width: this.width,
height: this.height,
ratio: cameraState.ratio,
nodesPowRatio: 0.5,
scalingRatio: WEBGL_OVERSAMPLING_RATIO,
});
// Drawing edges
if (!this.settings.hideEdgesOnMove || !moving) {
program = this.edgePrograms[this.settings.defaultEdgeType];
program.render({
matrix: cameraMatrix,
width: this.width,
height: this.height,
ratio: cameraState.ratio,
nodesPowRatio: 0.5,
edgesPowRatio: 0.5,
scalingRatio: WEBGL_OVERSAMPLING_RATIO,
});
}
// Do not display labels on move per setting
if (this.settings.hideLabelsOnMove && moving)
return this;
this.renderLabels();
this.renderEdgeLabels();
this.renderHighlightedNodes();
return this;
};
/**
* Method used to render the highlighted nodes.
* Method used to render labels.
*
* @return {WebGLRenderer}
*/
}, {
key: 'renderHighlightedNodes',
value: function renderHighlightedNodes() {
var _this5 = this;
var camera = this.camera;
var sizeRatio = Math.pow(camera.getState().ratio, 0.5);
var context = this.contexts.hovers;
// Clearing
context.clearRect(0, 0, this.width, this.height);
// Rendering
var render = function render(node) {
var data = _this5.nodeDataCache[node];
var _camera$graphToDispla2 = camera.graphToDisplay(data.x, data.y),
x = _camera$graphToDispla2.x,
y = _camera$graphToDispla2.y;
var size = data.size / sizeRatio;
(0, _hover2.default)(context, {
label: data.label,
color: data.color,
size: size,
x: x,
y: y
WebGLRenderer.prototype.renderLabels = function () {
if (!this.settings.renderLabels)
return this;
var cameraState = this.camera.getState();
// Finding visible nodes to display their labels
var visibleNodes;
if (cameraState.ratio >= 1) {
// Camera is unzoomed so no need to ask the quadtree for visible nodes
visibleNodes = this.graph.nodes();
}
else {
// Let's ask the quadtree
var viewRectangle = this.camera.viewRectangle(this);
visibleNodes = this.quadtree.rectangle(viewRectangle.x1, 1 - viewRectangle.y1, viewRectangle.x2, 1 - viewRectangle.y2, viewRectangle.height);
}
// Selecting labels to draw
var gridSettings = this.settings.labelGrid;
var labelsToDisplay = labels_1.labelsToDisplayFromGrid({
cache: this.nodeDataCache,
camera: this.camera,
cell: gridSettings.cell,
dimensions: this,
displayedLabels: this.displayedLabels,
fontSize: this.settings.labelSize,
graph: this.graph,
renderedSizeThreshold: gridSettings.renderedSizeThreshold,
visibleNodes: visibleNodes,
});
};
if (this.hoveredNode) render(this.hoveredNode);
this.highlightedNodes.forEach(render);
}
// Drawing labels
var context = this.contexts.labels;
var sizeRatio = Math.pow(cameraState.ratio, 0.5);
for (var i = 0, l = labelsToDisplay.length; i < l; i++) {
var data = this.nodeDataCache[labelsToDisplay[i]];
var _a = this.camera.graphToViewport(this, data.x, data.y), x = _a.x, y = _a.y;
// TODO: we can cache the labels we need to render until the camera's ratio changes
// TODO: this should be computed in the canvas components?
var size = data.size / sizeRatio;
this.settings.labelRenderer(context, {
key: labelsToDisplay[i],
label: data.label,
size: size,
x: x,
y: y,
}, this.settings);
}
// Caching visible nodes and displayed labels
this.displayedLabels = new Set(labelsToDisplay);
return this;
};
/**
* Method used to schedule a render.
* Method used to render edge labels, based on which node labels were
* rendered.
*
* @return {WebGLRenderer}
*/
}, {
key: 'scheduleRender',
value: function scheduleRender() {
var _this6 = this;
// If we did not render in this frame yet
// if (!this.wasRenderedInThisFrame) {
// // Do we need to process data?
// if (this.needToProcess || this.needToSoftProcess)
// this.process(this.needToSoftProcess);
// // Resetting state
// this.renderFrame = null;
// this.needToProcess = false;
// this.needToSoftProcess = false;
// this.render();
// this.wasRenderedInThisFrame = true;
// requestAnimationFrame(() => {
// this.wasRenderedInThisFrame = false;
// });
// return this;
// }
// A frame is already scheduled
if (this.renderFrame) return this;
// Let's schedule a frame
this.renderFrame = requestAnimationFrame(function () {
// Do we need to process data?
if (_this6.needToProcess || _this6.needToSoftProcess) _this6.process(_this6.needToSoftProcess);
// Resetting state
_this6.renderFrame = null;
_this6.needToProcess = false;
_this6.needToSoftProcess = false;
WebGLRenderer.prototype.renderEdgeLabels = function () {
if (!this.settings.renderEdgeLabels)
return this;
var cameraState = this.camera.getState();
var sizeRatio = Math.pow(cameraState.ratio, 0.5);
var context = this.contexts.edgeLabels;
// Clearing
context.clearRect(0, 0, this.width, this.height);
var edgeLabelsToDisplay = labels_1.edgeLabelsToDisplayFromNodes({
graph: this.graph,
hoveredNode: this.hoveredNode,
displayedNodeLabels: this.displayedLabels,
highlightedNodes: this.highlightedNodes,
});
for (var i = 0, l = edgeLabelsToDisplay.length; i < l; i++) {
var edge = edgeLabelsToDisplay[i], extremities = this.graph.extremities(edge), sourceData = this.nodeDataCache[extremities[0]], targetData = this.nodeDataCache[extremities[1]], edgeData = this.edgeDataCache[edgeLabelsToDisplay[i]];
var _a = this.camera.graphToViewport(this, sourceData.x, sourceData.y), sourceX = _a.x, sourceY = _a.y;
var _b = this.camera.graphToViewport(this, targetData.x, targetData.y), targetX = _b.x, targetY = _b.y;
// TODO: we can cache the labels we need to render until the camera's ratio changes
// TODO: this should be computed in the canvas components?
var size = edgeData.size / sizeRatio;
this.settings.edgeLabelRenderer(context, {
key: edge,
label: edgeData.label,
color: edgeData.color,
size: size,
}, {
key: extremities[0],
x: sourceX,
y: sourceY,
}, {
key: extremities[1],
x: targetX,
y: targetY,
}, this.settings);
}
return this;
};
/**
* Method used to render the highlighted nodes.
*
* @return {WebGLRenderer}
*/
WebGLRenderer.prototype.renderHighlightedNodes = function () {
var _this = this;
var camera = this.camera;
var sizeRatio = Math.pow(camera.getState().ratio, 0.5);
var context = this.contexts.hovers;
// Clearing
context.clearRect(0, 0, this.width, this.height);
// Rendering
_this6.render();
});
}
var render = function (node) {
var data = _this.nodeDataCache[node];
var _a = camera.graphToViewport(_this, data.x, data.y), x = _a.x, y = _a.y;
var size = data.size / sizeRatio;
_this.settings.hoverRenderer(context, {
key: node,
label: data.label,
color: data.color,
size: size,
x: x,
y: y,
}, _this.settings);
};
if (this.hoveredNode)
render(this.hoveredNode);
this.highlightedNodes.forEach(render);
};
/**
* Method used to schedule a render.
*
* @return {WebGLRenderer}
*/
WebGLRenderer.prototype.scheduleRender = function () {
var _this = this;
// A frame is already scheduled
if (this.renderFrame)
return this;
// Let's schedule a frame
this.renderFrame = requestAnimationFrame(function () {
// Do we need to process data?
if (_this.needToProcess) {
_this.process();
}
else if (_this.needToSoftProcess) {
_this.process(true);
}
// Resetting state
_this.renderFrame = null;
_this.needToProcess = false;
_this.needToSoftProcess = false;
// Rendering
_this.render();
});
};
/**
* Method used to schedule a hover render.

@@ -906,21 +750,25 @@ *

*/
}, {
key: 'scheduleHighlightedNodesRender',
value: function scheduleHighlightedNodesRender() {
var _this7 = this;
if (this.renderHighlightedNodesFrame || this.renderFrame) return this;
this.renderHighlightedNodesFrame = requestAnimationFrame(function () {
// Resetting state
_this7.renderHighlightedNodesFrame = null;
// Rendering
_this7.renderHighlightedNodes();
});
}
WebGLRenderer.prototype.scheduleHighlightedNodesRender = function () {
var _this = this;
if (this.renderHighlightedNodesFrame || this.renderFrame)
return this;
this.renderHighlightedNodesFrame = requestAnimationFrame(function () {
// Resetting state
_this.renderHighlightedNodesFrame = null;
// Rendering
_this.renderHighlightedNodes();
_this.renderEdgeLabels();
});
};
/**
* Method used to manually refresh.
*
* @return {WebGLRenderer}
*/
WebGLRenderer.prototype.refresh = function () {
this.needToSoftProcess = true;
this.scheduleRender();
return this;
};
/**
* Method used to highlight a node.

@@ -931,17 +779,10 @@ *

*/
}, {
key: 'highlightNode',
value: function highlightNode(key) {
// TODO: check the existence of the node
// TODO: coerce?
this.highlightedNodes.add(key);
// Rendering
this.scheduleHighlightedNodesRender();
return this;
}
WebGLRenderer.prototype.highlightNode = function (key) {
// TODO: check the existence of the node
// TODO: coerce?
this.highlightedNodes.add(key);
// Rendering
this.scheduleHighlightedNodesRender();
return this;
};
/**

@@ -953,21 +794,56 @@ * Method used to unhighlight a node.

*/
}, {
key: 'unhighlightNode',
value: function unhighlightNode(key) {
// TODO: check the existence of the node
// TODO: coerce?
this.highlightedNodes.delete(key);
// Rendering
this.scheduleHighlightedNodesRender();
return this;
}
}]);
return WebGLRenderer;
}(_renderer2.default);
exports.default = WebGLRenderer;
WebGLRenderer.prototype.unhighlightNode = function (key) {
// TODO: check the existence of the node
// TODO: coerce?
this.highlightedNodes.delete(key);
// Rendering
this.scheduleHighlightedNodesRender();
return this;
};
/**
* Method used to shut the container & release event listeners.
*
* @return {undefined}
*/
WebGLRenderer.prototype.kill = function () {
var graph = this.graph;
// Emitting "kill" events so that plugins and such can cleanup
this.emit("kill");
// Releasing events
this.removeAllListeners();
// Releasing camera handlers
this.camera.removeListener("updated", this.listeners.camera);
// Releasing DOM events & captors
window.removeEventListener("resize", this.listeners.handleResize);
this.captors.mouse.kill();
// Releasing graph handlers
graph.removeListener("nodeAdded", this.listeners.addNodeGraphUpdate);
graph.removeListener("nodeDropped", this.listeners.graphUpdate);
graph.removeListener("nodeAttributesUpdated", this.listeners.softGraphUpdate);
graph.removeListener("edgeAdded", this.listeners.addEdgeGraphUpdate);
graph.removeListener("nodeDropped", this.listeners.graphUpdate);
graph.removeListener("edgeAttributesUpdated", this.listeners.softGraphUpdate);
graph.removeListener("cleared", this.listeners.graphUpdate);
// Releasing cache & state
this.quadtree = null;
this.nodeDataCache = null;
this.edgeDataCache = null;
this.highlightedNodes = null;
this.displayedLabels = null;
// Clearing frames
if (this.renderFrame) {
cancelAnimationFrame(this.renderFrame);
this.renderFrame = null;
}
if (this.renderHighlightedNodesFrame) {
cancelAnimationFrame(this.renderHighlightedNodesFrame);
this.renderHighlightedNodesFrame = null;
}
// Destroying canvases
var container = this.container;
while (container.firstChild)
container.removeChild(container.firstChild);
};
return WebGLRenderer;
}(renderer_1.default));
exports.default = WebGLRenderer;

@@ -1,114 +0,85 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _program = require('./program');
var _program2 = _interopRequireDefault(_program);
var _utils = require('../utils');
var _edgeFastVert = require('../shaders/edge.fast.vert.glsl');
var _edgeFastVert2 = _interopRequireDefault(_edgeFastVert);
var _edgeFastFrag = require('../shaders/edge.fast.frag.glsl');
var _edgeFastFrag2 = _interopRequireDefault(_edgeFastFrag);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Sigma.js WebGL Renderer Node Program
* =====================================
*
* Program rendering edges using GL_LINES which is presumably very fast but
* won't render thickness correctly on some GPUs and has some quirks.
*/
var EdgeFastProgram = function (_Program) {
_inherits(EdgeFastProgram, _Program);
function EdgeFastProgram() {
_classCallCheck(this, EdgeFastProgram);
var _this = _possibleConstructorReturn(this, (EdgeFastProgram.__proto__ || Object.getPrototypeOf(EdgeFastProgram)).call(this));
_this.vertexShaderSource = _edgeFastVert2.default;
_this.fragmentShaderSource = _edgeFastFrag2.default;
return _this;
}
_createClass(EdgeFastProgram, [{
key: 'process',
value: function process(array, sourceData, targetData, data, i) {
if (sourceData.hidden || targetData.hidden || data.hidden) {
for (var l = i + EdgeFastProgram.POINTS * EdgeFastProgram.ATTRIBUTES; i < l; i++) {
array[i] = 0;
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sigma.js WebGL Renderer Fast Edge Program
* ==========================================
*
* Program rendering edges using GL_LINES which is presumably very fast but
* won't render thickness correctly on some GPUs and has some quirks.
*/
var program_1 = __importDefault(require("./program"));
var utils_1 = require("../utils");
var edge_fast_vert_glsl_1 = __importDefault(require("../shaders/edge.fast.vert.glsl.js"));
var edge_fast_frag_glsl_1 = __importDefault(require("../shaders/edge.fast.frag.glsl.js"));
var POINTS = 2, ATTRIBUTES = 3;
var EdgeFastProgram = /** @class */ (function (_super) {
__extends(EdgeFastProgram, _super);
function EdgeFastProgram(gl) {
var _this = _super.call(this, gl, edge_fast_vert_glsl_1.default, edge_fast_frag_glsl_1.default) || this;
// Locations
_this.positionLocation = gl.getAttribLocation(_this.program, "a_position");
_this.colorLocation = gl.getAttribLocation(_this.program, "a_color");
_this.resolutionLocation = gl.getUniformLocation(_this.program, "u_resolution");
_this.matrixLocation = gl.getUniformLocation(_this.program, "u_matrix");
// Bindings
gl.enableVertexAttribArray(_this.positionLocation);
gl.enableVertexAttribArray(_this.colorLocation);
gl.vertexAttribPointer(_this.positionLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(_this.colorLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
return _this;
}
EdgeFastProgram.prototype.allocate = function (capacity) {
this.array = new Float32Array(POINTS * ATTRIBUTES * capacity);
};
EdgeFastProgram.prototype.process = function (sourceData, targetData, data, offset) {
var array = this.array;
var i = 0;
if (sourceData.hidden || targetData.hidden || data.hidden) {
for (var l = i + POINTS * ATTRIBUTES; i < l; i++)
array[i] = 0;
}
}
var thickness = data.size || 1,
x1 = sourceData.x,
y1 = sourceData.y,
x2 = targetData.x,
y2 = targetData.y,
color = (0, _utils.floatColor)(data.color);
array[i++] = x1;
array[i++] = y1;
array[i++] = color;
array[i++] = x2;
array[i++] = y2;
array[i++] = color;
}
}, {
key: 'render',
value: function render(gl, array, params) {
var program = this.program;
gl.useProgram(program);
// Attribute locations
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');
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, array, 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, EdgeFastProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(colorLocation, 1, gl.FLOAT, false, EdgeFastProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
// TODO: use gl line thickness
gl.lineWidth(3);
gl.drawArrays(gl.LINES, 0, array.length / EdgeFastProgram.ATTRIBUTES);
}
}]);
return EdgeFastProgram;
}(_program2.default);
var x1 = sourceData.x, y1 = sourceData.y, x2 = targetData.x, y2 = targetData.y, color = utils_1.floatColor(data.color);
i = POINTS * ATTRIBUTES * offset;
// First point
array[i++] = x1;
array[i++] = y1;
array[i++] = color;
// Second point
array[i++] = x2;
array[i++] = y2;
array[i] = color;
};
EdgeFastProgram.prototype.bufferData = function () {
var gl = this.gl;
// Vertices data
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW);
};
EdgeFastProgram.prototype.render = function (params) {
var gl = this.gl;
var program = this.program;
gl.useProgram(program);
// Binding uniforms
gl.uniform2f(this.resolutionLocation, params.width, params.height);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
// Drawing:
gl.drawArrays(gl.LINES, 0, this.array.length / ATTRIBUTES);
};
return EdgeFastProgram;
}(program_1.default));
exports.default = EdgeFastProgram;
EdgeFastProgram.POINTS = 2;
EdgeFastProgram.ATTRIBUTES = 3;

@@ -1,198 +0,167 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _program = require('./program');
var _program2 = _interopRequireDefault(_program);
var _utils = require('../utils');
var _edgeVert = require('../shaders/edge.vert.glsl');
var _edgeVert2 = _interopRequireDefault(_edgeVert);
var _edgeFrag = require('../shaders/edge.frag.glsl');
var _edgeFrag2 = _interopRequireDefault(_edgeFrag);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Sigma.js WebGL Renderer Node Program
* =====================================
*
* Program rendering edges as thick lines using four points translated
* orthogonally from the source & target's centers by half thickness.
*
* Rendering two triangles by using only four points is made possible through
* the use of indices.
*
* This method should be faster than the 6 points / 2 triangles approach and
* should handle thickness better than with gl.LINES.
*
* This version of the shader balances geometry computation evenly between
* the CPU & GPU (normals are computed on the CPU side).
*/
var EdgeProgram = function (_Program) {
_inherits(EdgeProgram, _Program);
function EdgeProgram(gl) {
_classCallCheck(this, EdgeProgram);
// Initializing buffers
var _this = _possibleConstructorReturn(this, (EdgeProgram.__proto__ || Object.getPrototypeOf(EdgeProgram)).call(this, gl, _edgeVert2.default, _edgeFrag2.default));
_this.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, _this.buffer);
_this.indicesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _this.indicesBuffer);
// Locations
_this.positionLocation = gl.getAttribLocation(_this.program, 'a_position');
_this.normalLocation = gl.getAttribLocation(_this.program, 'a_normal');
_this.thicknessLocation = gl.getAttribLocation(_this.program, 'a_thickness');
_this.colorLocation = gl.getAttribLocation(_this.program, 'a_color');
_this.resolutionLocation = gl.getUniformLocation(_this.program, 'u_resolution');
_this.ratioLocation = gl.getUniformLocation(_this.program, 'u_ratio');
_this.matrixLocation = gl.getUniformLocation(_this.program, 'u_matrix');
// Bindings
gl.enableVertexAttribArray(_this.positionLocation);
gl.enableVertexAttribArray(_this.normalLocation);
gl.enableVertexAttribArray(_this.thicknessLocation);
gl.enableVertexAttribArray(_this.colorLocation);
gl.vertexAttribPointer(_this.positionLocation, 2, gl.FLOAT, false, EdgeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(_this.normalLocation, 2, gl.FLOAT, false, EdgeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(_this.thicknessLocation, 1, gl.FLOAT, false, EdgeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
gl.vertexAttribPointer(_this.colorLocation, 1, gl.FLOAT, false, EdgeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 20);
return _this;
}
_createClass(EdgeProgram, [{
key: 'process',
value: function process(array, sourceData, targetData, data, i) {
if (sourceData.hidden || targetData.hidden || data.hidden) {
for (var l = i + EdgeProgram.POINTS * EdgeProgram.ATTRIBUTES; i < l; i++) {
array[i] = 0;
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sigma.js WebGL Renderer Edge Program
* =====================================
*
* Program rendering edges as thick lines using four points translated
* orthogonally from the source & target's centers by half thickness.
*
* Rendering two triangles by using only four points is made possible through
* the use of indices.
*
* This method should be faster than the 6 points / 2 triangles approach and
* should handle thickness better than with gl.LINES.
*
* This version of the shader balances geometry computation evenly between
* the CPU & GPU (normals are computed on the CPU side).
*/
var program_1 = __importDefault(require("./program"));
var utils_1 = require("../utils");
var edge_vert_glsl_1 = __importDefault(require("../shaders/edge.vert.glsl.js"));
var edge_frag_glsl_1 = __importDefault(require("../shaders/edge.frag.glsl.js"));
var POINTS = 4, ATTRIBUTES = 6, STRIDE = POINTS * ATTRIBUTES;
var EdgeProgram = /** @class */ (function (_super) {
__extends(EdgeProgram, _super);
function EdgeProgram(gl) {
var _this = _super.call(this, gl, edge_vert_glsl_1.default, edge_frag_glsl_1.default) || this;
// Initializing indices buffer
_this.indicesBuffer = gl.createBuffer();
// Locations
_this.positionLocation = gl.getAttribLocation(_this.program, "a_position");
_this.normalLocation = gl.getAttribLocation(_this.program, "a_normal");
_this.thicknessLocation = gl.getAttribLocation(_this.program, "a_thickness");
_this.colorLocation = gl.getAttribLocation(_this.program, "a_color");
_this.resolutionLocation = gl.getUniformLocation(_this.program, "u_resolution");
_this.ratioLocation = gl.getUniformLocation(_this.program, "u_ratio");
_this.matrixLocation = gl.getUniformLocation(_this.program, "u_matrix");
_this.scaleLocation = gl.getUniformLocation(_this.program, "u_scale");
_this.bind();
// Enabling the OES_element_index_uint extension
// NOTE: on older GPUs, this means that really large graphs won't
// have all their edges rendered. But it seems that the
// `OES_element_index_uint` is quite everywhere so we'll handle
// the potential issue if it really arises.
// NOTE: when using webgl2, the extension is enabled by default
_this.canUse32BitsIndices = utils_1.canUse32BitsIndices(gl);
_this.IndicesArray = _this.canUse32BitsIndices ? Uint32Array : Uint16Array;
_this.indicesType = _this.canUse32BitsIndices ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT;
return _this;
}
EdgeProgram.prototype.bind = function () {
var gl = this.gl;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
// Bindings
gl.enableVertexAttribArray(this.positionLocation);
gl.enableVertexAttribArray(this.normalLocation);
gl.enableVertexAttribArray(this.thicknessLocation);
gl.enableVertexAttribArray(this.colorLocation);
gl.vertexAttribPointer(this.positionLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(this.normalLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(this.thicknessLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
gl.vertexAttribPointer(this.colorLocation, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 20);
};
EdgeProgram.prototype.allocate = function (capacity) {
this.array = new Float32Array(POINTS * ATTRIBUTES * capacity);
};
EdgeProgram.prototype.process = function (sourceData, targetData, data, offset) {
if (sourceData.hidden || targetData.hidden || data.hidden) {
for (var i_1 = offset * STRIDE, l = i_1 + STRIDE; i_1 < l; i_1++)
this.array[i_1] = 0;
return;
}
}
var thickness = data.size || 1,
x1 = sourceData.x,
y1 = sourceData.y,
x2 = targetData.x,
y2 = targetData.y,
color = (0, _utils.floatColor)(data.color);
// Computing normals
var dx = x2 - x1,
dy = y2 - y1;
var len = dx * dx + dy * dy,
n1 = 0,
n2 = 0;
if (len) {
len = 1 / Math.sqrt(len);
n1 = -dy * len;
n2 = dx * len;
}
// First point
array[i++] = x1;
array[i++] = y1;
array[i++] = n1;
array[i++] = n2;
array[i++] = thickness;
array[i++] = color;
// First point flipped
array[i++] = x1;
array[i++] = y1;
array[i++] = -n1;
array[i++] = -n2;
array[i++] = thickness;
array[i++] = color;
// Second point
array[i++] = x2;
array[i++] = y2;
array[i++] = n1;
array[i++] = n2;
array[i++] = thickness;
array[i++] = color;
// Second point flipped
array[i++] = x2;
array[i++] = y2;
array[i++] = -n1;
array[i++] = -n2;
array[i++] = thickness;
array[i++] = color;
}
}, {
key: 'computeIndices',
value: function computeIndices(array) {
var l = array.length / EdgeProgram.ATTRIBUTES;
var size = l + l / 2;
var indices = new Uint16Array(size);
for (var i = 0, c = 0; i < size; i += 4) {
indices[c++] = i;
indices[c++] = i + 1;
indices[c++] = i + 2;
indices[c++] = i + 2;
indices[c++] = i + 1;
indices[c++] = i + 3;
}
return indices;
}
}, {
key: 'render',
value: function render(gl, array, params) {
var program = this.program;
gl.useProgram(program);
// Buffer data
gl.bufferData(gl.ARRAY_BUFFER, array, gl.DYNAMIC_DRAW);
// Binding uniforms
gl.uniform2f(this.resolutionLocation, params.width, params.height);
gl.uniform1f(this.ratioLocation, params.ratio / Math.pow(params.ratio, params.edgesPowRatio));
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
// Buffering indices data
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, params.indices, gl.STATIC_DRAW);
// Drawing:
gl.drawElements(gl.TRIANGLES, params.indices.length, gl.UNSIGNED_SHORT, 0);
}
}]);
return EdgeProgram;
}(_program2.default);
var thickness = data.size || 1, x1 = sourceData.x, y1 = sourceData.y, x2 = targetData.x, y2 = targetData.y, color = utils_1.floatColor(data.color);
// Computing normals
var dx = x2 - x1, dy = y2 - y1;
var len = dx * dx + dy * dy, n1 = 0, n2 = 0;
if (len) {
len = 1 / Math.sqrt(len);
n1 = -dy * len;
n2 = dx * len;
}
var i = POINTS * ATTRIBUTES * offset;
var array = this.array;
// First point
array[i++] = x1;
array[i++] = y1;
array[i++] = n1;
array[i++] = n2;
array[i++] = thickness;
array[i++] = color;
// First point flipped
array[i++] = x1;
array[i++] = y1;
array[i++] = -n1;
array[i++] = -n2;
array[i++] = thickness;
array[i++] = color;
// Second point
array[i++] = x2;
array[i++] = y2;
array[i++] = n1;
array[i++] = n2;
array[i++] = thickness;
array[i++] = color;
// Second point flipped
array[i++] = x2;
array[i++] = y2;
array[i++] = -n1;
array[i++] = -n2;
array[i++] = thickness;
array[i] = color;
};
EdgeProgram.prototype.computeIndices = function () {
var l = this.array.length / ATTRIBUTES;
var size = l + l / 2;
var indices = new this.IndicesArray(size);
for (var i = 0, c = 0; i < l; i += 4) {
indices[c++] = i;
indices[c++] = i + 1;
indices[c++] = i + 2;
indices[c++] = i + 2;
indices[c++] = i + 1;
indices[c++] = i + 3;
}
this.indicesArray = indices;
};
EdgeProgram.prototype.bufferData = function () {
var gl = this.gl;
// Vertices data
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW);
// Indices data
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indicesArray, gl.STATIC_DRAW);
};
EdgeProgram.prototype.render = function (params) {
var gl = this.gl;
var program = this.program;
gl.useProgram(program);
// Binding uniforms
// TODO: precise the uniform names
gl.uniform2f(this.resolutionLocation, params.width, params.height);
gl.uniform1f(this.ratioLocation,
// 1 / Math.pow(params.ratio, params.edgesPowRatio)
params.ratio);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
gl.uniform1f(this.scaleLocation, params.scalingRatio);
// Drawing:
gl.drawElements(gl.TRIANGLES, this.indicesArray.length, this.indicesType, 0);
};
return EdgeProgram;
}(program_1.default));
exports.default = EdgeProgram;
EdgeProgram.POINTS = 4;
EdgeProgram.ATTRIBUTES = 6;

@@ -1,105 +0,87 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _program = require('./program');
var _program2 = _interopRequireDefault(_program);
var _utils = require('../utils');
var _nodeFastVert = require('../shaders/node.fast.vert.glsl');
var _nodeFastVert2 = _interopRequireDefault(_nodeFastVert);
var _nodeFastFrag = require('../shaders/node.fast.frag.glsl');
var _nodeFastFrag2 = _interopRequireDefault(_nodeFastFrag);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Sigma.js WebGL Renderer Node Program
* =====================================
*
* Simple program rendering nodes using GL_POINTS. This is faster than the
* three triangle option but has some quirks and is not supported equally by
* every GPU.
*/
var NodeProgramFast = function (_Program) {
_inherits(NodeProgramFast, _Program);
function NodeProgramFast() {
_classCallCheck(this, NodeProgramFast);
var _this = _possibleConstructorReturn(this, (NodeProgramFast.__proto__ || Object.getPrototypeOf(NodeProgramFast)).call(this));
_this.vertexShaderSource = _nodeFastVert2.default;
_this.fragmentShaderSource = _nodeFastFrag2.default;
return _this;
}
_createClass(NodeProgramFast, [{
key: 'process',
value: function process(array, data, i) {
var color = (0, _utils.floatColor)(data.color);
array[i++] = data.x;
array[i++] = data.y;
array[i++] = data.size;
array[i++] = color;
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sigma.js WebGL Renderer Node Program
* =====================================
*
* Simple program rendering nodes using GL_POINTS. This is faster than the
* three triangle option but has some quirks and is not supported equally by
* every GPU.
*/
var program_1 = __importDefault(require("./program"));
var utils_1 = require("../utils");
var node_fast_vert_glsl_1 = __importDefault(require("../shaders/node.fast.vert.glsl.js"));
var node_fast_frag_glsl_1 = __importDefault(require("../shaders/node.fast.frag.glsl.js"));
var POINTS = 1, ATTRIBUTES = 4;
var NodeProgramFast = /** @class */ (function (_super) {
__extends(NodeProgramFast, _super);
function NodeProgramFast(gl) {
var _this = _super.call(this, gl, node_fast_vert_glsl_1.default, node_fast_frag_glsl_1.default) || this;
var program = _this.program;
// Locations
_this.positionLocation = gl.getAttribLocation(program, "a_position");
_this.sizeLocation = gl.getAttribLocation(program, "a_size");
_this.colorLocation = gl.getAttribLocation(program, "a_color");
_this.matrixLocation = gl.getUniformLocation(program, "u_matrix");
_this.ratioLocation = gl.getUniformLocation(program, "u_ratio");
_this.scaleLocation = gl.getUniformLocation(program, "u_scale");
// Bindings
gl.enableVertexAttribArray(_this.positionLocation);
gl.enableVertexAttribArray(_this.sizeLocation);
gl.enableVertexAttribArray(_this.colorLocation);
gl.vertexAttribPointer(_this.positionLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(_this.sizeLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(_this.colorLocation, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 12);
return _this;
}
}, {
key: 'render',
value: function render(gl, array, params) {
var program = this.program;
gl.useProgram(program);
// Attribute locations
var positionLocation = gl.getAttribLocation(program, 'a_position'),
sizeLocation = gl.getAttribLocation(program, 'a_size'),
colorLocation = gl.getAttribLocation(program, 'a_color'),
resolutionLocation = gl.getUniformLocation(program, 'u_resolution'),
matrixLocation = gl.getUniformLocation(program, 'u_matrix'),
ratioLocation = gl.getUniformLocation(program, 'u_ratio'),
scaleLocation = gl.getUniformLocation(program, 'u_scale');
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.DYNAMIC_DRAW);
gl.uniform2f(resolutionLocation, params.width, params.height);
gl.uniform1f(ratioLocation, 1 / Math.pow(params.ratio, params.nodesPowRatio));
gl.uniform1f(scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
gl.enableVertexAttribArray(positionLocation);
gl.enableVertexAttribArray(sizeLocation);
gl.enableVertexAttribArray(colorLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, NodeProgramFast.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(sizeLocation, 1, gl.FLOAT, false, NodeProgramFast.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(colorLocation, 1, gl.FLOAT, false, NodeProgramFast.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 12);
gl.drawArrays(gl.POINTS, 0, array.length / NodeProgramFast.ATTRIBUTES);
}
}]);
return NodeProgramFast;
}(_program2.default);
NodeProgramFast.prototype.allocate = function (capacity) {
this.array = new Float32Array(POINTS * ATTRIBUTES * capacity);
};
NodeProgramFast.prototype.process = function (data, offset) {
var color = utils_1.floatColor(data.color);
var i = offset * POINTS * ATTRIBUTES;
var array = this.array;
if (data.hidden) {
array[i++] = 0;
array[i++] = 0;
array[i++] = 0;
array[i++] = 0;
return;
}
array[i++] = data.x;
array[i++] = data.y;
array[i++] = data.size;
array[i] = color;
};
NodeProgramFast.prototype.bufferData = function () {
var gl = this.gl;
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW);
};
NodeProgramFast.prototype.render = function (params) {
var gl = this.gl;
var program = this.program;
gl.useProgram(program);
gl.uniform1f(this.ratioLocation, 1 / Math.pow(params.ratio, params.nodesPowRatio));
gl.uniform1f(this.scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
gl.drawArrays(gl.POINTS, 0, this.array.length / ATTRIBUTES);
};
return NodeProgramFast;
}(program_1.default));
exports.default = NodeProgramFast;
NodeProgramFast.POINTS = 1;
NodeProgramFast.ATTRIBUTES = 4;

@@ -1,129 +0,97 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _program = require('./program');
var _program2 = _interopRequireDefault(_program);
var _utils = require('../utils');
var _nodeVert = require('../shaders/node.vert.glsl');
var _nodeVert2 = _interopRequireDefault(_nodeVert);
var _nodeFrag = require('../shaders/node.frag.glsl');
var _nodeFrag2 = _interopRequireDefault(_nodeFrag);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Sigma.js WebGL Renderer Node Program
* =====================================
*
* Simple program rendering nodes as discs, shaped by triangles using the
* `gl.TRIANGLES` display mode. So, to draw one node, it will need to store
* three times the center of the node, with the color, the size and an angle
* indicating which "corner" of the triangle to draw.
*/
var ANGLE_1 = 0,
ANGLE_2 = 2 * Math.PI / 3,
ANGLE_3 = 4 * Math.PI / 3;
var NodeProgram = function (_Program) {
_inherits(NodeProgram, _Program);
function NodeProgram(gl) {
_classCallCheck(this, NodeProgram);
// Initializing buffers
var _this = _possibleConstructorReturn(this, (NodeProgram.__proto__ || Object.getPrototypeOf(NodeProgram)).call(this, gl, _nodeVert2.default, _nodeFrag2.default));
_this.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, _this.buffer);
// Locations
_this.positionLocation = gl.getAttribLocation(_this.program, 'a_position');
_this.sizeLocation = gl.getAttribLocation(_this.program, 'a_size');
_this.colorLocation = gl.getAttribLocation(_this.program, 'a_color');
_this.angleLocation = gl.getAttribLocation(_this.program, 'a_angle');
_this.resolutionLocation = gl.getUniformLocation(_this.program, 'u_resolution');
_this.matrixLocation = gl.getUniformLocation(_this.program, 'u_matrix');
_this.ratioLocation = gl.getUniformLocation(_this.program, 'u_ratio');
_this.scaleLocation = gl.getUniformLocation(_this.program, 'u_scale');
// Bindings
gl.enableVertexAttribArray(_this.positionLocation);
gl.enableVertexAttribArray(_this.sizeLocation);
gl.enableVertexAttribArray(_this.colorLocation);
gl.enableVertexAttribArray(_this.angleLocation);
gl.vertexAttribPointer(_this.positionLocation, 2, gl.FLOAT, false, NodeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(_this.sizeLocation, 1, gl.FLOAT, false, NodeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(_this.colorLocation, 1, gl.FLOAT, false, NodeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 12);
gl.vertexAttribPointer(_this.angleLocation, 1, gl.FLOAT, false, NodeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
return _this;
}
_createClass(NodeProgram, [{
key: 'process',
value: function process(array, data, i) {
var color = (0, _utils.floatColor)(data.color);
array[i++] = data.x;
array[i++] = data.y;
array[i++] = data.size;
array[i++] = color;
array[i++] = ANGLE_1;
array[i++] = data.x;
array[i++] = data.y;
array[i++] = data.size;
array[i++] = color;
array[i++] = ANGLE_2;
array[i++] = data.x;
array[i++] = data.y;
array[i++] = data.size;
array[i++] = color;
array[i++] = ANGLE_3;
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sigma.js WebGL Renderer Node Program
* =====================================
*
* Simple program rendering nodes as discs, shaped by triangles using the
* `gl.TRIANGLES` display mode. So, to draw one node, it will need to store
* three times the center of the node, with the color, the size and an angle
* indicating which "corner" of the triangle to draw.
*/
var program_1 = __importDefault(require("./program"));
var utils_1 = require("../utils");
var node_vert_glsl_1 = __importDefault(require("../shaders/node.vert.glsl.js"));
var node_frag_glsl_1 = __importDefault(require("../shaders/node.frag.glsl.js"));
var ANGLE_1 = 0, ANGLE_2 = (2 * Math.PI) / 3, ANGLE_3 = (4 * Math.PI) / 3;
var POINTS = 3, ATTRIBUTES = 5;
var NodeProgram = /** @class */ (function (_super) {
__extends(NodeProgram, _super);
function NodeProgram(gl) {
var _this = _super.call(this, gl, node_vert_glsl_1.default, node_frag_glsl_1.default) || this;
// Locations
_this.positionLocation = gl.getAttribLocation(_this.program, "a_position");
_this.sizeLocation = gl.getAttribLocation(_this.program, "a_size");
_this.colorLocation = gl.getAttribLocation(_this.program, "a_color");
_this.angleLocation = gl.getAttribLocation(_this.program, "a_angle");
_this.resolutionLocation = gl.getUniformLocation(_this.program, "u_resolution");
_this.matrixLocation = gl.getUniformLocation(_this.program, "u_matrix");
_this.ratioLocation = gl.getUniformLocation(_this.program, "u_ratio");
_this.scaleLocation = gl.getUniformLocation(_this.program, "u_scale");
// Bindings
gl.enableVertexAttribArray(_this.positionLocation);
gl.enableVertexAttribArray(_this.sizeLocation);
gl.enableVertexAttribArray(_this.colorLocation);
gl.enableVertexAttribArray(_this.angleLocation);
gl.vertexAttribPointer(_this.positionLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(_this.sizeLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(_this.colorLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 12);
gl.vertexAttribPointer(_this.angleLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
return _this;
}
}, {
key: 'render',
value: function render(gl, array, params) {
var program = this.program;
gl.useProgram(program);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.DYNAMIC_DRAW);
gl.uniform2f(this.resolutionLocation, params.width, params.height);
gl.uniform1f(this.ratioLocation, 1 / Math.pow(params.ratio, params.nodesPowRatio));
gl.uniform1f(this.scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
gl.drawArrays(gl.TRIANGLES, 0, array.length / NodeProgram.ATTRIBUTES);
}
}]);
return NodeProgram;
}(_program2.default);
NodeProgram.prototype.allocate = function (capacity) {
this.array = new Float32Array(POINTS * ATTRIBUTES * capacity);
};
NodeProgram.prototype.process = function (data, offset) {
var color = utils_1.floatColor(data.color);
var i = offset * POINTS * ATTRIBUTES;
var array = this.array;
array[i++] = data.x;
array[i++] = data.y;
array[i++] = data.size;
array[i++] = color;
array[i++] = ANGLE_1;
array[i++] = data.x;
array[i++] = data.y;
array[i++] = data.size;
array[i++] = color;
array[i++] = ANGLE_2;
array[i++] = data.x;
array[i++] = data.y;
array[i++] = data.size;
array[i++] = color;
array[i] = ANGLE_3;
};
NodeProgram.prototype.bufferData = function () {
var gl = this.gl;
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW);
};
NodeProgram.prototype.render = function (params) {
var gl = this.gl;
var program = this.program;
gl.useProgram(program);
gl.uniform2f(this.resolutionLocation, params.width, params.height);
gl.uniform1f(this.ratioLocation, 1 / Math.pow(params.ratio, params.nodesPowRatio));
gl.uniform1f(this.scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
gl.drawArrays(gl.TRIANGLES, 0, this.array.length / ATTRIBUTES);
};
return NodeProgram;
}(program_1.default));
exports.default = NodeProgram;
NodeProgram.POINTS = 3;
NodeProgram.ATTRIBUTES = 5;

@@ -1,20 +0,32 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
* Sigma.js WebGL Renderer Program
* ================================
*
* Class representing a single WebGL program used by sigma's WebGL renderer.
*/
var _utils = require('../shaders/utils');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
"use strict";
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCompoundProgram = void 0;
/**
* Sigma.js WebGL Renderer Program
* ================================
*
* Class representing a single WebGL program used by sigma's WebGL renderer.
*/
var utils_1 = require("../shaders/utils");
/**
* Program class.

@@ -24,35 +36,69 @@ *

*/
var Program = function () {
function Program(gl, vertexShaderSource, fragmentShaderSource) {
_classCallCheck(this, Program);
this.vertexShaderSource = vertexShaderSource;
this.fragmentShaderSource = fragmentShaderSource;
this.load(gl);
}
/**
* Method used to load the program into a webgl context.
*
* @param {WebGLContext} gl - The WebGL context.
* @return {WebGLProgram}
*/
_createClass(Program, [{
key: 'load',
value: function load(gl) {
this.vertexShader = (0, _utils.loadVertexShader)(gl, this.vertexShaderSource);
this.fragmentShader = (0, _utils.loadFragmentShader)(gl, this.fragmentShaderSource);
this.program = (0, _utils.loadProgram)(gl, [this.vertexShader, this.fragmentShader]);
return this.program;
var Program = /** @class */ (function () {
function Program(gl, vertexShaderSource, fragmentShaderSource) {
this.array = null;
// Binding context
this.gl = gl;
this.vertexShaderSource = vertexShaderSource;
this.fragmentShaderSource = fragmentShaderSource;
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
this.load(gl);
}
}]);
return Program;
}();
exports.default = Program;
/**
* Method used to load the program into a webgl context.
*
* @param {WebGLContext} gl - The WebGL context.
* @return {WebGLProgram}
*/
Program.prototype.load = function (gl) {
this.vertexShader = utils_1.loadVertexShader(gl, this.vertexShaderSource);
this.fragmentShader = utils_1.loadFragmentShader(gl, this.fragmentShaderSource);
this.program = utils_1.loadProgram(gl, [this.vertexShader, this.fragmentShader]);
return this.program;
};
return Program;
}());
exports.default = Program;
/**
* Helper function combining two or more programs into a single compound one.
* Note that this is more a quick & easy way to combine program than a really
* performant option. More performant programs can be written entirely.
*
* @param {array} programClasses - Program classes to combine.
* @return {function}
*/
// TODO: maybe those should handle their own canvases
function createCompoundProgram(programClasses) {
return /** @class */ (function () {
function CompoundProgram(gl) {
this.programs = programClasses.map(function (ProgramClass) { return new ProgramClass(gl); });
}
CompoundProgram.prototype.allocate = function (capacity) {
this.programs.forEach(function (program) { return program.allocate(capacity); });
};
CompoundProgram.prototype.process = function () {
var args = arguments;
this.programs.forEach(function (program) { return program.process.apply(program, __spread(args)); });
};
CompoundProgram.prototype.computeIndices = function () {
this.programs.forEach(function (program) {
if (typeof program.computeIndices === "function")
program.computeIndices();
});
};
CompoundProgram.prototype.bufferData = function () {
this.programs.forEach(function (program) { return program.bufferData(); });
};
CompoundProgram.prototype.render = function () {
var args = arguments;
this.programs.forEach(function (program) {
program.bind();
program.bufferData();
program.render.apply(program, __spread(args));
});
};
return CompoundProgram;
}());
}
exports.createCompoundProgram = createCompoundProgram;

@@ -1,7 +0,2 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.loadProgram = loadProgram;
"use strict";
/**

@@ -13,3 +8,4 @@ * Sigma.js Shader Utils

*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadProgram = exports.loadFragmentShader = exports.loadVertexShader = void 0;
/**

@@ -19,58 +15,40 @@ * Function used to load a shader.

function loadShader(type, gl, source) {
var glType = type === 'VERTEX' ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER;
// Creating the shader
var shader = gl.createShader(glType);
// Loading source
gl.shaderSource(shader, source);
// Compiling the shader
gl.compileShader(shader);
// Retrieving compilation status
var successfullyCompiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
// Throwing if something went awry
if (!successfullyCompiled) {
var infoLog = gl.getShaderInfoLog(shader);
gl.deleteShader(shader);
throw new Error('sigma/renderers/weblg/shaders/utils.loadShader: error while compiling the shader:\n' + infoLog + '\n' + source);
}
return shader;
var glType = type === "VERTEX" ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER;
// Creating the shader
var shader = gl.createShader(glType);
// Loading source
gl.shaderSource(shader, source);
// Compiling the shader
gl.compileShader(shader);
// Retrieving compilation status
var successfullyCompiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
// Throwing if something went awry
if (!successfullyCompiled) {
var infoLog = gl.getShaderInfoLog(shader);
gl.deleteShader(shader);
throw new Error("sigma/renderers/webgl/shaders/utils.loadShader: error while compiling the shader:\n" + infoLog + "\n" + source);
}
return shader;
}
var loadVertexShader = loadShader.bind(null, 'VERTEX'),
loadFragmentShader = loadShader.bind(null, 'FRAGMENT');
var loadVertexShader = loadShader.bind(null, "VERTEX"), loadFragmentShader = loadShader.bind(null, "FRAGMENT");
exports.loadVertexShader = loadVertexShader;
exports.loadFragmentShader = loadFragmentShader;
/**
* Function used to load a program.
*/
function loadProgram(gl, shaders) {
var program = gl.createProgram();
var i = void 0,
l = void 0;
// Attaching the shaders
for (i = 0, l = shaders.length; i < l; i++) {
gl.attachShader(program, shaders[i]);
}gl.linkProgram(program);
// Checking status
var successfullyLinked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!successfullyLinked) {
gl.deleteProgram(program);
throw new Error('sigma/renderers/weblg/shaders/utils.loadProgram: error while linking the program.');
}
return program;
}
var program = gl.createProgram();
var i, l;
// Attaching the shaders
for (i = 0, l = shaders.length; i < l; i++)
gl.attachShader(program, shaders[i]);
gl.linkProgram(program);
// Checking status
var successfullyLinked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!successfullyLinked) {
gl.deleteProgram(program);
throw new Error("sigma/renderers/webgl/shaders/utils.loadProgram: error while linking the program.");
}
return program;
}
exports.loadProgram = loadProgram;

@@ -1,90 +0,74 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.floatColor = floatColor;
exports.matrixFromCamera = matrixFromCamera;
exports.extractPixel = extractPixel;
var _glMatrix = require('gl-matrix');
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.canUse32BitsIndices = exports.extractPixel = exports.matrixFromCamera = exports.floatColor = void 0;
/**
* Sigma.js WebGL Renderer Utils
* ==============================
*
* Miscelleanous helper functions used by sigma's WebGL renderer.
*/
var matrices_1 = require("./matrices");
/**
* Memoized function returning a float-encoded color from various string
* formats describing colors.
*/
var FLOAT_COLOR_CACHE = {}; /**
* Sigma.js WebGL Renderer Utils
* ==============================
*
* Miscelleanous helper functions used by sigma's WebGL renderer.
*/
// TODO: this is heavy for what we do with it
var FLOAT_COLOR_CACHE = {};
var INT8 = new Int8Array(4);
var INT32 = new Int32Array(INT8.buffer, 0, 1);
var FLOAT32 = new Float32Array(INT8.buffer, 0, 1);
var RGBA_TEST_REGEX = /^\s*rgba?\s*\(/;
var RGBA_EXTRACT_REGEX = /^\s*rgba?\s*\(\s*([0-9]*)\s*,\s*([0-9]*)\s*,\s*([0-9]*)\s*(,.*)?\)\s*$/;
var RGBA_EXTRACT_REGEX = /^\s*rgba?\s*\(\s*([0-9]*)\s*,\s*([0-9]*)\s*,\s*([0-9]*)(?:\s*,\s*(.*)?)?\)\s*$/;
function floatColor(val) {
// If the color is already computed, we yield it
if (typeof FLOAT_COLOR_CACHE[val] !== 'undefined') return FLOAT_COLOR_CACHE[val];
var r = 0,
g = 0,
b = 0;
// Handling hexadecimal notation
if (val[0] === '#') {
if (val.length === 4) {
r = parseInt(val.charAt(1) + val.charAt(1), 16);
g = parseInt(val.charAt(2) + val.charAt(2), 16);
b = parseInt(val.charAt(3) + val.charAt(3), 16);
} else {
r = parseInt(val.charAt(1) + val.charAt(2), 16);
g = parseInt(val.charAt(3) + val.charAt(4), 16);
b = parseInt(val.charAt(5) + val.charAt(6), 16);
// If the color is already computed, we yield it
if (typeof FLOAT_COLOR_CACHE[val] !== "undefined")
return FLOAT_COLOR_CACHE[val];
var r = 0, g = 0, b = 0, a = 1;
// Handling hexadecimal notation
if (val[0] === "#") {
if (val.length === 4) {
r = parseInt(val.charAt(1) + val.charAt(1), 16);
g = parseInt(val.charAt(2) + val.charAt(2), 16);
b = parseInt(val.charAt(3) + val.charAt(3), 16);
}
else {
r = parseInt(val.charAt(1) + val.charAt(2), 16);
g = parseInt(val.charAt(3) + val.charAt(4), 16);
b = parseInt(val.charAt(5) + val.charAt(6), 16);
}
}
}
// Handling rgb notation
else if (RGBA_TEST_REGEX.test(val)) {
var match = val.match(RGBA_EXTRACT_REGEX);
r = +match[1];
g = +match[2];
b = +match[3];
// Handling rgb notation
else if (RGBA_TEST_REGEX.test(val)) {
var match = val.match(RGBA_EXTRACT_REGEX);
r = +match[1];
g = +match[2];
b = +match[3];
if (match[4])
a = +match[4];
}
var color = r * 256 * 256 + g * 256 + b;
FLOAT_COLOR_CACHE[val] = color;
return color;
a = (a * 255) | 0;
var bits = ((a << 24) | (b << 16) | (g << 8) | r) & 0xfeffffff;
INT32[0] = bits;
var color = FLOAT32[0];
FLOAT_COLOR_CACHE[val] = color;
return color;
}
exports.floatColor = floatColor;
/**
* Function returning a matrix from the current state of the camera.
*/
// TODO: it's possible to optimize this drastically!
function matrixFromCamera(state) {
var angle = state.angle,
ratio = state.ratio,
x = state.x,
y = state.y;
var matrix = _glMatrix.mat3.create(),
scale = _glMatrix.mat3.fromScaling(_glMatrix.mat3.create(), [1 / ratio, 1 / ratio]),
rotation = _glMatrix.mat3.fromRotation(_glMatrix.mat3.create(), -angle),
translation = _glMatrix.mat3.fromTranslation(_glMatrix.mat3.create(), [-x, -y]);
_glMatrix.mat3.multiply(matrix, scale, rotation);
_glMatrix.mat3.multiply(matrix, matrix, translation);
return matrix;
function matrixFromCamera(state, dimensions) {
var angle = state.angle, ratio = state.ratio, x = state.x, y = state.y;
var width = dimensions.width, height = dimensions.height;
var matrix = matrices_1.identity();
var smallestDimension = Math.min(width, height);
var cameraCentering = matrices_1.translate(matrices_1.identity(), -x, -y), cameraScaling = matrices_1.scale(matrices_1.identity(), 1 / ratio), cameraRotation = matrices_1.rotate(matrices_1.identity(), -angle), viewportScaling = matrices_1.scale(matrices_1.identity(), 2 * (smallestDimension / width), 2 * (smallestDimension / height));
// Logical order is reversed
matrices_1.multiply(matrix, viewportScaling);
matrices_1.multiply(matrix, cameraRotation);
matrices_1.multiply(matrix, cameraScaling);
matrices_1.multiply(matrix, cameraCentering);
return matrix;
}
exports.matrixFromCamera = matrixFromCamera;
/**

@@ -94,7 +78,14 @@ * Function extracting the color at the given pixel.

function extractPixel(gl, x, y, array) {
var data = array || new Uint8Array(4);
gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, data);
return data;
}
var data = array || new Uint8Array(4);
gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, data);
return data;
}
exports.extractPixel = extractPixel;
/**
* Function used to know whether given webgl context can use 32 bits indices.
*/
function canUse32BitsIndices(gl) {
var webgl2 = typeof WebGL2RenderingContext !== "undefined" && gl instanceof WebGL2RenderingContext;
return webgl2 || !!gl.getExtension("OES_element_index_uint");
}
exports.canUse32BitsIndices = canUse32BitsIndices;
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.assign = assign;
/**

@@ -13,6 +8,17 @@ * Sigma.js Utils

*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.assign = exports.isPlainObject = void 0;
/**
* Very simple Object.assign-like function.
* Checks whether the given value is a plain object.
*
* @param {mixed} value - Target value.
* @return {boolean}
*/
function isPlainObject(value) {
return typeof value === "object" && value !== null && value.constructor === Object;
}
exports.isPlainObject = isPlainObject;
/**
* Very simple recursive Object.assign-like function.
*
* @param {object} target - First object.

@@ -23,17 +29,22 @@ * @param {object} [...objects] - Objects to merge.

function assign(target) {
target = target || {};
for (var _len = arguments.length, objects = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
objects[_key - 1] = arguments[_key];
}
for (var i = 0, l = objects.length; i < l; i++) {
if (!objects[i]) continue;
for (var k in objects[i]) {
target[k] = objects[i][k];
var objects = [];
for (var _i = 1; _i < arguments.length; _i++) {
objects[_i - 1] = arguments[_i];
}
}
return target;
}
target = target || {};
for (var i = 0, l = objects.length; i < l; i++) {
var o = objects[i];
if (!o)
continue;
for (var k in o) {
if (isPlainObject(o[k])) {
target[k] = assign(target[k], o[k]);
}
else {
target[k] = o[k];
}
}
}
return target;
}
exports.assign = assign;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc