Comparing version
307
camera.js
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,27 +6,30 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
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 _events = require('events'); | ||
var easings = _interopRequireWildcard(require("./easings")); | ||
var _easings = require('./easings'); | ||
var _utils = require("./utils"); | ||
var easings = _interopRequireWildcard(_easings); | ||
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)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } | ||
var _utils = require('./utils'); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
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 _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); } } | ||
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. | ||
*/ | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
/** | ||
@@ -39,4 +42,3 @@ * Defaults. | ||
}; | ||
// TODO: animate options = number polymorphism? | ||
var DEFAULT_ZOOMING_RATIO = 1.5; // TODO: animate options = number polymorphism? | ||
// TODO: pan, zoom, unzoom, reset, rotate, zoomTo | ||
@@ -53,26 +55,24 @@ // TODO: add width / height to camera and add #.resize | ||
var Camera = function (_EventEmitter) { | ||
var Camera = | ||
/*#__PURE__*/ | ||
function (_EventEmitter) { | ||
_inherits(Camera, _EventEmitter); | ||
function Camera(dimensions) { | ||
function Camera() { | ||
var _this; | ||
_classCallCheck(this, Camera); | ||
dimensions = dimensions || {}; | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(Camera).call(this)); // Properties | ||
// Properties | ||
var _this = _possibleConstructorReturn(this, (Camera.__proto__ || Object.getPrototypeOf(Camera)).call(this)); | ||
_this.x = 0; | ||
_this.y = 0; | ||
_this.x = 0.5; | ||
_this.y = 0.5; | ||
_this.angle = 0; | ||
_this.ratio = 1; | ||
_this.width = dimensions.width || 0; | ||
_this.height = dimensions.height || 0; | ||
_this.ratio = 1; // State | ||
// State | ||
_this.nextFrame = null; | ||
_this.previousState = _this.getState(); | ||
_this.enabled = true; | ||
return _this; | ||
} | ||
/** | ||
@@ -86,3 +86,3 @@ * Method used to enable the camera. | ||
_createClass(Camera, [{ | ||
key: 'enable', | ||
key: "enable", | ||
value: function enable() { | ||
@@ -92,3 +92,2 @@ this.enabled = true; | ||
} | ||
/** | ||
@@ -101,3 +100,3 @@ * Method used to disable the camera. | ||
}, { | ||
key: 'disable', | ||
key: "disable", | ||
value: function disable() { | ||
@@ -107,3 +106,2 @@ this.enabled = false; | ||
} | ||
/** | ||
@@ -116,3 +114,3 @@ * Method used to retrieve the camera's current state. | ||
}, { | ||
key: 'getState', | ||
key: "getState", | ||
value: function getState() { | ||
@@ -126,5 +124,4 @@ return { | ||
} | ||
/** | ||
* Method used to retrieve the camera's dimensions. | ||
* Method used to retrieve the camera's previous state. | ||
* | ||
@@ -135,10 +132,12 @@ * @return {object} | ||
}, { | ||
key: 'getDimensions', | ||
value: function getDimensions() { | ||
key: "getPreviousState", | ||
value: function getPreviousState() { | ||
var state = this.previousState; | ||
return { | ||
width: this.width, | ||
height: this.height | ||
x: state.x, | ||
y: state.y, | ||
angle: state.angle, | ||
ratio: state.ratio | ||
}; | ||
} | ||
/** | ||
@@ -151,78 +150,78 @@ * Method used to check whether the camera is currently being animated. | ||
}, { | ||
key: 'isAnimated', | ||
key: "isAnimated", | ||
value: function isAnimated() { | ||
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. | ||
*/ | ||
// TODO: assign to gain one object | ||
// TODO: angles | ||
}, { | ||
key: 'abstractDisplayToGraph', | ||
value: function abstractDisplayToGraph(x, y) { | ||
var cos = Math.cos(this.angle), | ||
sin = Math.sin(this.angle); | ||
key: "graphToViewport", | ||
value: function graphToViewport(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 * cos - y * sin) * this.ratio, | ||
y: (y * cos + x * sin) * this.ratio | ||
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. | ||
*/ | ||
// TODO: angles | ||
}, { | ||
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; | ||
key: "viewportToGraph", | ||
value: function viewportToGraph(dimensions, x, y) { | ||
var smallestDimension = Math.min(dimensions.width, dimensions.height); | ||
var dx = smallestDimension / dimensions.width, | ||
dy = smallestDimension / dimensions.height; | ||
return { | ||
x: (X * cos - Y * sin) * this.ratio, | ||
y: (Y * cos + X * sin) * this.ratio | ||
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. | ||
*/ | ||
// TODO: angle | ||
}, { | ||
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; | ||
key: "viewRectangle", | ||
value: function viewRectangle(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 { | ||
x: x * relCos + y * relSin + xOffset, | ||
y: y * relCos - x * relSin + yOffset | ||
x1: p1.x, | ||
y1: p1.y, | ||
x2: p2.x, | ||
y2: p2.y, | ||
height: p2.y - h.y | ||
}; | ||
} | ||
/** | ||
@@ -236,48 +235,19 @@ * Method used to set the camera's state. | ||
}, { | ||
key: 'setState', | ||
key: "setState", | ||
value: function setState(state) { | ||
if (!this.enabled) return this; | ||
// TODO: validations | ||
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? | ||
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. | ||
@@ -293,31 +263,25 @@ * | ||
}, { | ||
key: 'animate', | ||
value: function animate(state, options /*, callback */) { | ||
key: "animate", | ||
value: function animate(state, options, callback) { | ||
var _this2 = this; | ||
if (!this.enabled) return this; | ||
if (!this.enabled) return this; // TODO: validation | ||
// 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 | ||
var easing = typeof options.easing === 'function' ? options.easing : easings[options.easing]; | ||
if (this.nextFrame) cancelAnimationFrame(this.nextFrame); // State | ||
// Canceling previous animation if needed | ||
// if (this.nextFrame) | ||
// cancelAnimationFrame(this.nextFrame); | ||
// State | ||
var start = Date.now(), | ||
initialState = this.getState(); | ||
initialState = this.getState(); // Function performing the animation | ||
// Function performing the animation | ||
var fn = function fn() { | ||
var t = (Date.now() - start) / options.duration; | ||
var t = (Date.now() - start) / options.duration; // The animation is over: | ||
// The animation is over: | ||
if (t >= 1) { | ||
_this2.nextFrame = null; | ||
_this2.setState(state); | ||
if (typeof callback === 'function') callback(); | ||
return; | ||
@@ -327,5 +291,3 @@ } | ||
var coefficient = easing(t); | ||
var newState = {}; | ||
if ('x' in state) newState.x = initialState.x + (state.x - initialState.x) * coefficient; | ||
@@ -348,2 +310,63 @@ if ('y' in state) newState.y = initialState.y + (state.y - initialState.y) * coefficient; | ||
} | ||
/** | ||
* Method used to zoom the camera. | ||
* | ||
* @param {number|object} factorOrOptions - Factor or options. | ||
* @return {function} | ||
*/ | ||
}, { | ||
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); | ||
} | ||
} | ||
/** | ||
* Method used to unzoom the camera. | ||
* | ||
* @param {number|object} factorOrOptions - Factor or options. | ||
* @return {function} | ||
*/ | ||
}, { | ||
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); | ||
} | ||
} | ||
/** | ||
* Method used to reset the camera. | ||
* | ||
* @param {object} options - Options. | ||
* @return {function} | ||
*/ | ||
}, { | ||
key: "animatedReset", | ||
value: function animatedReset(options) { | ||
return this.animate({ | ||
x: 0.5, | ||
y: 0.5, | ||
ratio: 1, | ||
angle: 0 | ||
}, options); | ||
} | ||
}]); | ||
@@ -350,0 +373,0 @@ |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,25 +6,31 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
var _events = require('events'); | ||
var _events = require("events"); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(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 _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(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. | ||
*/ | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
var Captor = function (_EventEmitter) { | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
var Captor = | ||
/*#__PURE__*/ | ||
function (_EventEmitter) { | ||
_inherits(Captor, _EventEmitter); | ||
function Captor(container, camera) { | ||
var _this; | ||
_classCallCheck(this, Captor); | ||
// Properties | ||
var _this = _possibleConstructorReturn(this, (Captor.__proto__ || Object.getPrototypeOf(Captor)).call(this)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(Captor).call(this)); // Properties | ||
@@ -31,0 +37,0 @@ _this.container = container; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,25 +6,30 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
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 _camera = _interopRequireDefault(require("../camera")); | ||
var _captor = require('../captor'); | ||
var _captor = _interopRequireDefault(require("../captor")); | ||
var _captor2 = _interopRequireDefault(_captor); | ||
var _utils = require("./utils"); | ||
var _utils = require('./utils'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(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 _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); } } | ||
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. | ||
*/ | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
/** | ||
@@ -41,3 +46,2 @@ * Constants. | ||
DOUBLE_CLICK_ZOOMING_DURATION = 200; | ||
/** | ||
@@ -49,22 +53,24 @@ * Mouse captor class. | ||
var MouseCaptor = function (_Captor) { | ||
var MouseCaptor = | ||
/*#__PURE__*/ | ||
function (_Captor) { | ||
_inherits(MouseCaptor, _Captor); | ||
function MouseCaptor(container, camera) { | ||
var _this; | ||
_classCallCheck(this, MouseCaptor); | ||
// Properties | ||
var _this = _possibleConstructorReturn(this, (MouseCaptor.__proto__ || Object.getPrototypeOf(MouseCaptor)).call(this, container, camera)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(MouseCaptor).call(this, container, camera)); // Properties | ||
_this.container = container; | ||
_this.camera = camera; | ||
_this.camera = camera; // State | ||
// State | ||
_this.enabled = true; | ||
_this.hasDragged = false; | ||
_this.downStartTime = null; | ||
_this.startMouseX = null; | ||
_this.startMouseY = null; | ||
_this.lastMouseX = null; | ||
_this.lastMouseY = null; | ||
_this.isMouseDown = false; | ||
_this.isMoving = true; | ||
_this.isMoving = false; | ||
_this.movingTimeout = null; | ||
@@ -75,12 +81,11 @@ _this.startCameraState = null; | ||
_this.doubleClickTimeout = null; | ||
_this.wheelLock = false; // Binding methods | ||
// 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); | ||
_this.handleClick = _this.handleClick.bind(_assertThisInitialized(_assertThisInitialized(_this))); | ||
_this.handleDown = _this.handleDown.bind(_assertThisInitialized(_assertThisInitialized(_this))); | ||
_this.handleUp = _this.handleUp.bind(_assertThisInitialized(_assertThisInitialized(_this))); | ||
_this.handleMove = _this.handleMove.bind(_assertThisInitialized(_assertThisInitialized(_this))); | ||
_this.handleWheel = _this.handleWheel.bind(_assertThisInitialized(_assertThisInitialized(_this))); | ||
_this.handleOut = _this.handleOut.bind(_assertThisInitialized(_assertThisInitialized(_this))); // Binding events | ||
// Binding events | ||
container.addEventListener('click', _this.handleClick, false); | ||
@@ -92,3 +97,2 @@ container.addEventListener('mousedown', _this.handleDown, false); | ||
container.addEventListener('mouseout', _this.handleOut, false); | ||
document.addEventListener('mouseup', _this.handleUp, false); | ||
@@ -99,3 +103,15 @@ return _this; | ||
_createClass(MouseCaptor, [{ | ||
key: 'handleClick', | ||
key: "kill", | ||
value: function kill() { | ||
var container = this.container; | ||
container.removeEventListener('click', this.handleClick); | ||
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); | ||
} | ||
}, { | ||
key: "handleClick", | ||
value: function handleClick(e) { | ||
@@ -105,3 +121,2 @@ var _this2 = this; | ||
if (!this.enabled) return; | ||
this.clicks++; | ||
@@ -111,6 +126,4 @@ | ||
this.clicks = 0; | ||
clearTimeout(this.doubleClickTimeout); | ||
this.doubleClickTimeout = null; | ||
return this.handleDoubleClick(e); | ||
@@ -122,23 +135,36 @@ } | ||
_this2.doubleClickTimeout = null; | ||
}, DOUBLE_CLICK_TIMEOUT); | ||
}, DOUBLE_CLICK_TIMEOUT); // NOTE: this is here to prevent click events on drag | ||
this.emit('click', (0, _utils.getMouseCoords)(e)); | ||
if (!this.hasDragged) this.emit('click', (0, _utils.getMouseCoords)(e)); | ||
} | ||
}, { | ||
key: 'handleDoubleClick', | ||
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 newRatio = cameraState.ratio / DOUBLE_CLICK_ZOOMING_RATIO; // TODO: factorize | ||
var position = this.camera.abstractDisplayToGraph((0, _utils.getX)(e) - center.x, (0, _utils.getY)(e) - center.y); | ||
var dimensions = { | ||
width: this.container.offsetWidth, | ||
height: this.container.offsetHeight | ||
}; | ||
var clickX = (0, _utils.getX)(e), | ||
clickY = (0, _utils.getY)(e); // TODO: baaaad we mustn't mutate the camera, create a Camera.from or #.copy | ||
// TODO: factorize pan & zoomTo | ||
var cameraWithNewRatio = new _camera.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: position.x * (1 - ratio) + cameraState.x, | ||
y: position.y * (1 - ratio) + cameraState.y, | ||
ratio: ratio * cameraState.ratio | ||
x: cameraState.x - deltaX, | ||
y: cameraState.y - deltaY, | ||
ratio: newRatio | ||
}, { | ||
@@ -148,28 +174,19 @@ easing: 'quadraticInOut', | ||
}); | ||
if (e.preventDefault) e.preventDefault();else e.returnValue = false; | ||
e.stopPropagation(); | ||
return false; | ||
} | ||
}, { | ||
key: 'handleDown', | ||
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.lastMouseX = (0, _utils.getX)(e); | ||
this.lastMouseY = (0, _utils.getY)(e); | ||
this.hasDragged = false; | ||
this.downStartTime = Date.now(); // TODO: dispatch events | ||
this.downStartTime = Date.now(); | ||
// TODO: dispatch events | ||
switch (e.which) { | ||
default: | ||
// Left button pressed | ||
@@ -181,6 +198,7 @@ this.isMouseDown = true; | ||
}, { | ||
key: 'handleUp', | ||
key: "handleUp", | ||
value: function handleUp(e) { | ||
var _this3 = this; | ||
if (!this.enabled || !this.isMouseDown) return; | ||
this.isMouseDown = false; | ||
@@ -195,9 +213,9 @@ | ||
y = (0, _utils.getY)(e); | ||
var cameraState = this.camera.getState(), | ||
previousCameraState = this.camera.getPreviousState(); | ||
var cameraState = this.camera.getState(); | ||
if (this.isMoving) { | ||
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 + MOUSE_INERTIA_RATIO * (cameraState.x - previousCameraState.x), | ||
y: cameraState.y + MOUSE_INERTIA_RATIO * (cameraState.y - previousCameraState.y) | ||
}, { | ||
@@ -207,3 +225,3 @@ duration: MOUSE_INERTIA_DURATION, | ||
}); | ||
} else if (this.startMouseX !== x || this.startMouseY !== y) { | ||
} else if (this.lastMouseX !== x || this.lastMouseY !== y) { | ||
this.camera.setState({ | ||
@@ -215,87 +233,100 @@ x: cameraState.x, | ||
this.isMoving = false; | ||
setImmediate(function () { | ||
return _this3.hasDragged = false; | ||
}); | ||
this.emit('mouseup', (0, _utils.getMouseCoords)(e)); | ||
this.isMoving = false; | ||
} | ||
}, { | ||
key: 'handleMove', | ||
key: "handleMove", | ||
value: function handleMove(e) { | ||
var _this3 = this; | ||
var _this4 = this; | ||
if (!this.enabled) return; | ||
this.emit('mousemove', (0, _utils.getMouseCoords)(e)); | ||
if (this.isMouseDown) { | ||
// 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; | ||
_this4.movingTimeout = null; | ||
_this4.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; | ||
var dimensions = { | ||
width: this.container.offsetWidth, | ||
height: this.container.offsetHeight | ||
}; | ||
var eX = (0, _utils.getX)(e), | ||
eY = (0, _utils.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(); | ||
if (cameraState.x !== x || cameraState.y !== y) { | ||
this.lastCameraState = cameraState; | ||
this.camera.setState({ | ||
x: x, | ||
y: y | ||
}); | ||
} | ||
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; | ||
} | ||
}, { | ||
key: 'handleWheel', | ||
key: "handleWheel", | ||
value: function handleWheel(e) { | ||
if (!this.enabled) return; | ||
var _this5 = this; | ||
if (e.preventDefault) e.preventDefault();else e.returnValue = false; | ||
e.stopPropagation(); | ||
if (!this.enabled) return false; | ||
var delta = (0, _utils.getWheelDelta)(e); | ||
if (!delta) return false; | ||
if (this.wheelLock) return false; | ||
this.wheelLock = true; // TODO: handle max zoom | ||
if (!delta) return; | ||
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 dimensions = { | ||
width: this.container.offsetWidth, | ||
height: this.container.offsetHeight | ||
}; | ||
var clickX = (0, _utils.getX)(e), | ||
clickY = (0, _utils.getY)(e); // TODO: baaaad we mustn't mutate the camera, create a Camera.from or #.copy | ||
// TODO: factorize pan & zoomTo | ||
var cameraState = this.camera.getState(); | ||
var position = this.camera.abstractDisplayToGraph((0, _utils.getX)(e) - center.x, (0, _utils.getY)(e) - center.y); | ||
var cameraWithNewRatio = new _camera.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: position.x * (1 - ratio) + cameraState.x, | ||
y: position.y * (1 - ratio) + cameraState.y, | ||
ratio: ratio * cameraState.ratio | ||
x: cameraState.x - deltaX, | ||
y: cameraState.y - deltaY, | ||
ratio: newRatio | ||
}, { | ||
easing: 'quadraticOut', | ||
easing: 'linear', | ||
duration: MOUSE_ZOOM_DURATION | ||
}, function () { | ||
return _this5.wheelLock = false; | ||
}); | ||
if (e.preventDefault) e.preventDefault();else e.returnValue = false; | ||
e.stopPropagation(); | ||
return false; | ||
} | ||
}, { | ||
key: 'handleOut', | ||
value: function handleOut() { | ||
// TODO: dispatch event | ||
key: "handleOut", | ||
value: function handleOut() {// TODO: dispatch event | ||
} | ||
@@ -305,4 +336,4 @@ }]); | ||
return MouseCaptor; | ||
}(_captor2.default); | ||
}(_captor.default); | ||
exports.default = MouseCaptor; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,11 +6,2 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
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; | ||
@@ -24,5 +15,12 @@ exports.getY = getY; | ||
var _utils = require('../renderers/utils'); | ||
var _utils = require("../renderers/utils"); | ||
/** | ||
* Sigma.js Captor Utils | ||
* ====================== | ||
* | ||
* Miscellenous helper functions related to the captors. | ||
*/ | ||
/** | ||
* Extract the local X position from a mouse or touch event. | ||
@@ -35,10 +33,6 @@ * | ||
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.'); | ||
} | ||
/** | ||
@@ -50,12 +44,10 @@ * 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.'); | ||
} | ||
/** | ||
@@ -67,12 +59,10 @@ * 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.'); | ||
} | ||
/** | ||
@@ -84,12 +74,10 @@ * 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.'); | ||
} | ||
/** | ||
@@ -101,5 +89,6 @@ * 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 { | ||
@@ -110,3 +99,2 @@ x: getWidth(e) / (2 * ratio), | ||
} | ||
/** | ||
@@ -121,14 +109,8 @@ * Convert mouse coords to sigma coords. | ||
*/ | ||
function getMouseCoords(e, x, y) { | ||
if (arguments.length < 2) { | ||
x = getX(e); | ||
y = getY(e); | ||
} | ||
var center = getCenter(e); | ||
// TODO: is this really needed to have this strange {x,y} with now? | ||
function getMouseCoords(e) { | ||
return { | ||
x: x - center.x, | ||
y: y - center.y, | ||
x: getX(e), | ||
y: getY(e), | ||
clientX: e.clientX, | ||
@@ -142,3 +124,2 @@ clientY: e.clientY, | ||
} | ||
/** | ||
@@ -150,8 +131,8 @@ * 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; | ||
function getWheelDelta(e) { | ||
if (typeof e.wheelDelta !== 'undefined') return e.wheelDelta / 360; | ||
if (typeof e.detail !== 'undefined') return e.detail / -9; | ||
throw new Error('sigma/captors/utils.getDelta: could not extract delta from event.'); | ||
} |
@@ -6,2 +6,4 @@ "use strict"; | ||
}); | ||
exports.cubicInOut = exports.cubicOut = exports.cubicIn = exports.quadraticInOut = exports.quadraticOut = exports.quadraticIn = exports.linear = void 0; | ||
/** | ||
@@ -13,15 +15,21 @@ * Sigma.js Easings | ||
*/ | ||
var linear = exports.linear = function linear(k) { | ||
var linear = function linear(k) { | ||
return k; | ||
}; | ||
var quadraticIn = exports.quadraticIn = function quadraticIn(k) { | ||
exports.linear = linear; | ||
var quadraticIn = function quadraticIn(k) { | ||
return k * k; | ||
}; | ||
var quadraticOut = exports.quadraticOut = function quadraticOut(k) { | ||
exports.quadraticIn = quadraticIn; | ||
var quadraticOut = function quadraticOut(k) { | ||
return k * (2 - k); | ||
}; | ||
var quadraticInOut = exports.quadraticInOut = function quadraticInOut(k) { | ||
exports.quadraticOut = quadraticOut; | ||
var quadraticInOut = function quadraticInOut(k) { | ||
if ((k *= 2) < 1) return 0.5 * k * k; | ||
@@ -31,13 +39,21 @@ return -0.5 * (--k * (k - 2) - 1); | ||
var cubicIn = exports.cubicIn = function cubicIn(k) { | ||
exports.quadraticInOut = quadraticInOut; | ||
var cubicIn = function cubicIn(k) { | ||
return k * k * k; | ||
}; | ||
var cubicOut = exports.cubicOut = function cubicOut(k) { | ||
exports.cubicIn = cubicIn; | ||
var cubicOut = function cubicOut(k) { | ||
return --k * k * k + 1; | ||
}; | ||
var cubicInOut = exports.cubicInOut = function cubicInOut(k) { | ||
exports.cubicOut = cubicOut; | ||
var cubicInOut = function cubicInOut(k) { | ||
if ((k *= 2) < 1) return 0.5 * k * k * k; | ||
return 0.5 * ((k -= 2) * k * k + 2); | ||
}; | ||
}; | ||
exports.cubicInOut = cubicInOut; |
@@ -1,46 +0,47 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _sigma = require('./sigma'); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
Object.defineProperty(exports, "Renderer", { | ||
enumerable: true, | ||
get: function get() { | ||
return _renderer.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "Camera", { | ||
enumerable: true, | ||
get: function get() { | ||
return _camera.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "QuadTree", { | ||
enumerable: true, | ||
get: function get() { | ||
return _quadtree.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "MouseCaptor", { | ||
enumerable: true, | ||
get: function get() { | ||
return _mouse.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "WebGLRenderer", { | ||
enumerable: true, | ||
get: function get() { | ||
return _webgl.default; | ||
} | ||
}); | ||
var _sigma2 = _interopRequireDefault(_sigma); | ||
var _renderer = _interopRequireDefault(require("./renderer")); | ||
var _renderer = require('./renderer'); | ||
var _camera = _interopRequireDefault(require("./camera")); | ||
var _renderer2 = _interopRequireDefault(_renderer); | ||
var _quadtree = _interopRequireDefault(require("./quadtree")); | ||
var _camera = require('./camera'); | ||
var _mouse = _interopRequireDefault(require("./captors/mouse")); | ||
var _camera2 = _interopRequireDefault(_camera); | ||
var _webgl = _interopRequireDefault(require("./renderers/webgl")); | ||
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 }; } | ||
/** | ||
* Sigma.js Library Endpoint | ||
* ========================== | ||
* | ||
* The 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; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
{ | ||
"name": "sigma", | ||
"version": "2.0.0-alpha2", | ||
"version": "2.0.0-alpha20", | ||
"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", | ||
"scripts": { | ||
@@ -16,6 +16,6 @@ "build": "webpack --colors --progress && webpack --colors --progress -p", | ||
"prepublish": "npm run test && npm run dist && npm run build", | ||
"test": "mocha --compilers js:babel-core/register ./test/endpoint.js" | ||
"test": "mocha --require @babel/register ./test/endpoint.js" | ||
}, | ||
"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" | ||
}, | ||
@@ -37,23 +37,37 @@ "repository": { | ||
"license": "MIT", | ||
"dependencies": { | ||
"@yomguithereal/helpers": "^1.0.0", | ||
"events": "^3.0.0", | ||
"graphology-metrics": "1.6.0", | ||
"graphology-utils": "^1.4.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.1.2", | ||
"@babel/core": "7.1.2", | ||
"@babel/preset-env": "7.1.0", | ||
"@babel/register": "7.0.0", | ||
"@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-eslint": "10.0.1", | ||
"babel-loader": "8.0.4", | ||
"chroma-js": "^1.4.0", | ||
"d3-scale": "^2.1.2", | ||
"eslint": "^4.19.1", | ||
"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.0.1", | ||
"html-webpack-plugin": "^2.22.0", | ||
"mocha": "^3.0.2", | ||
"glob": "^7.1.3", | ||
"graphology": "^0.13.1", | ||
"graphology-communities-louvain": "^0.1.1", | ||
"graphology-components": "^0.1.0", | ||
"graphology-generators": "^0.10.1", | ||
"graphology-gexf": "^0.5.0", | ||
"graphology-layout": "0.1.0", | ||
"graphology-layout-forceatlas2": "^0.2.1", | ||
"graphology-library": "^0.1.1", | ||
"html-webpack-plugin": "^3.2.0", | ||
"mocha": "^5.0.5", | ||
"raw-loader": "^0.5.1", | ||
"rimraf": "^2.6.1", | ||
"webpack": "^2.5.1", | ||
"webpack-dev-server": "^2.4.5", | ||
"worker-loader": "^0.8.0" | ||
"simple-statistics": "^6.1.1", | ||
"webpack": "^4.20.2", | ||
"webpack-cli": "^3.1.2", | ||
"webpack-dev-server": "^3.1.9" | ||
}, | ||
@@ -70,13 +84,8 @@ "keywords": [ | ||
"presets": [ | ||
"es2015" | ||
"@babel/env" | ||
] | ||
}, | ||
"eslintConfig": { | ||
"extends": "@yomguithereal/eslint-config/es6" | ||
}, | ||
"dependencies": { | ||
"events": "^1.1.1", | ||
"gl-matrix": "^2.3.2", | ||
"graphology-utils": "^1.1.1" | ||
"extends": "@yomguithereal/eslint-config/es7" | ||
} | ||
} |
210
quadtree.js
@@ -6,28 +6,25 @@ "use strict"; | ||
}); | ||
exports.default = void 0; | ||
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 _extend = _interopRequireDefault(require("@yomguithereal/helpers/extend")); | ||
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"); } } | ||
/* eslint no-nested-ternary: 0 */ | ||
/** | ||
* Sigma.js Quad Tree Class | ||
* ========================= | ||
* | ||
* Class implementing the quad tree data structure used to solve hovers and | ||
* determine which elements are currently in the scope of the camera so that | ||
* we don't waste time rendering things the user cannot see anyway. | ||
*/ | ||
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); } } | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
// 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 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 | ||
// 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) | ||
/** | ||
@@ -45,3 +42,2 @@ * Constants. | ||
MAX_LEVEL = 5; | ||
var X_OFFSET = 0, | ||
@@ -51,3 +47,2 @@ Y_OFFSET = 1, | ||
HEIGHT_OFFSET = 3; | ||
var TOP_LEFT = 1, | ||
@@ -57,3 +52,2 @@ TOP_RIGHT = 2, | ||
BOTTOM_RIGHT = 4; | ||
/** | ||
@@ -72,2 +66,3 @@ * Geometry helpers. | ||
*/ | ||
function isAxisAligned(x1, y1, x2, y2) { | ||
@@ -77,6 +72,10 @@ return x1 === x2 || y1 === y2; | ||
function rectangleCollidesWithQuad(x1, y1, w, qx, qy, qw, qh) { | ||
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) { | ||
@@ -87,6 +86,4 @@ var xmp = qx + qw / 2, | ||
left = x < xmp; | ||
return top ? left ? TOP_LEFT : TOP_RIGHT : left ? BOTTOM_LEFT : BOTTOM_RIGHT; | ||
} | ||
/** | ||
@@ -96,4 +93,5 @@ * Helper functions that are not bound to the class so an external user | ||
*/ | ||
function buildQuadrants(maxLevel, data) { | ||
// [block, level] | ||
@@ -105,3 +103,2 @@ var stack = [0, 0]; | ||
block = stack.pop(); | ||
var topLeftBlock = 4 * block + BLOCKS, | ||
@@ -111,3 +108,2 @@ topRightBlock = 4 * block + 2 * BLOCKS, | ||
bottomRightBlock = 4 * block + 4 * BLOCKS; | ||
var x = data[block + X_OFFSET], | ||
@@ -119,3 +115,2 @@ y = data[block + Y_OFFSET], | ||
hh = height / 2; | ||
data[topLeftBlock + X_OFFSET] = x; | ||
@@ -125,3 +120,2 @@ data[topLeftBlock + Y_OFFSET] = y; | ||
data[topLeftBlock + HEIGHT_OFFSET] = hh; | ||
data[topRightBlock + X_OFFSET] = x + hw; | ||
@@ -131,3 +125,2 @@ data[topRightBlock + Y_OFFSET] = y; | ||
data[topRightBlock + HEIGHT_OFFSET] = hh; | ||
data[bottomLeftBlock + X_OFFSET] = x; | ||
@@ -137,3 +130,2 @@ data[bottomLeftBlock + Y_OFFSET] = y + hh; | ||
data[bottomLeftBlock + HEIGHT_OFFSET] = hh; | ||
data[bottomRightBlock + X_OFFSET] = x + hw; | ||
@@ -157,12 +149,6 @@ data[bottomRightBlock + Y_OFFSET] = y + hh; | ||
w = size * 2; | ||
var level = 0, | ||
block = 0; | ||
// [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(); | ||
while (true) { | ||
// If we reached max level | ||
@@ -179,22 +165,40 @@ if (level >= maxLevel) { | ||
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; // If we don't have at least a collision, there is an issue | ||
var collidingWithTopLeft = rectangleCollidesWithQuad(x1, y1, w, data[topLeftBlock + X_OFFSET], data[topLeftBlock + Y_OFFSET], data[topLeftBlock + WIDTH_OFFSET], data[topLeftBlock + HEIGHT_OFFSET]); | ||
if (collisions === 0) throw new Error("sigma/quadtree.insertNode: no collision (level: ".concat(level, ", key: ").concat(key, ", x: ").concat(x, ", y: ").concat(y, ", size: ").concat(size, ").")); // If we have 3 collisions, we have a geometry problem obviously | ||
var collidingWithTopRight = rectangleCollidesWithQuad(x1, y1, w, data[topRightBlock + X_OFFSET], data[topRightBlock + Y_OFFSET], data[topRightBlock + WIDTH_OFFSET], data[topRightBlock + HEIGHT_OFFSET]); | ||
if (collisions === 3) throw new Error("sigma/quadtree.insertNode: 3 impossible collisions (level: ".concat(level, ", key: ").concat(key, ", x: ").concat(x, ", y: ").concat(y, ", size: ").concat(size, ").")); // If we have more that one collision, we stop here and store the node | ||
// in the relevant containers | ||
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) { | ||
// 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] || []; | ||
@@ -205,15 +209,42 @@ containers[block].push(key); | ||
level++; | ||
} | ||
} // Else we recurse into the correct quads | ||
// Else we recurse into the correct quads | ||
if (collidingWithTopLeft) stack.push(topLeftBlock, level); | ||
if (collidingWithTopRight) stack.push(topRightBlock, level); | ||
if (collidingWithTopLeft) block = topLeftBlock; | ||
if (collidingWithTopRight) block = topRightBlock; | ||
if (collidingWithBottomLeft) block = bottomLeftBlock; | ||
if (collidingWithBottomRight) block = bottomRightBlock; | ||
} | ||
} | ||
if (collidingWithBottomLeft) stack.push(bottomLeftBlock, level); | ||
function getNodesInAxisAlignedRectangleArea(maxLevel, data, containers, x1, y1, w, h) { | ||
// [block, level] | ||
var stack = [0, 0]; | ||
var collectedNodes = []; | ||
var container; | ||
if (collidingWithBottomRight) stack.push(bottomRightBlock, level); | ||
while (stack.length) { | ||
var level = stack.pop(), | ||
block = stack.pop(); // Collecting nodes | ||
container = containers[block]; | ||
if (container) (0, _extend.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); | ||
} | ||
return collectedNodes; | ||
} | ||
/** | ||
@@ -223,16 +254,26 @@ * QuadTree class. | ||
* @constructor | ||
* @param {Graph} graph - A graph instance. | ||
* @param {object} boundaries - The graph boundaries. | ||
*/ | ||
var QuadTree = function () { | ||
function QuadTree(boundaries) { | ||
var QuadTree = | ||
/*#__PURE__*/ | ||
function () { | ||
function QuadTree(params) { | ||
_classCallCheck(this, QuadTree); | ||
// Allocating the underlying byte array | ||
params = params || {}; // 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); | ||
this.cache = null; | ||
this.lastRectangle = null; | ||
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; | ||
} | ||
@@ -244,3 +285,2 @@ | ||
insertNode(MAX_LEVEL, this.data, this.containers, key, x, y, size); | ||
return this; | ||
@@ -251,5 +291,4 @@ } | ||
value: function resize(boundaries) { | ||
this.clear(); | ||
this.clear(); // Building the quadrants | ||
// Building the quadrants | ||
this.data[X_OFFSET] = boundaries.x; | ||
@@ -259,3 +298,2 @@ this.data[Y_OFFSET] = boundaries.y; | ||
this.data[HEIGHT_OFFSET] = boundaries.height; | ||
buildQuadrants(MAX_LEVEL, this.data); | ||
@@ -267,3 +305,2 @@ } | ||
this.containers = {}; | ||
return this; | ||
@@ -275,3 +312,2 @@ } | ||
var nodes = []; | ||
var block = 0, | ||
@@ -282,5 +318,3 @@ level = 0; | ||
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; | ||
@@ -292,2 +326,24 @@ level++; | ||
} | ||
}, { | ||
key: "rectangle", | ||
value: function rectangle(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; | ||
} | ||
}]); | ||
@@ -294,0 +350,0 @@ |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,17 +6,20 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
var _events = require('events'); | ||
var _events = require("events"); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(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 _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(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. | ||
*/ | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
/** | ||
@@ -27,3 +30,5 @@ * Renderer class. | ||
*/ | ||
var Renderer = function (_EventEmitter) { | ||
var Renderer = | ||
/*#__PURE__*/ | ||
function (_EventEmitter) { | ||
_inherits(Renderer, _EventEmitter); | ||
@@ -34,3 +39,3 @@ | ||
return _possibleConstructorReturn(this, (Renderer.__proto__ || Object.getPrototypeOf(Renderer)).apply(this, arguments)); | ||
return _possibleConstructorReturn(this, _getPrototypeOf(Renderer).apply(this, arguments)); | ||
} | ||
@@ -37,0 +42,0 @@ |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -8,10 +8,6 @@ Object.defineProperty(exports, "__esModule", { | ||
var _node = require('./node'); | ||
var _node = _interopRequireDefault(require("./node")); | ||
var _node2 = _interopRequireDefault(_node); | ||
var _label = _interopRequireDefault(require("./label")); | ||
var _label = require('./label'); | ||
var _label2 = _interopRequireDefault(_label); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -26,7 +22,8 @@ | ||
*/ | ||
function drawHover(context, data) { | ||
function drawHover(context, data, settings) { | ||
var size = settings.labelSize, | ||
font = settings.labelFont, | ||
weight = settings.labelWeight; | ||
context.font = "".concat(weight, " ").concat(size, "px ").concat(font); // Then we draw the label background | ||
context.font = '14px arial'; | ||
// Then we draw the label background | ||
context.beginPath(); | ||
@@ -38,11 +35,8 @@ context.fillStyle = '#fff'; | ||
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); | ||
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); | ||
@@ -56,122 +50,11 @@ context.moveTo(x, y + e); | ||
context.lineTo(x, y + e); | ||
context.closePath(); | ||
context.fill(); | ||
context.shadowOffsetX = 0; | ||
context.shadowOffsetY = 0; | ||
context.shadowBlur = 0; | ||
context.shadowBlur = 0; // Then we need to draw the node | ||
// Then we need to draw the node | ||
(0, _node2.default)(context, data); | ||
(0, _node.default)(context, data); // And finally we draw the label | ||
// And finally we draw the label | ||
(0, _label2.default)(context, data); | ||
} | ||
// ;(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); | ||
(0, _label.default)(context, data, settings); | ||
} |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -7,2 +7,3 @@ Object.defineProperty(exports, "__esModule", { | ||
exports.default = drawLabel; | ||
/** | ||
@@ -14,7 +15,9 @@ * Sigma.js Canvas Renderer Label Component | ||
*/ | ||
function drawLabel(context, data) { | ||
function drawLabel(context, data, settings) { | ||
var size = settings.labelSize, | ||
font = settings.labelFont, | ||
weight = settings.labelWeight; | ||
context.fillStyle = '#000'; | ||
context.font = '14px arial'; | ||
context.fillText(data.label, data.x + data.size + 3, data.y + 14 / 3); | ||
context.font = "".concat(weight, " ").concat(size, "px ").concat(font); | ||
context.fillText(data.label, data.x + data.size + 3, data.y + size / 3); | ||
} |
@@ -7,2 +7,3 @@ "use strict"; | ||
exports.default = drawNode; | ||
/** | ||
@@ -17,9 +18,7 @@ * Sigma.js Canvas Renderer Node Component | ||
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(); | ||
} |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -8,3 +8,12 @@ Object.defineProperty(exports, "__esModule", { | ||
exports.getPixelRatio = getPixelRatio; | ||
exports.createNodeRescalingFunction = createNodeRescalingFunction; | ||
exports.createNormalizationFunction = createNormalizationFunction; | ||
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | ||
function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | ||
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||
/** | ||
@@ -26,3 +35,2 @@ * Sigma.js Rendering Utils | ||
var element = document.createElement(tag); | ||
if (!attributes) return element; | ||
@@ -42,3 +50,2 @@ | ||
} | ||
/** | ||
@@ -49,58 +56,42 @@ * 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; | ||
} | ||
/** | ||
* 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; | ||
function createNormalizationFunction(extent) { | ||
var _extent$x = _slicedToArray(extent.x, 2), | ||
minX = _extent$x[0], | ||
maxX = _extent$x[1], | ||
_extent$y = _slicedToArray(extent.y, 2), | ||
minY = _extent$y[0], | ||
maxY = _extent$y[1]; | ||
var fn; | ||
var ratio = Math.max(maxX - minX, maxY - minY); | ||
if (ratio === 0) ratio = 1; | ||
var dX = (maxX + minX) / 2, | ||
dY = (maxY + minY) / 2; | ||
var hx = (maxX + minX) / 2, | ||
hy = (maxY + minY) / 2; | ||
fn = function fn(data) { | ||
return { | ||
x: 0.5 + (data.x - dX) / ratio, | ||
y: 0.5 + (data.y - dY) / ratio | ||
}; | ||
}; // TODO: possibility to apply this in batch over array of indices | ||
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 | ||
}; | ||
fn.applyTo = function (data) { | ||
data.x = 0.5 + (data.x - dX) / ratio; | ||
data.y = 0.5 + (data.y - dY) / ratio; | ||
}; | ||
@@ -110,8 +101,9 @@ | ||
return { | ||
x: data.x / scale + hx, | ||
y: data.y / scale + hy | ||
x: dX + ratio * (data.x - 0.5), | ||
y: dY + ratio * (data.y - 0.5) | ||
}; | ||
}; | ||
fn.ratio = ratio; | ||
return fn; | ||
} |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,58 +6,55 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
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 _extent = require("graphology-metrics/extent"); | ||
var _glMatrix = require('gl-matrix'); | ||
var _isGraph = _interopRequireDefault(require("graphology-utils/is-graph")); | ||
var _renderer = require('../../renderer'); | ||
var _renderer = _interopRequireDefault(require("../../renderer")); | ||
var _renderer2 = _interopRequireDefault(_renderer); | ||
var _camera = _interopRequireDefault(require("../../camera")); | ||
var _camera = require('../../camera'); | ||
var _mouse = _interopRequireDefault(require("../../captors/mouse")); | ||
var _camera2 = _interopRequireDefault(_camera); | ||
var _quadtree = _interopRequireDefault(require("../../quadtree")); | ||
var _mouse = require('../../captors/mouse'); | ||
var _displayData2 = require("../display-data"); | ||
var _mouse2 = _interopRequireDefault(_mouse); | ||
var _node2 = _interopRequireDefault(require("./programs/node.fast")); | ||
var _quadtree = require('../../quadtree'); | ||
var _edge = _interopRequireDefault(require("./programs/edge")); | ||
var _quadtree2 = _interopRequireDefault(_quadtree); | ||
var _label = _interopRequireDefault(require("../canvas/components/label")); | ||
var _node = require('./programs/node'); | ||
var _hover = _interopRequireDefault(require("../canvas/components/hover")); | ||
var _node2 = _interopRequireDefault(_node); | ||
var _utils = require("../../utils"); | ||
var _edge = require('./programs/edge'); | ||
var _utils2 = require("../utils"); | ||
var _edge2 = _interopRequireDefault(_edge); | ||
var _utils3 = require("./utils"); | ||
var _label = require('../canvas/components/label'); | ||
var _labels = require("../../heuristics/labels"); | ||
var _label2 = _interopRequireDefault(_label); | ||
var _zIndex = require("../../heuristics/z-index"); | ||
var _hover = require('../canvas/components/hover'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _hover2 = _interopRequireDefault(_hover); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _utils = require('../../utils'); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _utils2 = require('../utils'); | ||
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); } } | ||
var _utils3 = require('./utils'); | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
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 _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
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. | ||
*/ | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
@@ -69,3 +66,23 @@ /** | ||
var WEBGL_OVERSAMPLING_RATIO = (0, _utils2.getPixelRatio)(); | ||
/** | ||
* Defaults. | ||
*/ | ||
var DEFAULT_SETTINGS = { | ||
// Performance | ||
hideEdgesOnMove: false, | ||
hideLabelsOnMove: false, | ||
renderLabels: true, | ||
// Component rendering | ||
defaultNodeColor: '#999', | ||
defaultEdgeColor: '#ccc', | ||
labelFont: 'Arial', | ||
labelSize: 14, | ||
labelWeight: 'normal', | ||
// Reducers | ||
nodeReducer: null, | ||
edgeReducer: null, | ||
// Features | ||
zIndex: false | ||
}; | ||
/** | ||
@@ -75,18 +92,25 @@ * 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) { | ||
var WebGLRenderer = | ||
/*#__PURE__*/ | ||
function (_Renderer) { | ||
_inherits(WebGLRenderer, _Renderer); | ||
function WebGLRenderer(container) { | ||
function WebGLRenderer(graph, container, settings) { | ||
var _this; | ||
_classCallCheck(this, WebGLRenderer); | ||
// Validating | ||
var _this = _possibleConstructorReturn(this, (WebGLRenderer.__proto__ || Object.getPrototypeOf(WebGLRenderer)).call(this)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(WebGLRenderer).call(this)); | ||
settings = settings || {}; | ||
_this.settings = (0, _utils.assign)({}, DEFAULT_SETTINGS, settings); // Validating | ||
if (!(container instanceof HTMLElement)) throw new Error('sigma/renderers/webgl: container should be an html element.'); | ||
if (!(0, _isGraph.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 | ||
// Properties | ||
_this.sigma = null; | ||
_this.graph = graph; | ||
_this.captors = {}; | ||
@@ -96,23 +120,22 @@ _this.container = container; | ||
_this.contexts = {}; | ||
_this.listeners = {}; | ||
_this.listeners = {}; // Indices & cache | ||
// TODO: this could be improved by key => index => floatArray | ||
// TODO: the cache should erase keys on node delete & add new | ||
_this.quadtree = new _quadtree2.default(); | ||
_this.nodeArray = null; | ||
_this.nodeIndicesArray = null; | ||
_this.nodeOrder = {}; | ||
_this.quadtree = new _quadtree.default(); | ||
_this.nodeDataCache = {}; | ||
_this.edgeArray = null; | ||
_this.edgeIndicesArray = null; | ||
_this.edgeOrder = {}; | ||
_this.edgeDataCache = {}; | ||
_this.nodeExtent = null; | ||
_this.edgeExtent = null; | ||
// TODO: if we drop size scaling => this should become "rescalingFunction" | ||
_this.nodeRescalingFunction = null; | ||
_this.initializeCache(); // Normalization function | ||
// Starting dimensions | ||
_this.normalizationFunction = null; // Starting dimensions | ||
_this.width = 0; | ||
_this.height = 0; | ||
_this.height = 0; // State | ||
// State | ||
_this.highlightedNodes = new Set(); | ||
_this.displayedLabels = new Set(); | ||
_this.hoveredNode = null; | ||
@@ -123,24 +146,22 @@ _this.wasRenderedInThisFrame = false; | ||
_this.needToProcess = false; | ||
_this.needToSoftProcess = false; | ||
_this.pixel = new Uint8Array(4); | ||
_this.needToSoftProcess = false; // Initializing contexts | ||
// Initializing contexts | ||
_this.createContext('edges'); | ||
_this.createContext('nodes'); | ||
_this.createContext('labels', false); | ||
_this.createContext('hovers', false); | ||
_this.createContext('mouse', false); | ||
// Blending | ||
_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); | ||
gl.enable(gl.BLEND); // Loading programs | ||
// Loading programs | ||
_this.nodePrograms = { | ||
@@ -150,27 +171,32 @@ def: new _node2.default(_this.contexts.nodes) | ||
_this.edgePrograms = { | ||
def: new _edge2.default(_this.contexts.edges) | ||
}; | ||
def: new _edge.default(_this.contexts.edges) | ||
}; // Initial resize | ||
// Initial resize | ||
_this.resize(); | ||
_this.resize(); // Initializing the camera | ||
// Initializing the camera | ||
_this.camera = new _camera2.default({ | ||
_this.camera = new _camera.default({ | ||
width: _this.width, | ||
height: _this.height | ||
}); | ||
}); // Binding camera events | ||
// Binding camera events | ||
_this.bindCameraHandlers(); | ||
_this.bindCameraHandlers(); // Initializing captors | ||
// Initializing captors | ||
_this.captors = { | ||
mouse: new _mouse2.default(_this.elements.mouse, _this.camera) | ||
}; | ||
mouse: new _mouse.default(_this.elements.mouse, _this.camera) | ||
}; // Binding event handlers | ||
// Binding event handlers | ||
_this.bindEventHandlers(); | ||
_this.bindEventHandlers(); // Binding graph handlers | ||
_this.bindGraphHandlers(); // Processing data for the first time & render | ||
_this.process(); | ||
_this.render(); | ||
return _this; | ||
} | ||
/**--------------------------------------------------------------------------- | ||
@@ -182,8 +208,8 @@ * Internal methods. | ||
/** | ||
* Method used to test a pixel of the given context. | ||
* Internal function used to create a canvas context and add the relevant | ||
* DOM elements. | ||
* | ||
* @param {WebGLContext} gl - Context. | ||
* @param {number} x - Client x. | ||
* @param {number} y - Client y. | ||
* @return {boolean} | ||
* @param {string} id - Context's id. | ||
* @param {boolean} webgl - Whether the context is a webgl or canvas one. | ||
* @return {WebGLRenderer} | ||
*/ | ||
@@ -193,25 +219,7 @@ | ||
_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; | ||
} | ||
/** | ||
* Internal function used to create a canvas context and add the relevant | ||
* DOM elements. | ||
* | ||
* @param {string} id - Context's id. | ||
* @param {boolean} webgl - Whether the context is a webgl or canvas one. | ||
* @return {WebGLRenderer} | ||
*/ | ||
}, { | ||
key: 'createContext', | ||
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, | ||
class: "sigma-".concat(id), | ||
style: { | ||
@@ -221,18 +229,46 @@ position: 'absolute' | ||
}); | ||
this.elements[id] = element; | ||
this.container.appendChild(element); | ||
var contextOptions = { | ||
preserveDrawingBuffer: true, | ||
preserveDrawingBuffer: false, | ||
antialias: false | ||
}; | ||
var context; | ||
var context = element.getContext(webgl ? 'webgl' : '2d', contextOptions); | ||
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); | ||
} else { | ||
context = element.getContext('2d', contextOptions); | ||
} | ||
this.contexts[id] = context; | ||
return this; | ||
} | ||
/** | ||
* Method used to initialize display data cache. | ||
* | ||
* @return {WebGLRenderer} | ||
*/ | ||
}, { | ||
key: "initializeCache", | ||
value: function initializeCache() { | ||
var graph = this.graph; | ||
var nodes = graph.nodes(); | ||
for (var i = 0, l = nodes.length; i < l; i++) { | ||
this.nodeDataCache[nodes[i]] = new _displayData2.NodeDisplayData(i, this.settings); | ||
} | ||
var edges = graph.edges(); | ||
for (var _i = 0, _l = edges.length; _i < _l; _i++) { | ||
this.edgeDataCache[edges[_i]] = new _displayData2.EdgeDisplayData(_i, this.settings); | ||
} | ||
} | ||
/** | ||
@@ -245,3 +281,3 @@ * Method binding camera handlers. | ||
}, { | ||
key: 'bindCameraHandlers', | ||
key: "bindCameraHandlers", | ||
value: function bindCameraHandlers() { | ||
@@ -255,6 +291,4 @@ var _this2 = this; | ||
this.camera.on('updated', this.listeners.camera); | ||
return this; | ||
} | ||
/** | ||
@@ -267,97 +301,102 @@ * Method binding event handlers. | ||
}, { | ||
key: 'bindEventHandlers', | ||
key: "bindEventHandlers", | ||
value: function bindEventHandlers() { | ||
var _this3 = this; | ||
// Function checking if the mouse is on the given node | ||
// 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 | ||
// Function returning the nodes in the mouse's quad | ||
var getQuadNodes = function getQuadNodes(mouseX, mouseY) { | ||
var mouseGraphPosition = _this3.camera.viewportToGraph(_this3, mouseX, mouseY); // TODO: minus 1? lol | ||
var mouseGraphPosition = _this3.camera.displayToGraph(mouseX, mouseY); | ||
return _this3.quadtree.point(mouseGraphPosition.x, mouseGraphPosition.y); | ||
}; | ||
return _this3.quadtree.point(mouseGraphPosition.x, 1 - mouseGraphPosition.y); | ||
}; // Handling mouse move | ||
// 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); // We will hover the node whose center is closest to mouse | ||
var quadNodes = getQuadNodes(e.clientX, e.clientY); | ||
var minDistance = Infinity, | ||
nodeToHover = null; | ||
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 pos = _this3.camera.graphToViewport(_this3, data.x, data.y); | ||
var size = data.size / sizeRatio; | ||
if (mouseIsOnNode(e.clientX, e.clientY, pos.x, pos.y, size)) { | ||
_this3.hoveredNode = node; | ||
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 | ||
_this3.emit('overNode', { node: node }); | ||
return _this3.scheduleHighlightedNodesRender(); | ||
if (distance < minDistance) { | ||
minDistance = distance; | ||
nodeToHover = node; | ||
} | ||
} | ||
} | ||
// Checking if the hovered node is still hovered | ||
if (nodeToHover && _this3.hoveredNode !== nodeToHover) { | ||
_this3.hoveredNode = nodeToHover; | ||
_this3.emit('enterNode', { | ||
node: nodeToHover | ||
}); | ||
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 _pos = _this3.camera.graphToViewport(_this3, _data.x, _data.y); | ||
var _size = _data.size / sizeRatio; | ||
if (!mouseIsOnNode(e.clientX, e.clientY, _pos.x, _pos.y, _size)) { | ||
if (!mouseIsOnNode(e.x, e.y, _pos.x, _pos.y, _size)) { | ||
var _node = _this3.hoveredNode; | ||
_this3.hoveredNode = null; | ||
_this3.emit('outNode', { node: _this3.hoveredNode }); | ||
_this3.emit('leaveNode', { | ||
node: _node | ||
}); | ||
return _this3.scheduleHighlightedNodesRender(); | ||
} | ||
} | ||
}; | ||
}; // Handling click | ||
// Handling down | ||
this.listeners.handleDown = function (e) { | ||
var sizeRatio = Math.pow(_this3.camera.getState().ratio, 0.5); | ||
var quadNodes = getQuadNodes(e.clientX, e.clientY); | ||
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.clientX, e.clientY, 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); | ||
var quadNodes = getQuadNodes(e.clientX, e.clientY); | ||
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 pos = _this3.camera.graphToViewport(_this3, data.x, data.y); | ||
var size = data.size / sizeRatio; | ||
if (mouseIsOnNode(e.clientX, e.clientY, pos.x, pos.y, size)) return _this3.emit('clickNode', { node: node }); | ||
if (mouseIsOnNode(e.x, e.y, pos.x, pos.y, size)) return _this3.emit('clickNode', { | ||
node: node | ||
}); | ||
} | ||
@@ -368,10 +407,6 @@ | ||
// 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; | ||
} | ||
/** | ||
@@ -384,10 +419,11 @@ * Method binding graph handlers | ||
}, { | ||
key: 'bindGraphHandlers', | ||
key: "bindGraphHandlers", | ||
value: function bindGraphHandlers() { | ||
var _this4 = this; | ||
var graph = this.sigma.getGraph(); | ||
var graph = this.graph; | ||
this.listeners.graphUpdate = function () { | ||
_this4.needToProcess = true; | ||
_this4.scheduleRender(); | ||
@@ -398,8 +434,9 @@ }; | ||
_this4.needToSoftProcess = true; | ||
_this4.scheduleRender(); | ||
}; | ||
// TODO: bind this on composed state events | ||
}; // 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); | ||
@@ -412,6 +449,4 @@ graph.on('nodeDropped', this.listeners.graphUpdate); | ||
graph.on('cleared', this.listeners.graphUpdate); | ||
return this; | ||
} | ||
/** | ||
@@ -424,91 +459,75 @@ * Method used to process the whole graph's data. | ||
}, { | ||
key: 'process', | ||
key: "process", | ||
value: function process() { | ||
var keepArrays = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; | ||
var graph = this.graph, | ||
settings = this.settings; // Clearing the quad | ||
this.quadtree.clear(); // Computing extents | ||
var graph = this.sigma.getGraph(); | ||
var nodeExtentProperties = ['x', 'y']; | ||
var extent = this.sigma.getGraphExtent(); | ||
if (this.settings.zIndex) { | ||
nodeExtentProperties.push('z'); | ||
this.edgeExtent = (0, _extent.edgeExtent)(graph, ['z']); | ||
} | ||
// Rescaling function | ||
this.nodeRescalingFunction = (0, _utils2.createNodeRescalingFunction)({ width: this.width, height: this.height }, extent); | ||
this.nodeExtent = (0, _extent.nodeExtent)(graph, nodeExtentProperties); // Rescaling function | ||
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 = {}; | ||
this.normalizationFunction = (0, _utils2.createNormalizationFunction)(this.nodeExtent); | ||
var nodeProgram = this.nodePrograms.def; | ||
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 (!keepArrays) { | ||
this.nodeArray = new Float32Array(_node2.default.POINTS * _node2.default.ATTRIBUTES * graph.order); | ||
if (this.settings.zIndex) nodes = (0, _zIndex.zIndexOrdering)(this.edgeExtent.z, function (node) { | ||
return graph.getNodeAttribute(node, 'z'); | ||
}, nodes); | ||
this.nodeOrder = {}; | ||
} | ||
var nodes = graph.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 | ||
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); | ||
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.def; | ||
if (!keepArrays) edgeProgram.allocate(graph.size); | ||
var edges = graph.edges(); // Handling edge z-index | ||
if (!keepArrays) { | ||
this.edgeArray = new Float32Array(_edge2.default.POINTS * _edge2.default.ATTRIBUTES * graph.size); | ||
if (this.settings.zIndex) edges = (0, _zIndex.zIndexOrdering)(this.edgeExtent.z, function (edge) { | ||
return graph.getEdgeAttribute(edge, 'z'); | ||
}, edges); | ||
this.edgeOrder = {}; | ||
} | ||
for (var _i2 = 0, _l2 = edges.length; _i2 < _l2; _i2++) { | ||
var edge = edges[_i2]; | ||
var edges = graph.edges(); | ||
var _data2 = graph.getEdgeAttributes(edge); | ||
for (var _i = 0, _l = edges.length; _i < _l; _i++) { | ||
var edge = edges[_i]; | ||
var _displayData = this.edgeDataCache[edge]; | ||
if (settings.edgeReducer) _data2 = settings.edgeReducer(edge, _data2); | ||
this.edgeOrder[edge] = _i; | ||
_displayData.assign(_data2); | ||
var _data2 = this.sigma.getEdgeData(edge), | ||
extremities = graph.extremities(edge), | ||
var extremities = graph.extremities(edge), | ||
sourceData = this.nodeDataCache[extremities[0]], | ||
targetData = this.nodeDataCache[extremities[1]]; | ||
edgeProgram.process(sourceData, targetData, _displayData, _i2); | ||
_displayData.index = _i2; | ||
} // Computing edge indices if necessary | ||
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); | ||
if (!keepArrays && typeof edgeProgram.computeIndices === 'function') edgeProgram.computeIndices(); | ||
edgeProgram.bufferData(); | ||
return this; | ||
} | ||
/** | ||
@@ -521,14 +540,9 @@ * Method used to process a single node. | ||
}, { | ||
key: 'processNode', | ||
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); | ||
var data = this.graph.getNodeAttributes(key); | ||
nodeProgram.process(data, this.nodeDataCache[key].index); | ||
return this; | ||
} | ||
/** | ||
@@ -541,19 +555,13 @@ * Method used to process a single edge. | ||
}, { | ||
key: 'processEdge', | ||
key: "processEdge", | ||
value: function processEdge(key) { | ||
var graph = this.sigma.getGraph(); | ||
var graph = this.graph; | ||
var edgeProgram = this.edgePrograms.def; | ||
var data = this.sigma.getEdgeData(key), | ||
var data = graph.getEdgeAttributes(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); | ||
sourceData = graph.getNodeAttributes(extremities[0]), | ||
targetData = graph.getNodeAttributes(extremities[1]); | ||
edgeProgram.process(sourceData, targetData, data, this.edgeDataCache[key].index); | ||
return this; | ||
} | ||
/**--------------------------------------------------------------------------- | ||
@@ -565,24 +573,2 @@ * 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,7 +580,6 @@ * | ||
}, { | ||
key: 'getCamera', | ||
key: "getCamera", | ||
value: function getCamera() { | ||
return this.camera; | ||
} | ||
/** | ||
@@ -607,7 +592,6 @@ * Method returning the mouse captor. | ||
}, { | ||
key: 'getMouseCaptor', | ||
key: "getMouseCaptor", | ||
value: function getMouseCaptor() { | ||
return this.captors.mouse; | ||
} | ||
/** | ||
@@ -622,3 +606,3 @@ * Method used to resize the renderer. | ||
}, { | ||
key: 'resize', | ||
key: "resize", | ||
value: function resize(width, height) { | ||
@@ -636,28 +620,27 @@ var previousWidth = this.width, | ||
// If nothing has changed, we can stop right here | ||
if (previousWidth === this.width && previousHeight === this.height) 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 | ||
// Sizing dom elements | ||
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 | ||
// Sizing contexts | ||
for (var _id in this.contexts) { | ||
var context = this.contexts[_id]; | ||
var context = this.contexts[_id]; // Canvas contexts | ||
// 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); | ||
} | ||
// WebGL contexts | ||
} // 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'); | ||
@@ -673,3 +656,2 @@ } | ||
} | ||
/** | ||
@@ -682,19 +664,15 @@ * Method used to clear the canvases. | ||
}, { | ||
key: 'clear', | ||
key: "clear", | ||
value: function clear() { | ||
var context = this.contexts.nodes; | ||
context.clear(context.COLOR_BUFFER_BIT); | ||
// NOTE: don't need to clear with preserveDrawingBuffer to false | ||
// let context = this.contexts.nodes; | ||
// context.clear(context.COLOR_BUFFER_BIT); | ||
// context = this.contexts.edges; | ||
// context.clear(context.COLOR_BUFFER_BIT); | ||
var context = this.contexts.labels; | ||
context.clearRect(0, 0, this.width, this.height); // context = this.contexts.hovers; | ||
// context.clearRect(0, 0, this.width, this.height); | ||
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; | ||
} | ||
/** | ||
@@ -707,5 +685,4 @@ * Method used to render. | ||
}, { | ||
key: 'render', | ||
key: "render", | ||
value: function render() { | ||
// If a render was scheduled, we cancel it | ||
@@ -717,27 +694,22 @@ if (this.renderFrame) { | ||
this.needToSoftProcess = false; | ||
} | ||
} // If we have no nodes we can stop right there | ||
// First we need to resize | ||
this.resize(); | ||
// Clearing the canvases | ||
this.clear(); | ||
if (!this.graph.order) return this; // TODO: improve this heuristic or move to the captor itself? | ||
// Then we need to extract a matrix from the camera | ||
var cameraState = this.camera.getState(), | ||
cameraMatrix = (0, _utils3.matrixFromCamera)(cameraState); | ||
var moving = this.camera.isAnimated() || this.captors.mouse.isMoving || this.captors.mouse.hasDragged || this.captors.mouse.wheelLock; // First we need to resize | ||
var translation = _glMatrix.mat3.fromTranslation(_glMatrix.mat3.create(), [this.width / 2, this.height / 2]); | ||
this.resize(); // Clearing the canvases | ||
_glMatrix.mat3.multiply(cameraMatrix, translation, cameraMatrix); | ||
this.clear(); // Then we need to extract a matrix from the camera | ||
var program = void 0, | ||
gl = void 0; | ||
var cameraState = this.camera.getState(), | ||
cameraMatrix = (0, _utils3.matrixFromCamera)(cameraState, { | ||
width: this.width, | ||
height: this.height | ||
}); | ||
var program; // Drawing nodes | ||
// 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, { | ||
program.render({ | ||
matrix: cameraMatrix, | ||
@@ -749,41 +721,59 @@ width: this.width, | ||
scalingRatio: WEBGL_OVERSAMPLING_RATIO | ||
}); | ||
}); // Drawing edges | ||
// Drawing edges | ||
gl = this.contexts.edges; | ||
program = this.edgePrograms.def; | ||
if (!this.settings.hideEdgesOnMove || !moving) { | ||
program = this.edgePrograms.def; | ||
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 | ||
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 | ||
if (this.settings.hideLabelsOnMove && moving) return this; // 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); | ||
} | ||
if (!this.settings.renderLabels) return this; // Selecting labels to draw | ||
var labelsToDisplay = (0, _labels.labelsToDisplayFromGrid)({ | ||
cache: this.nodeDataCache, | ||
camera: this.camera, | ||
displayedLabels: this.displayedLabels, | ||
visibleNodes: visibleNodes, | ||
dimensions: this, | ||
graph: this.graph | ||
}); // Drawing labels | ||
// TODO: POW RATIO is currently default 0.5 and harcoded | ||
var nodes = this.sigma.getGraph().nodes(), | ||
context = this.contexts.labels; | ||
var 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]]; | ||
for (var i = 0, l = labelsToDisplay.length; i < l; i++) { | ||
var data = this.nodeDataCache[labelsToDisplay[i]]; | ||
var _camera$graphToDispla = this.camera.graphToDisplay(data.x, data.y), | ||
x = _camera$graphToDispla.x, | ||
y = _camera$graphToDispla.y; | ||
var _this$camera$graphToV = this.camera.graphToViewport(this, data.x, data.y), | ||
x = _this$camera$graphToV.x, | ||
y = _this$camera$graphToV.y; // TODO: we can cache the labels we need to render until the camera's ratio changes | ||
// 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; | ||
var size = data.size / sizeRatio; | ||
// TODO: this is the label threshold hardcoded | ||
if (size < 8) continue; | ||
(0, _label2.default)(context, { | ||
(0, _label.default)(context, { | ||
label: data.label, | ||
@@ -793,11 +783,11 @@ size: size, | ||
y: y | ||
}); | ||
} | ||
}, this.settings); | ||
} // Caching visible nodes and displayed labels | ||
// Rendering highlighted nodes | ||
this.displayedLabels = new Set(labelsToDisplay); // Rendering highlighted nodes | ||
this.renderHighlightedNodes(); | ||
return this; | ||
} | ||
/** | ||
@@ -810,3 +800,3 @@ * Method used to render the highlighted nodes. | ||
}, { | ||
key: 'renderHighlightedNodes', | ||
key: "renderHighlightedNodes", | ||
value: function renderHighlightedNodes() { | ||
@@ -816,21 +806,16 @@ var _this5 = this; | ||
var camera = this.camera; | ||
var sizeRatio = Math.pow(camera.getState().ratio, 0.5); | ||
var context = this.contexts.hovers; // Clearing | ||
var context = this.contexts.hovers; | ||
context.clearRect(0, 0, this.width, this.height); // Rendering | ||
// 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 _camera$graphToViewpo = camera.graphToViewport(_this5, data.x, data.y), | ||
x = _camera$graphToViewpo.x, | ||
y = _camera$graphToViewpo.y; | ||
var size = data.size / sizeRatio; | ||
(0, _hover2.default)(context, { | ||
(0, _hover.default)(context, { | ||
label: data.label, | ||
@@ -841,10 +826,8 @@ color: data.color, | ||
y: y | ||
}); | ||
}, _this5.settings); | ||
}; | ||
if (this.hoveredNode) render(this.hoveredNode); | ||
this.highlightedNodes.forEach(render); | ||
} | ||
/** | ||
@@ -857,48 +840,20 @@ * Method used to schedule a render. | ||
}, { | ||
key: 'scheduleRender', | ||
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; | ||
if (this.renderFrame) return this; // Let's schedule a frame | ||
// Let's schedule a frame | ||
this.renderFrame = requestAnimationFrame(function () { | ||
// Do we need to process data? | ||
if (_this6.needToProcess || _this6.needToSoftProcess) _this6.process(_this6.needToSoftProcess); | ||
if (_this6.needToProcess || _this6.needToSoftProcess) _this6.process(_this6.needToSoftProcess); // Resetting state | ||
// Resetting state | ||
_this6.renderFrame = null; | ||
_this6.needToProcess = false; | ||
_this6.needToSoftProcess = false; | ||
_this6.needToSoftProcess = false; // Rendering | ||
// Rendering | ||
_this6.render(); | ||
}); | ||
} | ||
/** | ||
@@ -911,18 +866,27 @@ * Method used to schedule a hover render. | ||
}, { | ||
key: 'scheduleHighlightedNodesRender', | ||
key: "scheduleHighlightedNodesRender", | ||
value: function scheduleHighlightedNodesRender() { | ||
var _this7 = this; | ||
if (this.renderHighlightedNodesFrame) return this; | ||
if (this.renderHighlightedNodesFrame || this.renderFrame) return this; | ||
this.renderHighlightedNodesFrame = requestAnimationFrame(function () { | ||
// Resetting state | ||
_this7.renderHighlightedNodesFrame = null; | ||
_this7.renderHighlightedNodesFrame = null; // Rendering | ||
// Rendering | ||
_this7.renderHighlightedNodes(); | ||
}); | ||
} | ||
/** | ||
* Method used to manually refresh. | ||
* | ||
* @return {WebGLRenderer} | ||
*/ | ||
}, { | ||
key: "refresh", | ||
value: function refresh() { | ||
this.needToSoftProcess = true; | ||
this.scheduleRender(); | ||
return this; | ||
} | ||
/** | ||
@@ -936,15 +900,11 @@ * Method used to highlight a node. | ||
}, { | ||
key: 'highlightNode', | ||
key: "highlightNode", | ||
value: function highlightNode(key) { | ||
// TODO: check the existence of the node | ||
// TODO: coerce? | ||
this.highlightedNodes.add(key); | ||
this.highlightedNodes.add(key); // Rendering | ||
// Rendering | ||
this.scheduleHighlightedNodesRender(); | ||
return this; | ||
} | ||
/** | ||
@@ -958,19 +918,64 @@ * Method used to unhighlight a node. | ||
}, { | ||
key: 'unhighlightNode', | ||
key: "unhighlightNode", | ||
value: function unhighlightNode(key) { | ||
// TODO: check the existence of the node | ||
// TODO: coerce? | ||
this.highlightedNodes.delete(key); | ||
this.highlightedNodes.delete(key); // Rendering | ||
// Rendering | ||
this.scheduleHighlightedNodesRender(); | ||
return this; | ||
} | ||
/** | ||
* Method used to shut the container & release event listeners. | ||
* | ||
* @return {undefined} | ||
*/ | ||
}, { | ||
key: "kill", | ||
value: function kill() { | ||
var graph = this.graph; // 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.graphUpdate); | ||
graph.removeListener('nodeDropped', this.listeners.graphUpdate); | ||
graph.removeListener('nodeAttributesUpdated', this.listeners.softGraphUpdate); | ||
graph.removeListener('edgeAdded', this.listeners.graphUpdate); | ||
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.previousVisibleNodes = 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; | ||
}(_renderer2.default); | ||
}(_renderer.default); | ||
exports.default = WebGLRenderer; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,44 +6,63 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
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 = _interopRequireDefault(require("./program")); | ||
var _program = require('./program'); | ||
var _utils = require("../utils"); | ||
var _program2 = _interopRequireDefault(_program); | ||
var _edgeFastVert = _interopRequireDefault(require("../shaders/edge.fast.vert.glsl")); | ||
var _utils = require('../utils'); | ||
var _edgeFastFrag = _interopRequireDefault(require("../shaders/edge.fast.frag.glsl")); | ||
var _edgeFastVert = require('../shaders/edge.fast.vert.glsl'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _edgeFastVert2 = _interopRequireDefault(_edgeFastVert); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _edgeFastFrag = require('../shaders/edge.fast.frag.glsl'); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _edgeFastFrag2 = _interopRequireDefault(_edgeFastFrag); | ||
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); } } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _createClass(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"); } } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
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 _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return 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. | ||
*/ | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
var EdgeFastProgram = function (_Program) { | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
var POINTS = 2, | ||
ATTRIBUTES = 3; | ||
var EdgeFastProgram = | ||
/*#__PURE__*/ | ||
function (_Program) { | ||
_inherits(EdgeFastProgram, _Program); | ||
function EdgeFastProgram() { | ||
function EdgeFastProgram(gl) { | ||
var _this; | ||
_classCallCheck(this, EdgeFastProgram); | ||
var _this = _possibleConstructorReturn(this, (EdgeFastProgram.__proto__ || Object.getPrototypeOf(EdgeFastProgram)).call(this)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(EdgeFastProgram).call(this, gl, _edgeFastVert.default, _edgeFastFrag.default)); // Binding context | ||
_this.vertexShaderSource = _edgeFastVert2.default; | ||
_this.fragmentShaderSource = _edgeFastFrag2.default; | ||
_this.gl = gl; // Array data | ||
_this.array = null; // Initializing buffers | ||
_this.buffer = gl.createBuffer(); | ||
gl.bindBuffer(gl.ARRAY_BUFFER, _this.buffer); // 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; | ||
@@ -53,7 +72,13 @@ } | ||
_createClass(EdgeFastProgram, [{ | ||
key: 'process', | ||
value: function process(array, sourceData, targetData, data, i) { | ||
key: "allocate", | ||
value: function allocate(capacity) { | ||
this.array = new Float32Array(POINTS * ATTRIBUTES * capacity); | ||
} | ||
}, { | ||
key: "process", | ||
value: function process(sourceData, targetData, data, offset) { | ||
var array = this.array; | ||
if (sourceData.hidden || targetData.hidden || data.hidden) { | ||
for (var l = i + EdgeFastProgram.POINTS * EdgeFastProgram.ATTRIBUTES; i < l; i++) { | ||
for (var l = i + POINTS * ATTRIBUTES; i < l; i++) { | ||
array[i] = 0; | ||
@@ -63,4 +88,3 @@ } | ||
var thickness = data.size || 1, | ||
x1 = sourceData.x, | ||
var x1 = sourceData.x, | ||
y1 = sourceData.y, | ||
@@ -70,39 +94,30 @@ x2 = targetData.x, | ||
color = (0, _utils.floatColor)(data.color); | ||
var i = POINTS * ATTRIBUTES * offset; // First point | ||
array[i++] = x1; | ||
array[i++] = y1; | ||
array[i++] = color; | ||
array[i++] = color; // Second point | ||
array[i++] = x2; | ||
array[i++] = y2; | ||
array[i++] = color; | ||
array[i] = color; | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render(gl, array, params) { | ||
key: "bufferData", | ||
value: function bufferData() { | ||
var gl = this.gl; // Vertices data | ||
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render(params) { | ||
var gl = this.gl; | ||
var program = this.program; | ||
gl.useProgram(program); | ||
gl.useProgram(program); // Binding uniforms | ||
// 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'); | ||
gl.uniform2f(this.resolutionLocation, params.width, params.height); | ||
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix); // Drawing: | ||
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); | ||
gl.drawArrays(gl.LINES, 0, this.array.length / ATTRIBUTES); | ||
} | ||
@@ -112,8 +127,4 @@ }]); | ||
return EdgeFastProgram; | ||
}(_program2.default); | ||
}(_program.default); | ||
exports.default = EdgeFastProgram; | ||
EdgeFastProgram.POINTS = 2; | ||
EdgeFastProgram.ATTRIBUTES = 3; | ||
exports.default = EdgeFastProgram; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,59 +6,56 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
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 = _interopRequireDefault(require("./program")); | ||
var _program = require('./program'); | ||
var _utils = require("../utils"); | ||
var _program2 = _interopRequireDefault(_program); | ||
var _edgeVert = _interopRequireDefault(require("../shaders/edge.vert.glsl")); | ||
var _utils = require('../utils'); | ||
var _edgeFrag = _interopRequireDefault(require("../shaders/edge.frag.glsl")); | ||
var _edgeVert = require('../shaders/edge.vert.glsl'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _edgeVert2 = _interopRequireDefault(_edgeVert); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _edgeFrag = require('../shaders/edge.frag.glsl'); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _edgeFrag2 = _interopRequireDefault(_edgeFrag); | ||
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); } } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _createClass(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"); } } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
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 _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return 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). | ||
*/ | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
var EdgeProgram = function (_Program) { | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
var POINTS = 4, | ||
ATTRIBUTES = 6, | ||
STRIDE = POINTS * ATTRIBUTES; | ||
var EdgeProgram = | ||
/*#__PURE__*/ | ||
function (_Program) { | ||
_inherits(EdgeProgram, _Program); | ||
function EdgeProgram(gl) { | ||
var _this; | ||
_classCallCheck(this, EdgeProgram); | ||
// Initializing buffers | ||
var _this = _possibleConstructorReturn(this, (EdgeProgram.__proto__ || Object.getPrototypeOf(EdgeProgram)).call(this, gl, _edgeVert2.default, _edgeFrag2.default)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(EdgeProgram).call(this, gl, _edgeVert.default, _edgeFrag.default)); // Binding context | ||
_this.gl = gl; // Array data | ||
_this.array = null; | ||
_this.indicesArray = null; // Initializing buffers | ||
_this.buffer = gl.createBuffer(); | ||
gl.bindBuffer(gl.ARRAY_BUFFER, _this.buffer); | ||
_this.indicesBuffer = gl.createBuffer(); // Locations | ||
_this.indicesBuffer = gl.createBuffer(); | ||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _this.indicesBuffer); | ||
// Locations | ||
_this.positionLocation = gl.getAttribLocation(_this.program, 'a_position'); | ||
@@ -71,13 +68,15 @@ _this.normalLocation = gl.getAttribLocation(_this.program, 'a_normal'); | ||
_this.matrixLocation = gl.getUniformLocation(_this.program, 'u_matrix'); | ||
_this.scaleLocation = gl.getUniformLocation(_this.program, 'u_scale'); | ||
// Bindings | ||
gl.enableVertexAttribArray(_this.positionLocation); | ||
gl.enableVertexAttribArray(_this.normalLocation); | ||
gl.enableVertexAttribArray(_this.thicknessLocation); | ||
gl.enableVertexAttribArray(_this.colorLocation); | ||
_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 | ||
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); | ||
_this.canUse32BitsIndices = (0, _utils.canUse32BitsIndices)(gl); | ||
_this.IndicesArray = _this.canUse32BitsIndices ? Uint32Array : Uint16Array; | ||
_this.indicesType = _this.canUse32BitsIndices ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT; | ||
return _this; | ||
@@ -87,9 +86,31 @@ } | ||
_createClass(EdgeProgram, [{ | ||
key: 'process', | ||
value: function process(array, sourceData, targetData, data, i) { | ||
key: "bind", | ||
value: function bind() { | ||
var gl = this.gl; | ||
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer); | ||
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); | ||
} | ||
}, { | ||
key: "allocate", | ||
value: function allocate(capacity) { | ||
this.array = new Float32Array(POINTS * ATTRIBUTES * capacity); | ||
} | ||
}, { | ||
key: "process", | ||
value: function process(sourceData, targetData, data, offset) { | ||
if (sourceData.hidden || targetData.hidden || data.hidden) { | ||
for (var l = i + EdgeProgram.POINTS * EdgeProgram.ATTRIBUTES; i < l; i++) { | ||
array[i] = 0; | ||
for (var _i = offset * STRIDE, l = _i + STRIDE; _i < l; _i++) { | ||
this.array[_i] = 0; | ||
} | ||
return; | ||
} | ||
@@ -102,8 +123,6 @@ | ||
y2 = targetData.y, | ||
color = (0, _utils.floatColor)(data.color); | ||
color = (0, _utils.floatColor)(data.color); // Computing normals | ||
// Computing normals | ||
var dx = x2 - x1, | ||
dy = y2 - y1; | ||
var len = dx * dx + dy * dy, | ||
@@ -115,3 +134,2 @@ n1 = 0, | ||
len = 1 / Math.sqrt(len); | ||
n1 = -dy * len; | ||
@@ -121,3 +139,5 @@ n2 = dx * len; | ||
// First point | ||
var i = POINTS * ATTRIBUTES * offset; | ||
var array = this.array; // First point | ||
array[i++] = x1; | ||
@@ -128,5 +148,4 @@ array[i++] = y1; | ||
array[i++] = thickness; | ||
array[i++] = color; | ||
array[i++] = color; // First point flipped | ||
// First point flipped | ||
array[i++] = x1; | ||
@@ -137,5 +156,4 @@ array[i++] = y1; | ||
array[i++] = thickness; | ||
array[i++] = color; | ||
array[i++] = color; // Second point | ||
// Second point | ||
array[i++] = x2; | ||
@@ -146,5 +164,4 @@ array[i++] = y2; | ||
array[i++] = thickness; | ||
array[i++] = color; | ||
array[i++] = color; // Second point flipped | ||
// Second point flipped | ||
array[i++] = x2; | ||
@@ -155,14 +172,12 @@ array[i++] = y2; | ||
array[i++] = thickness; | ||
array[i++] = color; | ||
array[i] = color; | ||
} | ||
}, { | ||
key: 'computeIndices', | ||
value: function computeIndices(array) { | ||
var l = array.length / EdgeProgram.ATTRIBUTES; | ||
key: "computeIndices", | ||
value: function computeIndices() { | ||
var l = this.array.length / ATTRIBUTES; | ||
var size = l + l / 2; | ||
var indices = new this.IndicesArray(size); | ||
var indices = new Uint16Array(size); | ||
for (var i = 0, c = 0; i < size; i += 4) { | ||
for (var i = 0, c = 0; i < l; i += 4) { | ||
indices[c++] = i; | ||
@@ -176,24 +191,28 @@ indices[c++] = i + 1; | ||
return indices; | ||
this.indicesArray = indices; | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render(gl, array, params) { | ||
key: "bufferData", | ||
value: function bufferData() { | ||
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); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render(params) { | ||
var gl = this.gl; | ||
var program = this.program; | ||
gl.useProgram(program); | ||
gl.useProgram(program); // Binding uniforms | ||
// TODO: precise the uniform names | ||
// 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.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: | ||
// 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); | ||
gl.drawElements(gl.TRIANGLES, this.indicesArray.length, this.indicesType, 0); | ||
} | ||
@@ -203,8 +222,4 @@ }]); | ||
return EdgeProgram; | ||
}(_program2.default); | ||
}(_program.default); | ||
exports.default = EdgeProgram; | ||
EdgeProgram.POINTS = 4; | ||
EdgeProgram.ATTRIBUTES = 6; | ||
exports.default = EdgeProgram; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,45 +6,68 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
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 = _interopRequireDefault(require("./program")); | ||
var _program = require('./program'); | ||
var _utils = require("../utils"); | ||
var _program2 = _interopRequireDefault(_program); | ||
var _nodeFastVert = _interopRequireDefault(require("../shaders/node.fast.vert.glsl")); | ||
var _utils = require('../utils'); | ||
var _nodeFastFrag = _interopRequireDefault(require("../shaders/node.fast.frag.glsl")); | ||
var _nodeFastVert = require('../shaders/node.fast.vert.glsl'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _nodeFastVert2 = _interopRequireDefault(_nodeFastVert); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _nodeFastFrag = require('../shaders/node.fast.frag.glsl'); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _nodeFastFrag2 = _interopRequireDefault(_nodeFastFrag); | ||
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); } } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _createClass(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"); } } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
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 _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return 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. | ||
*/ | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
var NodeProgramFast = function (_Program) { | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
var POINTS = 1, | ||
ATTRIBUTES = 4; | ||
var NodeProgramFast = | ||
/*#__PURE__*/ | ||
function (_Program) { | ||
_inherits(NodeProgramFast, _Program); | ||
function NodeProgramFast() { | ||
function NodeProgramFast(gl) { | ||
var _this; | ||
_classCallCheck(this, NodeProgramFast); | ||
var _this = _possibleConstructorReturn(this, (NodeProgramFast.__proto__ || Object.getPrototypeOf(NodeProgramFast)).call(this)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(NodeProgramFast).call(this, gl, _nodeFastVert.default, _nodeFastFrag.default)); // Binding context | ||
_this.vertexShaderSource = _nodeFastVert2.default; | ||
_this.fragmentShaderSource = _nodeFastFrag2.default; | ||
_this.gl = gl; // Array data | ||
_this.array = null; // Initializing buffers | ||
_this.buffer = gl.createBuffer(); | ||
gl.bindBuffer(gl.ARRAY_BUFFER, _this.buffer); | ||
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; | ||
@@ -54,44 +77,42 @@ } | ||
_createClass(NodeProgramFast, [{ | ||
key: 'process', | ||
value: function process(array, data, i) { | ||
key: "allocate", | ||
value: function allocate(capacity) { | ||
this.array = new Float32Array(POINTS * ATTRIBUTES * capacity); | ||
} | ||
}, { | ||
key: "process", | ||
value: function process(data, offset) { | ||
var color = (0, _utils.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; | ||
array[i] = color; | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render(gl, array, params) { | ||
key: "bufferData", | ||
value: function bufferData() { | ||
var gl = this.gl; | ||
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render(params) { | ||
var gl = this.gl; | ||
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); | ||
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); | ||
} | ||
@@ -101,8 +122,4 @@ }]); | ||
return NodeProgramFast; | ||
}(_program2.default); | ||
}(_program.default); | ||
exports.default = NodeProgramFast; | ||
NodeProgramFast.POINTS = 1; | ||
NodeProgramFast.ATTRIBUTES = 4; | ||
exports.default = NodeProgramFast; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,53 +6,57 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
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 = _interopRequireDefault(require("./program")); | ||
var _program = require('./program'); | ||
var _utils = require("../utils"); | ||
var _program2 = _interopRequireDefault(_program); | ||
var _nodeVert = _interopRequireDefault(require("../shaders/node.vert.glsl")); | ||
var _utils = require('../utils'); | ||
var _nodeFrag = _interopRequireDefault(require("../shaders/node.frag.glsl")); | ||
var _nodeVert = require('../shaders/node.vert.glsl'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _nodeVert2 = _interopRequireDefault(_nodeVert); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _nodeFrag = require('../shaders/node.frag.glsl'); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _nodeFrag2 = _interopRequireDefault(_nodeFrag); | ||
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); } } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _createClass(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"); } } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
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 _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return 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. | ||
*/ | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
var ANGLE_1 = 0, | ||
ANGLE_2 = 2 * Math.PI / 3, | ||
ANGLE_3 = 4 * Math.PI / 3; | ||
var POINTS = 3, | ||
ATTRIBUTES = 5; | ||
var NodeProgram = function (_Program) { | ||
var NodeProgram = | ||
/*#__PURE__*/ | ||
function (_Program) { | ||
_inherits(NodeProgram, _Program); | ||
function NodeProgram(gl) { | ||
var _this; | ||
_classCallCheck(this, NodeProgram); | ||
// Initializing buffers | ||
var _this = _possibleConstructorReturn(this, (NodeProgram.__proto__ || Object.getPrototypeOf(NodeProgram)).call(this, gl, _nodeVert2.default, _nodeFrag2.default)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(NodeProgram).call(this, gl, _nodeVert.default, _nodeFrag.default)); // Binding context | ||
_this.gl = gl; // Array data | ||
_this.array = null; // Initializing buffers | ||
_this.buffer = gl.createBuffer(); | ||
gl.bindBuffer(gl.ARRAY_BUFFER, _this.buffer); | ||
gl.bindBuffer(gl.ARRAY_BUFFER, _this.buffer); // Locations | ||
// Locations | ||
_this.positionLocation = gl.getAttribLocation(_this.program, 'a_position'); | ||
@@ -65,5 +69,4 @@ _this.sizeLocation = gl.getAttribLocation(_this.program, 'a_size'); | ||
_this.ratioLocation = gl.getUniformLocation(_this.program, 'u_ratio'); | ||
_this.scaleLocation = gl.getUniformLocation(_this.program, 'u_scale'); | ||
_this.scaleLocation = gl.getUniformLocation(_this.program, 'u_scale'); // Bindings | ||
// Bindings | ||
gl.enableVertexAttribArray(_this.positionLocation); | ||
@@ -73,10 +76,6 @@ gl.enableVertexAttribArray(_this.sizeLocation); | ||
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); | ||
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; | ||
@@ -86,6 +85,12 @@ } | ||
_createClass(NodeProgram, [{ | ||
key: 'process', | ||
value: function process(array, data, i) { | ||
key: "allocate", | ||
value: function allocate(capacity) { | ||
this.array = new Float32Array(POINTS * ATTRIBUTES * capacity); | ||
} | ||
}, { | ||
key: "process", | ||
value: function process(data, offset) { | ||
var color = (0, _utils.floatColor)(data.color); | ||
var i = offset * POINTS * ATTRIBUTES; | ||
var array = this.array; | ||
array[i++] = data.x; | ||
@@ -96,3 +101,2 @@ array[i++] = data.y; | ||
array[i++] = ANGLE_1; | ||
array[i++] = data.x; | ||
@@ -103,3 +107,2 @@ array[i++] = data.y; | ||
array[i++] = ANGLE_2; | ||
array[i++] = data.x; | ||
@@ -109,12 +112,16 @@ array[i++] = data.y; | ||
array[i++] = color; | ||
array[i++] = ANGLE_3; | ||
array[i] = ANGLE_3; | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render(gl, array, params) { | ||
key: "bufferData", | ||
value: function bufferData() { | ||
var gl = this.gl; | ||
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render(params) { | ||
var gl = this.gl; | ||
var program = this.program; | ||
gl.useProgram(program); | ||
gl.bufferData(gl.ARRAY_BUFFER, array, gl.DYNAMIC_DRAW); | ||
gl.uniform2f(this.resolutionLocation, params.width, params.height); | ||
@@ -124,4 +131,3 @@ gl.uniform1f(this.ratioLocation, 1 / Math.pow(params.ratio, params.nodesPowRatio)); | ||
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix); | ||
gl.drawArrays(gl.TRIANGLES, 0, array.length / NodeProgram.ATTRIBUTES); | ||
gl.drawArrays(gl.TRIANGLES, 0, this.array.length / ATTRIBUTES); | ||
} | ||
@@ -131,8 +137,4 @@ }]); | ||
return NodeProgram; | ||
}(_program2.default); | ||
}(_program.default); | ||
exports.default = NodeProgram; | ||
NodeProgram.POINTS = 3; | ||
NodeProgram.ATTRIBUTES = 5; | ||
exports.default = NodeProgram; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,15 +6,21 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.createCompoundProgram = createCompoundProgram; | ||
exports.default = void 0; | ||
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 _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
var _utils = require('../shaders/utils'); | ||
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } | ||
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } | ||
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
/** | ||
@@ -25,3 +31,5 @@ * Program class. | ||
*/ | ||
var Program = function () { | ||
var Program = | ||
/*#__PURE__*/ | ||
function () { | ||
function Program(gl, vertexShaderSource, fragmentShaderSource) { | ||
@@ -32,6 +40,4 @@ _classCallCheck(this, Program); | ||
this.fragmentShaderSource = fragmentShaderSource; | ||
this.load(gl); | ||
} | ||
/** | ||
@@ -46,9 +52,7 @@ * Method used to load the program into a webgl context. | ||
_createClass(Program, [{ | ||
key: 'load', | ||
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; | ||
@@ -60,3 +64,71 @@ } | ||
}(); | ||
/** | ||
* 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 | ||
exports.default = Program; | ||
exports.default = Program; | ||
function createCompoundProgram(programClasses) { | ||
return ( | ||
/*#__PURE__*/ | ||
function () { | ||
function CompoundProgram(gl) { | ||
_classCallCheck(this, CompoundProgram); | ||
this.programs = programClasses.map(function (ProgramClass) { | ||
return new ProgramClass(gl); | ||
}); | ||
} | ||
_createClass(CompoundProgram, [{ | ||
key: "allocate", | ||
value: function allocate(capacity) { | ||
this.programs.forEach(function (program) { | ||
return program.allocate(capacity); | ||
}); | ||
} | ||
}, { | ||
key: "process", | ||
value: function process() { | ||
var args = arguments; | ||
this.programs.forEach(function (program) { | ||
return program.process.apply(program, _toConsumableArray(args)); | ||
}); | ||
} | ||
}, { | ||
key: "computeIndices", | ||
value: function computeIndices() { | ||
this.programs.forEach(function (program) { | ||
if (typeof program.computeIndices === 'function') program.computeIndices(); | ||
}); | ||
} | ||
}, { | ||
key: "bufferData", | ||
value: function bufferData() { | ||
this.programs.forEach(function (program) { | ||
return program.bufferData(); | ||
}); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var args = arguments; | ||
this.programs.forEach(function (program) { | ||
program.bind(); | ||
program.bufferData(); | ||
program.render.apply(program, _toConsumableArray(args)); | ||
}); | ||
} | ||
}]); | ||
return CompoundProgram; | ||
}() | ||
); | ||
} |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -7,2 +7,4 @@ Object.defineProperty(exports, "__esModule", { | ||
exports.loadProgram = loadProgram; | ||
exports.loadFragmentShader = exports.loadVertexShader = void 0; | ||
/** | ||
@@ -19,22 +21,16 @@ * Sigma.js Shader Utils | ||
function loadShader(type, gl, source) { | ||
var glType = type === 'VERTEX' ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER; | ||
var glType = type === 'VERTEX' ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER; // Creating the shader | ||
// Creating the shader | ||
var shader = gl.createShader(glType); | ||
var shader = gl.createShader(glType); // Loading source | ||
// Loading source | ||
gl.shaderSource(shader, source); | ||
gl.shaderSource(shader, source); // Compiling the shader | ||
// Compiling the shader | ||
gl.compileShader(shader); | ||
gl.compileShader(shader); // Retrieving compilation status | ||
// Retrieving compilation status | ||
var successfullyCompiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); | ||
var successfullyCompiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); // Throwing if something went awry | ||
// 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); | ||
throw new Error("sigma/renderers/weblg/shaders/utils.loadShader: error while compiling the shader:\n".concat(infoLog, "\n").concat(source)); | ||
} | ||
@@ -47,5 +43,4 @@ | ||
loadFragmentShader = loadShader.bind(null, 'FRAGMENT'); | ||
exports.loadFragmentShader = loadFragmentShader; | ||
exports.loadVertexShader = loadVertexShader; | ||
exports.loadFragmentShader = loadFragmentShader; | ||
@@ -55,19 +50,15 @@ /** | ||
*/ | ||
function loadProgram(gl, shaders) { | ||
var program = gl.createProgram(); | ||
var i, l; // Attaching the shaders | ||
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 | ||
gl.linkProgram(program); // Checking status | ||
var successfullyLinked = gl.getProgramParameter(program, gl.LINK_STATUS); | ||
if (!successfullyLinked) { | ||
gl.deleteProgram(program); | ||
@@ -74,0 +65,0 @@ throw new Error('sigma/renderers/weblg/shaders/utils.loadProgram: error while linking the program.'); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -9,32 +9,32 @@ Object.defineProperty(exports, "__esModule", { | ||
exports.extractPixel = extractPixel; | ||
exports.canUse32BitsIndices = canUse32BitsIndices; | ||
var _glMatrix = require('gl-matrix'); | ||
var _matrices = require("./matrices"); | ||
/** | ||
* Sigma.js WebGL Renderer Utils | ||
* ============================== | ||
* | ||
* Miscelleanous helper functions used by sigma's WebGL renderer. | ||
*/ | ||
/** | ||
* 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; | ||
b = 0, | ||
a = 1; // Handling hexadecimal notation | ||
// Handling hexadecimal notation | ||
if (val[0] === '#') { | ||
@@ -50,26 +50,25 @@ if (val.length === 4) { | ||
} | ||
} | ||
// Handling rgb notation | ||
} // 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; | ||
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; | ||
} | ||
/** | ||
* Function returning a matrix from the current state of the camera. | ||
*/ | ||
// TODO: it's possible to optimize this drastically! | ||
// TODO: it's possible to optimize this drastically! | ||
function matrixFromCamera(state) { | ||
function matrixFromCamera(state, dimensions) { | ||
var angle = state.angle, | ||
@@ -79,24 +78,35 @@ ratio = state.ratio, | ||
y = state.y; | ||
var width = dimensions.width, | ||
height = dimensions.height; | ||
var matrix = (0, _matrices.identity)(); | ||
var smallestDimension = Math.min(width, height); | ||
var cameraCentering = (0, _matrices.translate)((0, _matrices.identity)(), -x, -y), | ||
cameraScaling = (0, _matrices.scale)((0, _matrices.identity)(), 1 / ratio), | ||
cameraRotation = (0, _matrices.rotate)((0, _matrices.identity)(), -angle), | ||
viewportScaling = (0, _matrices.scale)((0, _matrices.identity)(), 2 * (smallestDimension / width), 2 * (smallestDimension / height)); // Logical order is reversed | ||
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); | ||
(0, _matrices.multiply)(matrix, viewportScaling); | ||
(0, _matrices.multiply)(matrix, cameraRotation); | ||
(0, _matrices.multiply)(matrix, cameraScaling); | ||
(0, _matrices.multiply)(matrix, cameraCentering); | ||
return matrix; | ||
} | ||
/** | ||
* 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; | ||
} | ||
/** | ||
* Function used to know whether given webgl context can use 32 bits indices. | ||
*/ | ||
return data; | ||
function canUse32BitsIndices(gl) { | ||
var webgl2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext; | ||
return webgl2 || !!gl.getExtension('OES_element_index_uint'); | ||
} |
@@ -7,2 +7,3 @@ "use strict"; | ||
exports.assign = assign; | ||
/** | ||
@@ -25,3 +26,3 @@ * Sigma.js Utils | ||
for (var _len = arguments.length, objects = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
for (var _len = arguments.length, objects = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
objects[_key - 1] = arguments[_key]; | ||
@@ -28,0 +29,0 @@ } |
@@ -1,17 +0,19 @@ | ||
var path = require('path'); | ||
var path = require('path'), | ||
glob = require('glob'); | ||
var shaders = glob.sync(path.join(__dirname, 'src', 'renderers', 'webgl', 'shaders', '*.glsl')); | ||
var entry = {}; | ||
shaders.forEach(function(p) { | ||
entry[path.basename(p, '.glsl')] = p; | ||
}); | ||
module.exports = { | ||
entry: { | ||
'node.vert': './src/renderers/webgl/shaders/node.vert.glsl', | ||
'node.fast.vert': './src/renderers/webgl/shaders/node.fast.vert.glsl', | ||
'edge.vert': './src/renderers/webgl/shaders/edge.vert.glsl', | ||
'edge.fast.vert': './src/renderers/webgl/shaders/edge.fast.vert.glsl', | ||
'node.frag': './src/renderers/webgl/shaders/node.frag.glsl', | ||
'node.fast.frag': './src/renderers/webgl/shaders/node.fast.frag.glsl', | ||
'edge.frag': './src/renderers/webgl/shaders/edge.frag.glsl', | ||
'edge.fast.frag': './src/renderers/webgl/shaders/edge.fast.frag.glsl' | ||
}, | ||
mode: 'production', | ||
entry: entry, | ||
output: { | ||
path: path.join(__dirname, 'renderers', 'webgl', 'shaders'), | ||
filename: '[name].glsl' | ||
filename: '[name].glsl', | ||
libraryTarget: 'commonjs2' | ||
}, | ||
@@ -18,0 +20,0 @@ module: { |
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
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
821918
35.98%57
50%4
33.33%28
40%3826
-66.61%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
Updated
Updated