UNPKG

react-sigma-conglei

Version:

Lightweight but powerful library for drawing network graphs built on top of dunnock/react-sigma

409 lines (358 loc) 12.7 kB
var Sigma = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // identity function for calling harmony imports with the correct context /******/ __webpack_require__.i = function(value) { return value; }; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 130); /******/ }) /************************************************************************/ /******/ ({ /***/ 130: /***/ (function(module, exports) { /*** IMPORTS FROM imports-loader ***/ (function() { /** * This plugin provides a method to drag & drop nodes. Check the * sigma.plugins.dragNodes function doc or the examples/basic.html & * examples/api-candy.html code samples to know more. */ (function() { 'use strict'; if (typeof sigma === 'undefined') throw 'sigma is not declared'; sigma.utils.pkg('sigma.plugins'); /** * This function will add `mousedown`, `mouseup` & `mousemove` events to the * nodes in the `overNode`event to perform drag & drop operations. It uses * `linear interpolation` [http://en.wikipedia.org/wiki/Linear_interpolation] * and `rotation matrix` [http://en.wikipedia.org/wiki/Rotation_matrix] to * calculate the X and Y coordinates from the `cam` or `renderer` node * attributes. These attributes represent the coordinates of the nodes in * the real container, not in canvas. * * Fired events: * ************* * startdrag Fired at the beginning of the drag. * drag Fired while the node is dragged. * drop Fired at the end of the drag if the node has been dragged. * dragend Fired at the end of the drag. * * Recognized parameters: * ********************** * @param {sigma} s The related sigma instance. * @param {renderer} renderer The related renderer instance. */ function DragNodes(s, renderer) { sigma.classes.dispatcher.extend(this); // A quick hardcoded rule to prevent people from using this plugin with the // WebGL renderer (which is impossible at the moment): // if ( // sigma.renderers.webgl && // renderer instanceof sigma.renderers.webgl // ) // throw new Error( // 'The sigma.plugins.dragNodes is not compatible with the WebGL renderer' // ); // Init variables: var _self = this, _s = s, _body = document.body, _renderer = renderer, _mouse = renderer.container.lastChild, _camera = renderer.camera, _node = null, _prefix = '', _hoverStack = [], _hoverIndex = {}, _isMouseDown = false, _isMouseOverCanvas = false, _drag = false; if (renderer instanceof sigma.renderers.svg) { _mouse = renderer.container.firstChild; } // It removes the initial substring ('read_') if it's a WegGL renderer. if (renderer instanceof sigma.renderers.webgl) { _prefix = renderer.options.prefix.substr(5); } else { _prefix = renderer.options.prefix; } renderer.bind('overNode', nodeMouseOver); renderer.bind('outNode', treatOutNode); renderer.bind('click', click); _s.bind('kill', function() { _self.unbindAll(); }); /** * Unbind all event listeners. */ this.unbindAll = function() { _mouse.removeEventListener('mousedown', nodeMouseDown); _body.removeEventListener('mousemove', nodeMouseMove); _body.removeEventListener('mouseup', nodeMouseUp); _renderer.unbind('overNode', nodeMouseOver); _renderer.unbind('outNode', treatOutNode); } // Calculates the global offset of the given element more accurately than // element.offsetTop and element.offsetLeft. function calculateOffset(element) { var style = window.getComputedStyle(element); var getCssProperty = function(prop) { return parseInt(style.getPropertyValue(prop).replace('px', '')) || 0; }; return { left: element.getBoundingClientRect().left + getCssProperty('padding-left'), top: element.getBoundingClientRect().top + getCssProperty('padding-top') }; }; function click(event) { // event triggered at the end of the click _isMouseDown = false; _body.removeEventListener('mousemove', nodeMouseMove); _body.removeEventListener('mouseup', nodeMouseUp); if (!_hoverStack.length) { _node = null; } }; function nodeMouseOver(event) { // Don't treat the node if it is already registered if (_hoverIndex[event.data.node.id]) { return; } // Add node to array of current nodes over _hoverStack.push(event.data.node); _hoverIndex[event.data.node.id] = true; if(_hoverStack.length && ! _isMouseDown) { // Set the current node to be the last one in the array _node = _hoverStack[_hoverStack.length - 1]; _mouse.addEventListener('mousedown', nodeMouseDown); } }; function treatOutNode(event) { // Remove the node from the array var indexCheck = _hoverStack.map(function(e) { return e; }).indexOf(event.data.node); _hoverStack.splice(indexCheck, 1); delete _hoverIndex[event.data.node.id]; if(_hoverStack.length && ! _isMouseDown) { // On out, set the current node to be the next stated in array _node = _hoverStack[_hoverStack.length - 1]; } else { _mouse.removeEventListener('mousedown', nodeMouseDown); } }; function nodeMouseDown(event) { _isMouseDown = true; var size = _s.graph.nodes().length; // when there is only node in the graph, the plugin cannot apply // linear interpolation. So treat it as if a user is dragging // the graph if (_node && size > 1) { _mouse.removeEventListener('mousedown', nodeMouseDown); _body.addEventListener('mousemove', nodeMouseMove); _body.addEventListener('mouseup', nodeMouseUp); // Do not refresh edgequadtree during drag: var k, c; for (k in _s.cameras) { c = _s.cameras[k]; if (c.edgequadtree !== undefined) { c.edgequadtree._enabled = false; } } // Deactivate drag graph. _renderer.settings({mouseEnabled: false, enableHovering: false}); _s.refresh(); _self.dispatchEvent('startdrag', { node: _node, captor: event, renderer: _renderer }); } }; function nodeMouseUp(event) { _isMouseDown = false; _mouse.addEventListener('mousedown', nodeMouseDown); _body.removeEventListener('mousemove', nodeMouseMove); _body.removeEventListener('mouseup', nodeMouseUp); // Allow to refresh edgequadtree: var k, c; for (k in _s.cameras) { c = _s.cameras[k]; if (c.edgequadtree !== undefined) { c.edgequadtree._enabled = true; } } // Activate drag graph. _renderer.settings({mouseEnabled: true, enableHovering: true}); _s.refresh(); if (_drag) { _self.dispatchEvent('drop', { node: _node, captor: event, renderer: _renderer }); } _self.dispatchEvent('dragend', { node: _node, captor: event, renderer: _renderer }); _drag = false; _node = null; }; function nodeMouseMove(event) { if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1) { clearTimeout(timeOut); var timeOut = setTimeout(executeNodeMouseMove, 0); } else { executeNodeMouseMove(); } function executeNodeMouseMove() { var offset = calculateOffset(_renderer.container), x = event.clientX - offset.left, y = event.clientY - offset.top, cos = Math.cos(_camera.angle), sin = Math.sin(_camera.angle), nodes = _s.graph.nodes(), ref = []; // Getting and derotating the reference coordinates. for (var i = 0; i < 2; i++) { var n = nodes[i]; var aux = { x: n.x * cos + n.y * sin, y: n.y * cos - n.x * sin, renX: n[_prefix + 'x'], renY: n[_prefix + 'y'], }; ref.push(aux); } // Applying linear interpolation. // if the nodes are on top of each other, we use the camera ratio to interpolate if (ref[0].x === ref[1].x && ref[0].y === ref[1].y) { var xRatio = (ref[0].renX === 0) ? 1 : ref[0].renX; var yRatio = (ref[0].renY === 0) ? 1 : ref[0].renY; x = (ref[0].x / xRatio) * (x - ref[0].renX) + ref[0].x; y = (ref[0].y / yRatio) * (y - ref[0].renY) + ref[0].y; } else { var xRatio = (ref[1].renX - ref[0].renX) / (ref[1].x - ref[0].x); var yRatio = (ref[1].renY - ref[0].renY) / (ref[1].y - ref[0].y); // if the coordinates are the same, we use the other ratio to interpolate if (ref[1].x === ref[0].x) { xRatio = yRatio; } if (ref[1].y === ref[0].y) { yRatio = xRatio; } x = (x - ref[0].renX) / xRatio + ref[0].x; y = (y - ref[0].renY) / yRatio + ref[0].y; } // Rotating the coordinates. _node.x = x * cos - y * sin; _node.y = y * cos + x * sin; _s.refresh(); _drag = true; _self.dispatchEvent('drag', { node: _node, captor: event, renderer: _renderer }); } }; }; /** * Interface * ------------------ * * > var dragNodesListener = sigma.plugins.dragNodes(s, s.renderers[0]); */ var _instance = {}; /** * @param {sigma} s The related sigma instance. * @param {renderer} renderer The related renderer instance. */ sigma.plugins.dragNodes = function(s, renderer) { // Create object if undefined if (!_instance[s.id]) { _instance[s.id] = new DragNodes(s, renderer); } s.bind('kill', function() { sigma.plugins.killDragNodes(s); }); return _instance[s.id]; }; /** * This method removes the event listeners and kills the dragNodes instance. * * @param {sigma} s The related sigma instance. */ sigma.plugins.killDragNodes = function(s) { if (_instance[s.id] instanceof DragNodes) { _instance[s.id].unbindAll(); delete _instance[s.id]; } }; }).call(window); }.call(window)); /***/ }) /******/ });