diff --git a/dist/vis.js b/dist/vis.js index 07684d9b..718306b2 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 4.0.0-SNAPSHOT - * @date 2015-05-18 + * @date 2015-05-19 * * @license * Copyright (C) 2011-2014 Almende B.V, http://almende.com @@ -172,7 +172,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; var moment = __webpack_require__(40); - var uuid = __webpack_require__(113); + var uuid = __webpack_require__(42); /** * Test whether given object is a number @@ -3144,7 +3144,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var Emitter = __webpack_require__(42); + var Emitter = __webpack_require__(43); var DataSet = __webpack_require__(3); var DataView = __webpack_require__(4); var util = __webpack_require__(1); @@ -6307,23 +6307,23 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var Emitter = __webpack_require__(42); + var Emitter = __webpack_require__(43); var Hammer = __webpack_require__(41); var util = __webpack_require__(1); var DataSet = __webpack_require__(3); var DataView = __webpack_require__(4); var Range = __webpack_require__(17); - var Core = __webpack_require__(43); + var Core = __webpack_require__(44); var TimeAxis = __webpack_require__(35); var CurrentTime = __webpack_require__(26); var CustomTime = __webpack_require__(27); var ItemSet = __webpack_require__(32); - var ConfigurationSystem = __webpack_require__(44); - var Validator = __webpack_require__(45)['default']; - var printStyle = __webpack_require__(45).printStyle; - var allOptions = __webpack_require__(46).allOptions; - var configureOptions = __webpack_require__(46).configureOptions; + var ConfigurationSystem = __webpack_require__(45); + var Validator = __webpack_require__(46)['default']; + var printStyle = __webpack_require__(46).printStyle; + var allOptions = __webpack_require__(47).allOptions; + var configureOptions = __webpack_require__(47).configureOptions; /** * Create a timeline visualization @@ -6746,23 +6746,23 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var Emitter = __webpack_require__(42); + var Emitter = __webpack_require__(43); var Hammer = __webpack_require__(41); var util = __webpack_require__(1); var DataSet = __webpack_require__(3); var DataView = __webpack_require__(4); var Range = __webpack_require__(17); - var Core = __webpack_require__(43); + var Core = __webpack_require__(44); var TimeAxis = __webpack_require__(35); var CurrentTime = __webpack_require__(26); var CustomTime = __webpack_require__(27); var LineGraph = __webpack_require__(34); - var ConfigurationSystem = __webpack_require__(44); - var Validator = __webpack_require__(45)['default']; - var printStyle = __webpack_require__(45).printStyle; - var allOptions = __webpack_require__(47).allOptions; - var configureOptions = __webpack_require__(47).configureOptions; + var ConfigurationSystem = __webpack_require__(45); + var Validator = __webpack_require__(46)['default']; + var printStyle = __webpack_require__(46).printStyle; + var allOptions = __webpack_require__(48).allOptions; + var configureOptions = __webpack_require__(48).configureOptions; /** * Create a timeline visualization @@ -7756,7 +7756,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; var util = __webpack_require__(1); - var hammerUtil = __webpack_require__(48); + var hammerUtil = __webpack_require__(49); var moment = __webpack_require__(40); var Component = __webpack_require__(25); var DateUtil = __webpack_require__(15); @@ -10504,7 +10504,7 @@ return /******/ (function(modules) { // webpackBootstrap var util = __webpack_require__(1); var Component = __webpack_require__(25); var moment = __webpack_require__(40); - var locales = __webpack_require__(49); + var locales = __webpack_require__(50); /** * A current time bar @@ -10681,7 +10681,7 @@ return /******/ (function(modules) { // webpackBootstrap var util = __webpack_require__(1); var Component = __webpack_require__(25); var moment = __webpack_require__(40); - var locales = __webpack_require__(49); + var locales = __webpack_require__(50); /** * A custom time bar @@ -11522,9 +11522,9 @@ return /******/ (function(modules) { // webpackBootstrap var util = __webpack_require__(1); var DOMutil = __webpack_require__(2); - var Line = __webpack_require__(50); - var Bar = __webpack_require__(51); - var Points = __webpack_require__(52); + var Line = __webpack_require__(51); + var Bar = __webpack_require__(52); + var Points = __webpack_require__(53); /** * /** @@ -14189,8 +14189,8 @@ return /******/ (function(modules) { // webpackBootstrap var DataAxis = __webpack_require__(28); var GraphGroup = __webpack_require__(29); var Legend = __webpack_require__(33); - var BarFunctions = __webpack_require__(51); - var LineFunctions = __webpack_require__(50); + var BarFunctions = __webpack_require__(52); + var LineFunctions = __webpack_require__(51); var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items @@ -15599,68 +15599,68 @@ return /******/ (function(modules) { // webpackBootstrap function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - var _modulesGroups = __webpack_require__(53); + var _modulesGroups = __webpack_require__(54); var _modulesGroups2 = _interopRequireDefault(_modulesGroups); - var _modulesNodesHandler = __webpack_require__(54); + var _modulesNodesHandler = __webpack_require__(55); var _modulesNodesHandler2 = _interopRequireDefault(_modulesNodesHandler); - var _modulesEdgesHandler = __webpack_require__(55); + var _modulesEdgesHandler = __webpack_require__(56); var _modulesEdgesHandler2 = _interopRequireDefault(_modulesEdgesHandler); - var _modulesPhysicsEngine = __webpack_require__(56); + var _modulesPhysicsEngine = __webpack_require__(57); var _modulesPhysicsEngine2 = _interopRequireDefault(_modulesPhysicsEngine); - var _modulesClustering = __webpack_require__(57); + var _modulesClustering = __webpack_require__(58); var _modulesClustering2 = _interopRequireDefault(_modulesClustering); - var _modulesCanvasRenderer = __webpack_require__(58); + var _modulesCanvasRenderer = __webpack_require__(59); var _modulesCanvasRenderer2 = _interopRequireDefault(_modulesCanvasRenderer); - var _modulesCanvas = __webpack_require__(59); + var _modulesCanvas = __webpack_require__(60); var _modulesCanvas2 = _interopRequireDefault(_modulesCanvas); - var _modulesView = __webpack_require__(60); + var _modulesView = __webpack_require__(61); var _modulesView2 = _interopRequireDefault(_modulesView); - var _modulesInteractionHandler = __webpack_require__(61); + var _modulesInteractionHandler = __webpack_require__(62); var _modulesInteractionHandler2 = _interopRequireDefault(_modulesInteractionHandler); - var _modulesSelectionHandler = __webpack_require__(62); + var _modulesSelectionHandler = __webpack_require__(63); var _modulesSelectionHandler2 = _interopRequireDefault(_modulesSelectionHandler); - var _modulesLayoutEngine = __webpack_require__(63); + var _modulesLayoutEngine = __webpack_require__(64); var _modulesLayoutEngine2 = _interopRequireDefault(_modulesLayoutEngine); - var _modulesManipulationSystem = __webpack_require__(64); + var _modulesManipulationSystem = __webpack_require__(65); var _modulesManipulationSystem2 = _interopRequireDefault(_modulesManipulationSystem); - var _sharedConfigurationSystem = __webpack_require__(44); + var _sharedConfigurationSystem = __webpack_require__(45); var _sharedConfigurationSystem2 = _interopRequireDefault(_sharedConfigurationSystem); - var _sharedValidator = __webpack_require__(45); + var _sharedValidator = __webpack_require__(46); var _sharedValidator2 = _interopRequireDefault(_sharedValidator); - var _optionsJs = __webpack_require__(65); + var _optionsJs = __webpack_require__(66); // Load custom shapes into CanvasRenderingContext2D - __webpack_require__(66); + __webpack_require__(67); - var Emitter = __webpack_require__(42); + var Emitter = __webpack_require__(43); var Hammer = __webpack_require__(41); var util = __webpack_require__(1); var DataSet = __webpack_require__(3); @@ -15668,8 +15668,8 @@ return /******/ (function(modules) { // webpackBootstrap var dotparser = __webpack_require__(38); var gephiParser = __webpack_require__(39); var Images = __webpack_require__(37); - var Activator = __webpack_require__(67); - var locales = __webpack_require__(68); + var Activator = __webpack_require__(68); + var locales = __webpack_require__(69); /** * @constructor Network @@ -15898,7 +15898,7 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.on('_dataChanged', function () { // update shortcut lists _this2._updateVisibleIndices(); - _this2.physics.updatePhysicsIndices(); + _this2.physics.updatePhysicsData(); // call the dataUpdated event because the only difference between the two is the updating of the indices _this2.body.emitter.emit('_dataUpdated'); @@ -17149,7 +17149,7 @@ return /******/ (function(modules) { // webpackBootstrap // use this instance. Else, load via commonjs. 'use strict'; - module.exports = typeof window !== 'undefined' && window['moment'] || __webpack_require__(69); + module.exports = typeof window !== 'undefined' && window['moment'] || __webpack_require__(70); /***/ }, /* 41 */ @@ -17160,8 +17160,8 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; if (typeof window !== 'undefined') { - var propagating = __webpack_require__(70); - var Hammer = window['Hammer'] || __webpack_require__(71); + var propagating = __webpack_require__(71); + var Hammer = window['Hammer'] || __webpack_require__(72); module.exports = propagating(Hammer, { preventDefault: 'mouse' }); @@ -17175,6 +17175,222 @@ return /******/ (function(modules) { // webpackBootstrap /* 42 */ /***/ function(module, exports, __webpack_require__) { + /* WEBPACK VAR INJECTION */(function(global) {'use strict'; + + var _rng; + + var globalVar = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : null; + + if (globalVar && globalVar.crypto && crypto.getRandomValues) { + // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto + // Moderately fast, high quality + var _rnds8 = new Uint8Array(16); + _rng = function whatwgRNG() { + crypto.getRandomValues(_rnds8); + return _rnds8; + }; + } + + if (!_rng) { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var _rnds = new Array(16); + _rng = function () { + for (var i = 0, r; i < 16; i++) { + if ((i & 3) === 0) r = Math.random() * 4294967296; + _rnds[i] = r >>> ((i & 3) << 3) & 255; + } + + return _rnds; + }; + } + + // uuid.js + // + // Copyright (c) 2010-2012 Robert Kieffer + // MIT License - http://opensource.org/licenses/mit-license.php + + // Unique ID creation requires a high quality random # generator. We feature + // detect to determine the best RNG source, normalizing to a function that + // returns 128-bits of randomness, since that's what's usually required + + //var _rng = require('./rng'); + + // Maps for number <-> hex string conversion + var _byteToHex = []; + var _hexToByte = {}; + for (var i = 0; i < 256; i++) { + _byteToHex[i] = (i + 256).toString(16).substr(1); + _hexToByte[_byteToHex[i]] = i; + } + + // **`parse()` - Parse a UUID into it's component bytes** + function parse(s, buf, offset) { + var i = buf && offset || 0, + ii = 0; + + buf = buf || []; + s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) { + if (ii < 16) { + // Don't overflow! + buf[i + ii++] = _hexToByte[oct]; + } + }); + + // Zero out remaining bytes if string was short + while (ii < 16) { + buf[i + ii++] = 0; + } + + return buf; + } + + // **`unparse()` - Convert UUID byte array (ala parse()) into a string** + function unparse(buf, offset) { + var i = offset || 0, + bth = _byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]]; + } + + // **`v1()` - Generate time-based UUID** + // + // Inspired by https://github.com/LiosK/UUID.js + // and http://docs.python.org/library/uuid.html + + // random #'s we need to init node and clockseq + var _seedBytes = _rng(); + + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + var _nodeId = [_seedBytes[0] | 1, _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]]; + + // Per 4.2.2, randomize (14 bit) clockseq + var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 16383; + + // Previous uuid creation time + var _lastMSecs = 0, + _lastNSecs = 0; + + // See https://github.com/broofa/node-uuid for API details + function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + + var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 16383; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 268435455) * 10000 + nsecs) % 4294967296; + b[i++] = tl >>> 24 & 255; + b[i++] = tl >>> 16 & 255; + b[i++] = tl >>> 8 & 255; + b[i++] = tl & 255; + + // `time_mid` + var tmh = msecs / 4294967296 * 10000 & 268435455; + b[i++] = tmh >>> 8 & 255; + b[i++] = tmh & 255; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 15 | 16; // include version + b[i++] = tmh >>> 16 & 255; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 128; + + // `clock_seq_low` + b[i++] = clockseq & 255; + + // `node` + var node = options.node || _nodeId; + for (var n = 0; n < 6; n++) { + b[i + n] = node[n]; + } + + return buf ? buf : unparse(b); + } + + // **`v4()` - Generate random UUID** + + // See https://github.com/broofa/node-uuid for API details + function v4(options, buf, offset) { + // Deprecated - 'format' argument, as supported in v1.2 + var i = buf && offset || 0; + + if (typeof options == 'string') { + buf = options == 'binary' ? new Array(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || _rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = rnds[6] & 15 | 64; + rnds[8] = rnds[8] & 63 | 128; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ii++) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || unparse(rnds); + } + + // Export public API + var uuid = v4; + uuid.v1 = v1; + uuid.v4 = v4; + uuid.parse = parse; + uuid.unparse = unparse; + + module.exports = uuid; + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 43 */ +/***/ function(module, exports, __webpack_require__) { + /** * Expose `Emitter`. @@ -17342,21 +17558,21 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 43 */ +/* 44 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Emitter = __webpack_require__(42); + var Emitter = __webpack_require__(43); var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(48); + var hammerUtil = __webpack_require__(49); var util = __webpack_require__(1); var DataSet = __webpack_require__(3); var DataView = __webpack_require__(4); var Range = __webpack_require__(17); var ItemSet = __webpack_require__(32); var TimeAxis = __webpack_require__(35); - var Activator = __webpack_require__(67); + var Activator = __webpack_require__(68); var DateUtil = __webpack_require__(15); var CustomTime = __webpack_require__(27); @@ -18309,7 +18525,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Core; /***/ }, -/* 44 */ +/* 45 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -18324,7 +18540,7 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _networkModulesComponentsColorPicker = __webpack_require__(72); + var _networkModulesComponentsColorPicker = __webpack_require__(73); var _networkModulesComponentsColorPicker2 = _interopRequireDefault(_networkModulesComponentsColorPicker); @@ -18966,7 +19182,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 45 */ +/* 46 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -19279,7 +19495,7 @@ return /******/ (function(modules) { // webpackBootstrap // item is a function, which is allowed /***/ }, -/* 46 */ +/* 47 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -19496,7 +19712,7 @@ return /******/ (function(modules) { // webpackBootstrap exports.configureOptions = configureOptions; /***/ }, -/* 47 */ +/* 48 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -19767,7 +19983,7 @@ return /******/ (function(modules) { // webpackBootstrap exports.configureOptions = configureOptions; /***/ }, -/* 48 */ +/* 49 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -19839,7 +20055,7 @@ return /******/ (function(modules) { // webpackBootstrap exports.offRelease = exports.offTouch; /***/ }, -/* 49 */ +/* 50 */ /***/ function(module, exports, __webpack_require__) { // English @@ -19861,13 +20077,13 @@ return /******/ (function(modules) { // webpackBootstrap exports['nl_BE'] = exports['nl']; /***/ }, -/* 50 */ +/* 51 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var DOMutil = __webpack_require__(2); - var Points = __webpack_require__(52); + var Points = __webpack_require__(53); function Line(groupId, options) { this.groupId = groupId; @@ -20156,13 +20372,13 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Line; /***/ }, -/* 51 */ +/* 52 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var DOMutil = __webpack_require__(2); - var Points = __webpack_require__(52); + var Points = __webpack_require__(53); function Bargraph(groupId, options) { this.groupId = groupId; @@ -20404,7 +20620,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Bargraph; /***/ }, -/* 52 */ +/* 53 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -20451,7 +20667,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Points; /***/ }, -/* 53 */ +/* 54 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -20593,7 +20809,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 54 */ +/* 55 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -20608,11 +20824,11 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _componentsNode = __webpack_require__(73); + var _componentsNode = __webpack_require__(74); var _componentsNode2 = _interopRequireDefault(_componentsNode); - var _componentsSharedLabel = __webpack_require__(74); + var _componentsSharedLabel = __webpack_require__(75); var _componentsSharedLabel2 = _interopRequireDefault(_componentsSharedLabel); @@ -21066,7 +21282,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 55 */ +/* 56 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -21081,11 +21297,11 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _componentsEdge = __webpack_require__(75); + var _componentsEdge = __webpack_require__(76); var _componentsEdge2 = _interopRequireDefault(_componentsEdge); - var _componentsSharedLabel = __webpack_require__(74); + var _componentsSharedLabel = __webpack_require__(75); var _componentsSharedLabel2 = _interopRequireDefault(_componentsSharedLabel); @@ -21485,7 +21701,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 56 */ +/* 57 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -21500,35 +21716,35 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _componentsPhysicsBarnesHutSolver = __webpack_require__(76); + var _componentsPhysicsBarnesHutSolver = __webpack_require__(77); var _componentsPhysicsBarnesHutSolver2 = _interopRequireDefault(_componentsPhysicsBarnesHutSolver); - var _componentsPhysicsRepulsionSolver = __webpack_require__(77); + var _componentsPhysicsRepulsionSolver = __webpack_require__(78); var _componentsPhysicsRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsRepulsionSolver); - var _componentsPhysicsHierarchicalRepulsionSolver = __webpack_require__(78); + var _componentsPhysicsHierarchicalRepulsionSolver = __webpack_require__(79); var _componentsPhysicsHierarchicalRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsHierarchicalRepulsionSolver); - var _componentsPhysicsSpringSolver = __webpack_require__(79); + var _componentsPhysicsSpringSolver = __webpack_require__(80); var _componentsPhysicsSpringSolver2 = _interopRequireDefault(_componentsPhysicsSpringSolver); - var _componentsPhysicsHierarchicalSpringSolver = __webpack_require__(80); + var _componentsPhysicsHierarchicalSpringSolver = __webpack_require__(81); var _componentsPhysicsHierarchicalSpringSolver2 = _interopRequireDefault(_componentsPhysicsHierarchicalSpringSolver); - var _componentsPhysicsCentralGravitySolver = __webpack_require__(81); + var _componentsPhysicsCentralGravitySolver = __webpack_require__(82); var _componentsPhysicsCentralGravitySolver2 = _interopRequireDefault(_componentsPhysicsCentralGravitySolver); - var _componentsPhysicsFA2BasedRepulsionSolver = __webpack_require__(82); + var _componentsPhysicsFA2BasedRepulsionSolver = __webpack_require__(83); var _componentsPhysicsFA2BasedRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsFA2BasedRepulsionSolver); - var _componentsPhysicsFA2BasedCentralGravitySolver = __webpack_require__(83); + var _componentsPhysicsFA2BasedCentralGravitySolver = __webpack_require__(84); var _componentsPhysicsFA2BasedCentralGravitySolver2 = _interopRequireDefault(_componentsPhysicsFA2BasedCentralGravitySolver); @@ -21561,7 +21777,8 @@ return /******/ (function(modules) { // webpackBootstrap centralGravity: 0.3, springLength: 95, springConstant: 0.04, - damping: 0.09 + damping: 0.09, + avoidOverlap: 0 }, forceAtlas2Based: { theta: 0.5, @@ -21569,14 +21786,16 @@ return /******/ (function(modules) { // webpackBootstrap centralGravity: 0.01, springConstant: 0.08, springLength: 100, - damping: 0.4 + damping: 0.4, + avoidOverlap: 0 }, repulsion: { centralGravity: 0.2, springLength: 200, springConstant: 0.05, nodeDistance: 100, - damping: 0.09 + damping: 0.09, + avoidOverlap: 0 }, hierarchicalRepulsion: { centralGravity: 0, @@ -21705,6 +21924,10 @@ return /******/ (function(modules) { // webpackBootstrap value: function startSimulation() { if (this.physicsEnabled === true) { this.stabilized = false; + + // this sets the width of all nodes initially which could be required for the avoidOverlap + this.body.emitter.emit('_resizeNodes'); + if (this.viewFunction === undefined) { this.viewFunction = this.simulationStep.bind(this); this.body.emitter.on('initRedraw', this.viewFunction); @@ -21810,14 +22033,14 @@ return /******/ (function(modules) { // webpackBootstrap } } }, { - key: 'updatePhysicsIndices', + key: 'updatePhysicsData', /** * Nodes and edges can have the physics toggles on or off. A collection of indices is created here so we can skip the check all the time. * * @private */ - value: function updatePhysicsIndices() { + value: function updatePhysicsData() { this.physicsBody.forces = {}; this.physicsBody.physicsNodeIndices = []; this.physicsBody.physicsEdgeIndices = []; @@ -22028,6 +22251,9 @@ return /******/ (function(modules) { // webpackBootstrap iterations = this.options.stabilization.iterations; } + // this sets the width of all nodes initially which could be required for the avoidOverlap + this.body.emitter.emit('_resizeNodes'); + // stop the render loop this.stopSimulation(); @@ -22091,7 +22317,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 57 */ +/* 58 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -22106,7 +22332,7 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - var _componentsNodesCluster = __webpack_require__(84); + var _componentsNodesCluster = __webpack_require__(85); var _componentsNodesCluster2 = _interopRequireDefault(_componentsNodesCluster); @@ -22743,7 +22969,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 58 */ +/* 59 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -22800,6 +23026,9 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.on('dragEnd', function () { return _this.dragging = false; }); + this.body.emitter.on('_resizeNodes', function () { + return _this._resizeNodes(); + }); this.body.emitter.on('_redraw', function () { if (_this.renderingActive === false) { _this._redraw(); @@ -22961,6 +23190,41 @@ return /******/ (function(modules) { // webpackBootstrap ctx.clearRect(0, 0, w, h); } } + }, { + key: '_resizeNodes', + + /** + * Redraw all nodes + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @param {Boolean} [alwaysShow] + * @private + */ + value: function _resizeNodes() { + var ctx = this.canvas.frame.canvas.getContext('2d'); + if (this.pixelRatio === undefined) { + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); + } + ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + ctx.save(); + ctx.translate(this.body.view.translation.x, this.body.view.translation.y); + ctx.scale(this.body.view.scale, this.body.view.scale); + + var nodes = this.body.nodes; + var node = undefined; + + // resize all nodes + for (var nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + node = nodes[nodeId]; + node.resize(ctx); + node.updateBoundingBox(ctx); + } + } + + // restore original scaling and translation + ctx.restore(); + } }, { key: '_drawNodes', @@ -23083,7 +23347,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 59 */ +/* 60 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -23097,7 +23361,7 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(48); + var hammerUtil = __webpack_require__(49); var util = __webpack_require__(1); @@ -23451,7 +23715,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 60 */ +/* 61 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -23610,7 +23874,7 @@ return /******/ (function(modules) { // webpackBootstrap var factor = Math.min(this.canvas.frame.canvas.clientWidth / 600, this.canvas.frame.canvas.clientHeight / 600); zoomLevel *= factor; } else { - this.body.emitter.emit("_redraw", true); + this.body.emitter.emit("_resizeNodes"); range = this._getRange(options.nodes); var xDistance = Math.abs(range.maxX - range.minX) * 1.1; var yDistance = Math.abs(range.maxY - range.minY) * 1.1; @@ -23853,7 +24117,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 61 */ +/* 62 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -23868,11 +24132,11 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _componentsNavigationHandler = __webpack_require__(85); + var _componentsNavigationHandler = __webpack_require__(86); var _componentsNavigationHandler2 = _interopRequireDefault(_componentsNavigationHandler); - var _componentsPopup = __webpack_require__(86); + var _componentsPopup = __webpack_require__(87); var _componentsPopup2 = _interopRequireDefault(_componentsPopup); @@ -24559,7 +24823,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 62 */ +/* 63 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -24572,8 +24836,8 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - var Node = __webpack_require__(73); - var Edge = __webpack_require__(75); + var Node = __webpack_require__(74); + var Edge = __webpack_require__(76); var util = __webpack_require__(1); var SelectionHandler = (function () { @@ -25279,7 +25543,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 63 */ +/* 64 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -25431,7 +25695,6 @@ return /******/ (function(modules) { // webpackBootstrap if (!node.isFixed() && (node.x === undefined || node.y === undefined)) { var radius = 10 * 0.1 * nodesArray.length + 10; var angle = 2 * Math.PI * this.seededRandom(); - if (node.options.fixed.x === false) { node.x = radius * Math.cos(angle); } @@ -25776,7 +26039,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 64 */ +/* 65 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -25791,7 +26054,7 @@ return /******/ (function(modules) { // webpackBootstrap var util = __webpack_require__(1); var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(48); + var hammerUtil = __webpack_require__(49); /** * clears the toolbar div element of children @@ -26965,7 +27228,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 65 */ +/* 66 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -27194,6 +27457,7 @@ return /******/ (function(modules) { // webpackBootstrap springLength: { number: number }, springConstant: { number: number }, damping: { number: number }, + avoidOverlap: { number: number }, __type__: { object: object } }, forceAtlas2Based: { @@ -27202,6 +27466,7 @@ return /******/ (function(modules) { // webpackBootstrap springLength: { number: number }, springConstant: { number: number }, damping: { number: number }, + avoidOverlap: { number: number }, __type__: { object: object } }, repulsion: { @@ -27210,6 +27475,7 @@ return /******/ (function(modules) { // webpackBootstrap springConstant: { number: number }, nodeDistance: { number: number }, damping: { number: number }, + avoidOverlap: { number: number }, __type__: { object: object } }, hierarchicalRepulsion: { @@ -27399,7 +27665,8 @@ return /******/ (function(modules) { // webpackBootstrap centralGravity: [0.3, 0, 10, 0.05], springLength: [95, 0, 500, 5], springConstant: [0.04, 0, 5, 0.005], - damping: [0.09, 0, 1, 0.01] + damping: [0.09, 0, 1, 0.01], + avoidOverlap: [0, 0, 1, 0.01] }, forceAtlas2Based: { //theta: [0.5, 0.1, 1, 0.05], @@ -27407,14 +27674,16 @@ return /******/ (function(modules) { // webpackBootstrap centralGravity: [0.01, 0, 1, 0.005], springLength: [95, 0, 500, 5], springConstant: [0.08, 0, 5, 0.005], - damping: [0.4, 0, 1, 0.01] + damping: [0.4, 0, 1, 0.01], + avoidOverlap: [0, 0, 1, 0.01] }, repulsion: { centralGravity: [0.2, 0, 10, 0.05], springLength: [200, 0, 500, 5], springConstant: [0.05, 0, 5, 0.005], nodeDistance: [100, 0, 500, 5], - damping: [0.09, 0, 1, 0.01] + damping: [0.09, 0, 1, 0.01], + avoidOverlap: [0, 0, 1, 0.01] }, hierarchicalRepulsion: { centralGravity: [0.2, 0, 10, 0.05], @@ -27437,7 +27706,7 @@ return /******/ (function(modules) { // webpackBootstrap exports.configureOptions = configureOptions; /***/ }, -/* 66 */ +/* 67 */ /***/ function(module, exports, __webpack_require__) { /** @@ -27721,13 +27990,13 @@ return /******/ (function(modules) { // webpackBootstrap } /***/ }, -/* 67 */ +/* 68 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var keycharm = __webpack_require__(87); - var Emitter = __webpack_require__(42); + var keycharm = __webpack_require__(88); + var Emitter = __webpack_require__(43); var Hammer = __webpack_require__(41); var util = __webpack_require__(1); @@ -27874,7 +28143,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Activator; /***/ }, -/* 68 */ +/* 69 */ /***/ function(module, exports, __webpack_require__) { // English @@ -27918,7 +28187,7 @@ return /******/ (function(modules) { // webpackBootstrap exports['nl_BE'] = exports['nl']; /***/ }, -/* 69 */ +/* 70 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(module) {//! moment.js @@ -31004,10 +31273,10 @@ return /******/ (function(modules) { // webpackBootstrap return _moment; })); - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(89)(module))) + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(90)(module))) /***/ }, -/* 70 */ +/* 71 */ /***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;'use strict'; @@ -31235,7 +31504,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 71 */ +/* 72 */ /***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_RESULT__;/*! Hammer.JS - v2.0.4 - 2014-09-28 @@ -33690,7 +33959,7 @@ return /******/ (function(modules) { // webpackBootstrap prefixed: prefixed }); - if ("function" == TYPE_FUNCTION && __webpack_require__(90)) { + if ("function" == TYPE_FUNCTION && __webpack_require__(91)) { !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { return Hammer; }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); @@ -33704,7 +33973,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 72 */ +/* 73 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -33718,7 +33987,7 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(48); + var hammerUtil = __webpack_require__(49); var util = __webpack_require__(1); var ColorPicker = (function () { @@ -34284,7 +34553,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 73 */ +/* 74 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -34299,67 +34568,67 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _sharedLabel = __webpack_require__(74); + var _sharedLabel = __webpack_require__(75); var _sharedLabel2 = _interopRequireDefault(_sharedLabel); - var _nodesShapesBox = __webpack_require__(91); + var _nodesShapesBox = __webpack_require__(92); var _nodesShapesBox2 = _interopRequireDefault(_nodesShapesBox); - var _nodesShapesCircle = __webpack_require__(92); + var _nodesShapesCircle = __webpack_require__(93); var _nodesShapesCircle2 = _interopRequireDefault(_nodesShapesCircle); - var _nodesShapesCircularImage = __webpack_require__(93); + var _nodesShapesCircularImage = __webpack_require__(94); var _nodesShapesCircularImage2 = _interopRequireDefault(_nodesShapesCircularImage); - var _nodesShapesDatabase = __webpack_require__(94); + var _nodesShapesDatabase = __webpack_require__(95); var _nodesShapesDatabase2 = _interopRequireDefault(_nodesShapesDatabase); - var _nodesShapesDiamond = __webpack_require__(95); + var _nodesShapesDiamond = __webpack_require__(96); var _nodesShapesDiamond2 = _interopRequireDefault(_nodesShapesDiamond); - var _nodesShapesDot = __webpack_require__(96); + var _nodesShapesDot = __webpack_require__(97); var _nodesShapesDot2 = _interopRequireDefault(_nodesShapesDot); - var _nodesShapesEllipse = __webpack_require__(97); + var _nodesShapesEllipse = __webpack_require__(98); var _nodesShapesEllipse2 = _interopRequireDefault(_nodesShapesEllipse); - var _nodesShapesIcon = __webpack_require__(98); + var _nodesShapesIcon = __webpack_require__(99); var _nodesShapesIcon2 = _interopRequireDefault(_nodesShapesIcon); - var _nodesShapesImage = __webpack_require__(99); + var _nodesShapesImage = __webpack_require__(100); var _nodesShapesImage2 = _interopRequireDefault(_nodesShapesImage); - var _nodesShapesSquare = __webpack_require__(100); + var _nodesShapesSquare = __webpack_require__(101); var _nodesShapesSquare2 = _interopRequireDefault(_nodesShapesSquare); - var _nodesShapesStar = __webpack_require__(101); + var _nodesShapesStar = __webpack_require__(102); var _nodesShapesStar2 = _interopRequireDefault(_nodesShapesStar); - var _nodesShapesText = __webpack_require__(102); + var _nodesShapesText = __webpack_require__(103); var _nodesShapesText2 = _interopRequireDefault(_nodesShapesText); - var _nodesShapesTriangle = __webpack_require__(103); + var _nodesShapesTriangle = __webpack_require__(104); var _nodesShapesTriangle2 = _interopRequireDefault(_nodesShapesTriangle); - var _nodesShapesTriangleDown = __webpack_require__(104); + var _nodesShapesTriangleDown = __webpack_require__(105); var _nodesShapesTriangleDown2 = _interopRequireDefault(_nodesShapesTriangleDown); - var _sharedValidator = __webpack_require__(45); + var _sharedValidator = __webpack_require__(46); var _sharedValidator2 = _interopRequireDefault(_sharedValidator); @@ -34750,7 +35019,7 @@ return /******/ (function(modules) { // webpackBootstrap value: function parseOptions(parentOptions, newOptions) { var allowDeletion = arguments[2] === undefined ? false : arguments[2]; - var fields = ['color', 'fixed', 'shadow']; + var fields = ['color', 'font', 'fixed', 'shadow']; util.selectiveNotDeepExtend(fields, parentOptions, newOptions); // merge the shadow options into the parent. @@ -34778,6 +35047,10 @@ return /******/ (function(modules) { // webpackBootstrap } } } + + if (newOptions.font !== undefined) { + _sharedLabel2['default'].parseOptions(parentOptions.font, newOptions); + } } }]); @@ -34788,7 +35061,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 74 */ +/* 75 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -34892,7 +35165,7 @@ return /******/ (function(modules) { // webpackBootstrap ctx.fillRect(-this.size.width * 0.5, lineMargin, this.size.width, this.size.height); break; default: - ctx.fillRect(this.size.left, this.size.top, this.size.width, this.size.height); + ctx.fillRect(this.size.left, this.size.top - 0.5 * lineMargin, this.size.width, this.size.height); break; } } @@ -35103,7 +35376,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 75 */ +/* 76 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -35118,19 +35391,19 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _sharedLabel = __webpack_require__(74); + var _sharedLabel = __webpack_require__(75); var _sharedLabel2 = _interopRequireDefault(_sharedLabel); - var _edgesBezierEdgeDynamic = __webpack_require__(105); + var _edgesBezierEdgeDynamic = __webpack_require__(106); var _edgesBezierEdgeDynamic2 = _interopRequireDefault(_edgesBezierEdgeDynamic); - var _edgesBezierEdgeStatic = __webpack_require__(106); + var _edgesBezierEdgeStatic = __webpack_require__(107); var _edgesBezierEdgeStatic2 = _interopRequireDefault(_edgesBezierEdgeStatic); - var _edgesStraightEdge = __webpack_require__(107); + var _edgesStraightEdge = __webpack_require__(108); var _edgesStraightEdge2 = _interopRequireDefault(_edgesStraightEdge); @@ -35556,7 +35829,7 @@ return /******/ (function(modules) { // webpackBootstrap value: function parseOptions(parentOptions, newOptions) { var allowDeletion = arguments[2] === undefined ? false : arguments[2]; - var fields = ['id', 'font', 'from', 'hidden', 'hoverWidth', 'label', 'length', 'line', 'opacity', 'physics', 'selectionWidth', 'selfReferenceSize', 'to', 'title', 'value', 'width']; + var fields = ['id', 'from', 'hidden', 'hoverWidth', 'label', 'length', 'line', 'opacity', 'physics', 'selectionWidth', 'selfReferenceSize', 'to', 'title', 'value', 'width']; // only deep extend the items in the field array. These do not have shorthand. util.selectiveDeepExtend(fields, parentOptions, newOptions, allowDeletion); @@ -35653,7 +35926,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 76 */ +/* 77 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -35681,6 +35954,7 @@ return /******/ (function(modules) { // webpackBootstrap value: function setOptions(options) { this.options = options; this.thetaInversed = 1 / this.options.theta; + this.overlapAvoidanceFactor = 1 - Math.max(0, Math.min(1, this.options.avoidOverlap)); // if 1 then min distance = 0.5, if 0.5 then min distance = 0.5 + 0.5*node.shape.radius } }, { key: "solve", @@ -35780,6 +36054,11 @@ return /******/ (function(modules) { // webpackBootstrap distance = 0.1 * Math.random(); dx = distance; } + + if (this.overlapAvoidanceFactor < 1) { + distance = Math.max(0.1 + this.overlapAvoidanceFactor * node.shape.radius, distance - node.shape.radius); + } + // the dividing by the distance cubed instead of squared allows us to get the fx and fy components without sines and cosines // it is shorthand for gravityforce with distance squared and fx = dx/distance * gravityForce var gravityForce = this.options.gravitationalConstant * parentBranch.mass * node.options.mass / Math.pow(distance, 3); @@ -36139,7 +36418,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 77 */ +/* 78 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -36234,7 +36513,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 78 */ +/* 79 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -36325,7 +36604,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 79 */ +/* 80 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -36351,6 +36630,7 @@ return /******/ (function(modules) { // webpackBootstrap key: "setOptions", value: function setOptions(options) { this.options = options; + this.overlapAvoidanceFactor = 1 - Math.max(0, Math.min(1, this.options.avoidOverlap)); // if 1 then min distance = 0.5, if 0.5 then min distance = 0.5 + 0.5*node.shape.radius } }, { key: "solve", @@ -36405,8 +36685,17 @@ return /******/ (function(modules) { // webpackBootstrap * @private */ value: function _calculateSpringForce(node1, node2, edgeLength) { - var dx = node1.x - node2.x; - var dy = node1.y - node2.y; + var dx = undefined, + dy = undefined; + if (this.overlapAvoidanceFactor < 1) { + var nodesWidth = this.overlapAvoidanceFactor * (node1.shape.radius + node2.shape.radius); + dx = node1.x - node2.x - nodesWidth; + dy = node1.y - node2.y - nodesWidth; + } else { + dx = node1.x - node2.x; + dy = node1.y - node2.y; + } + var distance = Math.sqrt(dx * dx + dy * dy); distance = distance === 0 ? 0.01 : distance; @@ -36436,7 +36725,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 80 */ +/* 81 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -36557,7 +36846,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 81 */ +/* 82 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -36626,7 +36915,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 82 */ +/* 83 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -36647,7 +36936,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _BarnesHutSolver2 = __webpack_require__(76); + var _BarnesHutSolver2 = __webpack_require__(77); var _BarnesHutSolver3 = _interopRequireDefault(_BarnesHutSolver2); @@ -36678,6 +36967,11 @@ return /******/ (function(modules) { // webpackBootstrap distance = 0.1 * Math.random(); dx = distance; } + + if (this.overlapAvoidanceFactor < 1) { + distance = Math.max(0.1 + this.overlapAvoidanceFactor * node.shape.radius, distance - node.shape.radius); + } + var degree = node.edges.length + 1; // the dividing by the distance cubed instead of squared allows us to get the fx and fy components without sines and cosines // it is shorthand for gravityforce with distance squared and fx = dx/distance * gravityForce @@ -36697,7 +36991,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 83 */ +/* 84 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -36718,7 +37012,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _CentralGravitySolver2 = __webpack_require__(81); + var _CentralGravitySolver2 = __webpack_require__(82); var _CentralGravitySolver3 = _interopRequireDefault(_CentralGravitySolver2); @@ -36755,7 +37049,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 84 */ +/* 85 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -36774,7 +37068,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _Node2 = __webpack_require__(73); + var _Node2 = __webpack_require__(74); var _Node3 = _interopRequireDefault(_Node2); @@ -36802,7 +37096,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 85 */ +/* 86 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -36817,8 +37111,8 @@ return /******/ (function(modules) { // webpackBootstrap var util = __webpack_require__(1); var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(48); - var keycharm = __webpack_require__(87); + var hammerUtil = __webpack_require__(49); + var keycharm = __webpack_require__(88); var NavigationHandler = (function () { function NavigationHandler(body, canvas) { @@ -37072,7 +37366,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 86 */ +/* 87 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37199,7 +37493,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 87 */ +/* 88 */ /***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict"; @@ -37397,7 +37691,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 88 */ +/* 89 */ /***/ function(module, exports, __webpack_require__) { function webpackContext(req) { @@ -37406,11 +37700,11 @@ return /******/ (function(modules) { // webpackBootstrap webpackContext.keys = function() { return []; }; webpackContext.resolve = webpackContext; module.exports = webpackContext; - webpackContext.id = 88; + webpackContext.id = 89; /***/ }, -/* 89 */ +/* 90 */ /***/ function(module, exports, __webpack_require__) { module.exports = function(module) { @@ -37426,7 +37720,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 90 */ +/* 91 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {module.exports = __webpack_amd_options__; @@ -37434,7 +37728,7 @@ return /******/ (function(modules) { // webpackBootstrap /* WEBPACK VAR INJECTION */}.call(exports, {})) /***/ }, -/* 91 */ +/* 92 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37455,7 +37749,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilNodeBase = __webpack_require__(108); + var _utilNodeBase = __webpack_require__(109); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -37478,6 +37772,7 @@ return /******/ (function(modules) { // webpackBootstrap var textSize = this.labelModule.getTextSize(ctx, selected); this.width = textSize.width + 2 * margin; this.height = textSize.height + 2 * margin; + this.radius = 0.5 * this.width; } } }, { @@ -37542,7 +37837,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 92 */ +/* 93 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37563,7 +37858,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilCircleImageBase = __webpack_require__(109); + var _utilCircleImageBase = __webpack_require__(110); var _utilCircleImageBase2 = _interopRequireDefault(_utilCircleImageBase); @@ -37589,6 +37884,7 @@ return /******/ (function(modules) { // webpackBootstrap this.width = diameter; this.height = diameter; + this.radius = 0.5 * this.width; } } }, { @@ -37635,7 +37931,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 93 */ +/* 94 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37656,7 +37952,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilCircleImageBase = __webpack_require__(109); + var _utilCircleImageBase = __webpack_require__(110); var _utilCircleImageBase2 = _interopRequireDefault(_utilCircleImageBase); @@ -37682,6 +37978,7 @@ return /******/ (function(modules) { // webpackBootstrap this.width = diameter; this.height = diameter; this._swapToImageResizeWhenImageLoaded = true; + this.radius = 0.5 * this.width; } } else { if (this._swapToImageResizeWhenImageLoaded) { @@ -37742,7 +38039,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 94 */ +/* 95 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37763,7 +38060,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilNodeBase = __webpack_require__(108); + var _utilNodeBase = __webpack_require__(109); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -37787,6 +38084,7 @@ return /******/ (function(modules) { // webpackBootstrap var size = textSize.width + 2 * margin; this.width = size; this.height = size; + this.radius = 0.5 * this.width; } } }, { @@ -37850,7 +38148,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 95 */ +/* 96 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37871,7 +38169,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilShapeBase = __webpack_require__(110); + var _utilShapeBase = __webpack_require__(111); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -37910,7 +38208,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 96 */ +/* 97 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37931,7 +38229,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilShapeBase = __webpack_require__(110); + var _utilShapeBase = __webpack_require__(111); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -37970,7 +38268,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 97 */ +/* 98 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37991,7 +38289,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilNodeBase = __webpack_require__(108); + var _utilNodeBase = __webpack_require__(109); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -38017,6 +38315,7 @@ return /******/ (function(modules) { // webpackBootstrap if (this.width < this.height) { this.width = this.height; } + this.radius = 0.5 * this.width; } } }, { @@ -38080,7 +38379,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 98 */ +/* 99 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38101,7 +38400,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilNodeBase = __webpack_require__(108); + var _utilNodeBase = __webpack_require__(109); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -38127,6 +38426,7 @@ return /******/ (function(modules) { // webpackBootstrap }; this.width = iconSize.width + 2 * margin; this.height = iconSize.height + 2 * margin; + this.radius = 0.5 * this.width; } } }, { @@ -38199,7 +38499,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 99 */ +/* 100 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38220,7 +38520,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilCircleImageBase = __webpack_require__(109); + var _utilCircleImageBase = __webpack_require__(110); var _utilCircleImageBase2 = _interopRequireDefault(_utilCircleImageBase); @@ -38290,7 +38590,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 100 */ +/* 101 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38311,7 +38611,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilShapeBase = __webpack_require__(110); + var _utilShapeBase = __webpack_require__(111); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -38351,7 +38651,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 101 */ +/* 102 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38372,7 +38672,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilShapeBase = __webpack_require__(110); + var _utilShapeBase = __webpack_require__(111); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -38411,7 +38711,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 102 */ +/* 103 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38432,7 +38732,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilNodeBase = __webpack_require__(108); + var _utilNodeBase = __webpack_require__(109); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -38455,6 +38755,7 @@ return /******/ (function(modules) { // webpackBootstrap var textSize = this.labelModule.getTextSize(ctx, selected); this.width = textSize.width + 2 * margin; this.height = textSize.height + 2 * margin; + this.radius = 0.5 * this.width; } } }, { @@ -38499,7 +38800,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 103 */ +/* 104 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38520,7 +38821,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilShapeBase = __webpack_require__(110); + var _utilShapeBase = __webpack_require__(111); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -38559,7 +38860,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 104 */ +/* 105 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38580,7 +38881,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilShapeBase = __webpack_require__(110); + var _utilShapeBase = __webpack_require__(111); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -38619,7 +38920,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 105 */ +/* 106 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38640,7 +38941,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilBezierEdgeBase = __webpack_require__(111); + var _utilBezierEdgeBase = __webpack_require__(112); var _utilBezierEdgeBase2 = _interopRequireDefault(_utilBezierEdgeBase); @@ -38777,7 +39078,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 106 */ +/* 107 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38798,7 +39099,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilBezierEdgeBase = __webpack_require__(111); + var _utilBezierEdgeBase = __webpack_require__(112); var _utilBezierEdgeBase2 = _interopRequireDefault(_utilBezierEdgeBase); @@ -39043,7 +39344,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 107 */ +/* 108 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -39064,7 +39365,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilEdgeBase = __webpack_require__(112); + var _utilEdgeBase = __webpack_require__(113); var _utilEdgeBase2 = _interopRequireDefault(_utilEdgeBase); @@ -39155,7 +39456,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 108 */ +/* 109 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -39178,6 +39479,8 @@ return /******/ (function(modules) { // webpackBootstrap this.top = undefined; this.left = undefined; this.height = undefined; + this.width = undefined; + this.radius = undefined; this.boundingBox = { top: 0, left: 0, right: 0, bottom: 0 }; } @@ -39221,7 +39524,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 109 */ +/* 110 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -39242,7 +39545,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilNodeBase = __webpack_require__(108); + var _utilNodeBase = __webpack_require__(109); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -39278,6 +39581,7 @@ return /******/ (function(modules) { // webpackBootstrap } this.width = width; this.height = height; + this.radius = 0.5 * this.width; } } }, { @@ -39349,7 +39653,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 110 */ +/* 111 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -39370,7 +39674,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _utilNodeBase = __webpack_require__(108); + var _utilNodeBase = __webpack_require__(109); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -39390,6 +39694,7 @@ return /******/ (function(modules) { // webpackBootstrap var size = 2 * this.options.size; this.width = size; this.height = size; + this.radius = 0.5 * this.width; } } }, { @@ -39449,7 +39754,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 111 */ +/* 112 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -39470,7 +39775,7 @@ return /******/ (function(modules) { // webpackBootstrap 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) subClass.__proto__ = superClass; } - var _EdgeBase2 = __webpack_require__(112); + var _EdgeBase2 = __webpack_require__(113); var _EdgeBase3 = _interopRequireDefault(_EdgeBase2); @@ -39598,7 +39903,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 112 */ +/* 113 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -40183,222 +40488,6 @@ return /******/ (function(modules) { // webpackBootstrap exports['default'] = EdgeBase; module.exports = exports['default']; -/***/ }, -/* 113 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {'use strict'; - - var _rng; - - var globalVar = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : null; - - if (globalVar && globalVar.crypto && crypto.getRandomValues) { - // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto - // Moderately fast, high quality - var _rnds8 = new Uint8Array(16); - _rng = function whatwgRNG() { - crypto.getRandomValues(_rnds8); - return _rnds8; - }; - } - - if (!_rng) { - // Math.random()-based (RNG) - // - // If all else fails, use Math.random(). It's fast, but is of unspecified - // quality. - var _rnds = new Array(16); - _rng = function () { - for (var i = 0, r; i < 16; i++) { - if ((i & 3) === 0) r = Math.random() * 4294967296; - _rnds[i] = r >>> ((i & 3) << 3) & 255; - } - - return _rnds; - }; - } - - // uuid.js - // - // Copyright (c) 2010-2012 Robert Kieffer - // MIT License - http://opensource.org/licenses/mit-license.php - - // Unique ID creation requires a high quality random # generator. We feature - // detect to determine the best RNG source, normalizing to a function that - // returns 128-bits of randomness, since that's what's usually required - - //var _rng = require('./rng'); - - // Maps for number <-> hex string conversion - var _byteToHex = []; - var _hexToByte = {}; - for (var i = 0; i < 256; i++) { - _byteToHex[i] = (i + 256).toString(16).substr(1); - _hexToByte[_byteToHex[i]] = i; - } - - // **`parse()` - Parse a UUID into it's component bytes** - function parse(s, buf, offset) { - var i = buf && offset || 0, - ii = 0; - - buf = buf || []; - s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) { - if (ii < 16) { - // Don't overflow! - buf[i + ii++] = _hexToByte[oct]; - } - }); - - // Zero out remaining bytes if string was short - while (ii < 16) { - buf[i + ii++] = 0; - } - - return buf; - } - - // **`unparse()` - Convert UUID byte array (ala parse()) into a string** - function unparse(buf, offset) { - var i = offset || 0, - bth = _byteToHex; - return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]]; - } - - // **`v1()` - Generate time-based UUID** - // - // Inspired by https://github.com/LiosK/UUID.js - // and http://docs.python.org/library/uuid.html - - // random #'s we need to init node and clockseq - var _seedBytes = _rng(); - - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) - var _nodeId = [_seedBytes[0] | 1, _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]]; - - // Per 4.2.2, randomize (14 bit) clockseq - var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 16383; - - // Previous uuid creation time - var _lastMSecs = 0, - _lastNSecs = 0; - - // See https://github.com/broofa/node-uuid for API details - function v1(options, buf, offset) { - var i = buf && offset || 0; - var b = buf || []; - - options = options || {}; - - var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; - - // UUID timestamps are 100 nano-second units since the Gregorian epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. - var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); - - // Per 4.2.1.2, use count of uuid's generated during the current clock - // cycle to simulate higher resolution clock - var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; - - // Time since last uuid creation (in msecs) - var dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; - - // Per 4.2.1.2, Bump clockseq on clock regression - if (dt < 0 && options.clockseq === undefined) { - clockseq = clockseq + 1 & 16383; - } - - // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new - // time interval - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { - nsecs = 0; - } - - // Per 4.2.1.2 Throw error if too many uuids are requested - if (nsecs >= 10000) { - throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); - } - - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; - - // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - msecs += 12219292800000; - - // `time_low` - var tl = ((msecs & 268435455) * 10000 + nsecs) % 4294967296; - b[i++] = tl >>> 24 & 255; - b[i++] = tl >>> 16 & 255; - b[i++] = tl >>> 8 & 255; - b[i++] = tl & 255; - - // `time_mid` - var tmh = msecs / 4294967296 * 10000 & 268435455; - b[i++] = tmh >>> 8 & 255; - b[i++] = tmh & 255; - - // `time_high_and_version` - b[i++] = tmh >>> 24 & 15 | 16; // include version - b[i++] = tmh >>> 16 & 255; - - // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - b[i++] = clockseq >>> 8 | 128; - - // `clock_seq_low` - b[i++] = clockseq & 255; - - // `node` - var node = options.node || _nodeId; - for (var n = 0; n < 6; n++) { - b[i + n] = node[n]; - } - - return buf ? buf : unparse(b); - } - - // **`v4()` - Generate random UUID** - - // See https://github.com/broofa/node-uuid for API details - function v4(options, buf, offset) { - // Deprecated - 'format' argument, as supported in v1.2 - var i = buf && offset || 0; - - if (typeof options == 'string') { - buf = options == 'binary' ? new Array(16) : null; - options = null; - } - options = options || {}; - - var rnds = options.random || (options.rng || _rng)(); - - // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - rnds[6] = rnds[6] & 15 | 64; - rnds[8] = rnds[8] & 63 | 128; - - // Copy bytes to buffer, if provided - if (buf) { - for (var ii = 0; ii < 16; ii++) { - buf[i + ii] = rnds[ii]; - } - } - - return buf || unparse(rnds); - } - - // Export public API - var uuid = v4; - uuid.v1 = v1; - uuid.v4 = v4; - uuid.parse = parse; - uuid.unparse = unparse; - - module.exports = uuid; - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - /***/ } /******/ ]) }); diff --git a/docs/network/physics.html b/docs/network/physics.html index 14552d66..08094806 100644 --- a/docs/network/physics.html +++ b/docs/network/physics.html @@ -90,7 +90,8 @@ var options = { centralGravity: 0.3, springLength: 95, springConstant: 0.04, - damping: 0.09 + damping: 0.09, + avoidOverlap: false }, forceAtlas2Based: { theta: 0.5, @@ -98,14 +99,16 @@ var options = { centralGravity: 0.01, springConstant: 0.08, springLength: 100, - damping: 0.4 + damping: 0.4, + avoidOverlap: false }, repulsion: { centralGravity: 0.2, springLength: 200, springConstant: 0.05, nodeDistance: 100, - damping: 0.09 + damping: 0.09, + avoidOverlap: false }, hierarchicalRepulsion: { centralGravity: 0.0, @@ -149,6 +152,7 @@ network.setOptions(options); barnesHut.springLength Number 95 The edges are modelled as springs. This springLength here is the the rest length of the spring. barnesHut.springConstant Number 0.04 This is how 'sturdy' the springs are. Higher values mean stronger springs. barnesHut.damping Number 0.09 Accepted range: [0 .. 1]. The damping factor is how much of the velocity from the previous physics simulation iteration carries over to the next iteration. + barnesHut.avoidOverlap Number 0 Accepted range: [0 .. 1]. When larger than 0, the size of the node is taken into account. The distance will be calculated from the radius of the encompassing circle of the node for both the gravity model and the spring model. Value 1 is maximum overlap avoidance. forceAtlas2Based Object Object Force Atlas 2 has been developed by Jacomi et al (2014) for use with Gephi. The forceAtlas2Based solver makes use of some of the equations provided by them and makes use of the barnesHut implementation in vis. The main differences are the central gravity model, @@ -159,6 +163,7 @@ network.setOptions(options); forceAtlas2Based.springLength Number 100 The edges are modelled as springs. This springLength here is the the rest length of the spring. forceAtlas2Based.springConstant Number 0.08 This is how 'sturdy' the springs are. Higher values mean stronger springs. forceAtlas2Based.damping Number 0.4 Accepted range: [0 .. 1]. The damping factor is how much of the velocity from the previous physics simulation iteration carries over to the next iteration. + forceAtlas2Based.avoidOverlap Number 0 Accepted range: [0 .. 1]. When larger than 0, the size of the node is taken into account. The distance will be calculated from the radius of the encompassing circle of the node for both the gravity model and the spring model. Value 1 is maximum overlap avoidance. repulsion Object Object The repulsion model assumes nodes have a simplified repulsion field around them. It's force linearly decreases from 1 (at 0.5*nodeDistance and smaller) to 0 (at 2*nodeDistance). repulsion.nodeDistance Number 100 This is the range of influence for the repulsion. @@ -166,6 +171,7 @@ network.setOptions(options); repulsion.springLength Number 200 The edges are modelled as springs. This springLength here is the the rest length of the spring. repulsion.springConstant Number 0.05 This is how 'sturdy' the springs are. Higher values mean stronger springs. repulsion.damping Number 0.09 Accepted range: [0 .. 1]. The damping factor is how much of the velocity from the previous physics simulation iteration carries over to the next iteration. + repulsion.avoidOverlap Number 0 Accepted range: [0 .. 1]. When larger than 0, the size of the node is taken into account. The distance will be calculated from the radius of the encompassing circle of the node for the spring model. Value 1 is maximum overlap avoidance. hierarchicalRepulsion Object Object This model is based on the repulsion solver but the levels are taken into account and the forces are normalized. hierarchicalRepulsion.nodeDistance Number 120 This is the range of influence for the repulsion. diff --git a/examples/network/categories/02_random_nodes.html b/examples/network/categories/02_random_nodes.html index 0c9db9af..550b988a 100644 --- a/examples/network/categories/02_random_nodes.html +++ b/examples/network/categories/02_random_nodes.html @@ -14,8 +14,8 @@ } - - + + - +

diff --git a/examples/network/categories/28_world_cup_network_performance.html b/examples/network/categories/28_world_cup_network_performance.html index c8bccb42..d0d98f3c 100644 --- a/examples/network/categories/28_world_cup_network_performance.html +++ b/examples/network/categories/28_world_cup_network_performance.html @@ -5,10 +5,10 @@ Network | Static smooth curves - World Cup Network - - + + - + - + -

Labels can be aligned to edges in various ways.

+

Labels of edges can be aligned to edges in various ways.
Label alignment for nodes (top, bottom, left, right, inside) is planned but not in vis yet.

@@ -34,10 +37,10 @@ // create an array with edges var edges = [ - {from: 1, to: 2, label: 'middle', font: {align:'middle', background:'orange'}}, - {from: 1, to: 3, label: 'top', font: {align: 'top', background:'green'}}, - {from: 2, to: 4, label: 'horizontal', font: {align: 'horizontal', background: 'red'}}, - {from: 2, to: 5, label: 'bottom', font: { align:'bottom', background: '#ccd' }} + {from: 1, to: 2, label: 'middle', font: {align: 'middle'}}, + {from: 1, to: 3, label: 'top', font: {align: 'top'}}, + {from: 2, to: 4, label: 'horizontal', font: {align: 'horizontal'}}, + {from: 2, to: 5, label: 'bottom', font: {align: 'bottom'}} ]; // create a network @@ -46,11 +49,7 @@ nodes: nodes, edges: edges }; - var options = { - edges: { - font: {stroke: 0} - } - }; + var options = {}; var network = new vis.Network(container, data, options); diff --git a/examples/network/categories/labels/label_background.html b/examples/network/categories/labels/label_background.html new file mode 100644 index 00000000..109fdef6 --- /dev/null +++ b/examples/network/categories/labels/label_background.html @@ -0,0 +1,57 @@ + + + + Network | Label alignment + + + + + + + + + + +

Labels can have any color background.

+ +
+ + + + + diff --git a/examples/network/categories/labels/label_color_and_size.html b/examples/network/categories/labels/label_color_and_size.html new file mode 100644 index 00000000..7fc56c88 --- /dev/null +++ b/examples/network/categories/labels/label_color_and_size.html @@ -0,0 +1,61 @@ + + + + Network | Label stroke + + + + + + + + +

The style of the edges can be fully customized.

+ +
+ + + + + diff --git a/examples/network/categories/35_label_stroke.html b/examples/network/categories/labels/label_stroke.html similarity index 70% rename from examples/network/categories/35_label_stroke.html rename to examples/network/categories/labels/label_stroke.html index 65e0a902..997924ae 100644 --- a/examples/network/categories/35_label_stroke.html +++ b/examples/network/categories/labels/label_stroke.html @@ -2,23 +2,25 @@ Network | Label stroke - - - + + - + -

The font, size, and stroke of labels is fully customizable.

+

The stroke of labels is fully can have a width and color. Edgelabels by default have a white stroke for clarity.

diff --git a/examples/network/categories/nodeStyles/colors.html b/examples/network/categories/nodeStyles/colors.html index e57af215..0868b650 100644 --- a/examples/network/categories/nodeStyles/colors.html +++ b/examples/network/categories/nodeStyles/colors.html @@ -12,6 +12,10 @@ height: 400px; border: 1px solid lightgray; } + + p { + max-width:700px; + } @@ -26,12 +30,12 @@ diff --git a/examples/network/categories/nodeStyles/icons.html b/examples/network/categories/nodeStyles/icons.html index e9d1aca7..d55f892d 100644 --- a/examples/network/categories/nodeStyles/icons.html +++ b/examples/network/categories/nodeStyles/icons.html @@ -15,6 +15,12 @@ #mynetworkFA, #mynetworkIO { height: 300px; + width: 700px; + border:1px solid lightgrey; + } + + p { + max-width:700px; } @@ -170,13 +176,19 @@ - +

+Icons can be used for nodes as well. This example shows Icons from fontAwesome and Ionicons but it should work with similar packages as well. + It uses unicode and css to define the icons.

Remember! Unicode in javascript is done like this: \uf274 for the unicode f274. +
If a node is shown as a rectangle, it means the css is not loaded (or not yet loaded). A redraw will fix that. + +

+

- Use FontAwesome-icons for node

+ Use FontAwesome-icons for nodes

- Use Ionicons-icons for node

+ Use Ionicons-icons for nodes
diff --git a/lib/network/Network.js b/lib/network/Network.js index 916ac444..00f5f28c 100644 --- a/lib/network/Network.js +++ b/lib/network/Network.js @@ -260,7 +260,7 @@ Network.prototype.bindEventListeners = function () { this.body.emitter.on("_dataChanged", () => { // update shortcut lists this._updateVisibleIndices(); - this.physics.updatePhysicsIndices(); + this.physics.updatePhysicsData(); // call the dataUpdated event because the only difference between the two is the updating of the indices this.body.emitter.emit("_dataUpdated"); diff --git a/lib/network/modules/CanvasRenderer.js b/lib/network/modules/CanvasRenderer.js index 6cd438b7..ac2b8ca4 100644 --- a/lib/network/modules/CanvasRenderer.js +++ b/lib/network/modules/CanvasRenderer.js @@ -36,6 +36,7 @@ class CanvasRenderer { this.dragging = true; }); this.body.emitter.on("dragEnd", () => this.dragging = false); + this.body.emitter.on("_resizeNodes", () => this._resizeNodes()); this.body.emitter.on("_redraw", () => { if (this.renderingActive === false) { this._redraw(); @@ -194,6 +195,43 @@ class CanvasRenderer { } + /** + * Redraw all nodes + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @param {Boolean} [alwaysShow] + * @private + */ + _resizeNodes() { + let ctx = this.canvas.frame.canvas.getContext('2d'); + if (this.pixelRatio === undefined) { + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || + ctx.mozBackingStorePixelRatio || + ctx.msBackingStorePixelRatio || + ctx.oBackingStorePixelRatio || + ctx.backingStorePixelRatio || 1); + } + ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + ctx.save(); + ctx.translate(this.body.view.translation.x, this.body.view.translation.y); + ctx.scale(this.body.view.scale, this.body.view.scale); + + let nodes = this.body.nodes; + let node; + + // resize all nodes + for (let nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + node = nodes[nodeId]; + node.resize(ctx); + node.updateBoundingBox(ctx); + } + } + + // restore original scaling and translation + ctx.restore(); + } + /** * Redraw all nodes * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); diff --git a/lib/network/modules/LayoutEngine.js b/lib/network/modules/LayoutEngine.js index 2779493d..8039c2e8 100644 --- a/lib/network/modules/LayoutEngine.js +++ b/lib/network/modules/LayoutEngine.js @@ -134,7 +134,6 @@ class LayoutEngine { if ((!node.isFixed()) && (node.x === undefined || node.y === undefined)) { let radius = 10 * 0.1 * nodesArray.length + 10; let angle = 2 * Math.PI * this.seededRandom(); - if (node.options.fixed.x === false) { node.x = radius * Math.cos(angle); } diff --git a/lib/network/modules/PhysicsEngine.js b/lib/network/modules/PhysicsEngine.js index 20c92170..b3f8f886 100644 --- a/lib/network/modules/PhysicsEngine.js +++ b/lib/network/modules/PhysicsEngine.js @@ -35,7 +35,8 @@ class PhysicsEngine { centralGravity: 0.3, springLength: 95, springConstant: 0.04, - damping: 0.09 + damping: 0.09, + avoidOverlap: 0 }, forceAtlas2Based: { theta: 0.5, @@ -43,14 +44,16 @@ class PhysicsEngine { centralGravity: 0.01, springConstant: 0.08, springLength: 100, - damping: 0.4 + damping: 0.4, + avoidOverlap: 0 }, repulsion: { centralGravity: 0.2, springLength: 200, springConstant: 0.05, nodeDistance: 100, - damping: 0.09 + damping: 0.09, + avoidOverlap: 0 }, hierarchicalRepulsion: { centralGravity: 0.0, @@ -159,7 +162,6 @@ class PhysicsEngine { else { this.ready = true; this.body.emitter.emit('fit'); - } } @@ -169,6 +171,10 @@ class PhysicsEngine { startSimulation() { if (this.physicsEnabled === true) { this.stabilized = false; + + // this sets the width of all nodes initially which could be required for the avoidOverlap + this.body.emitter.emit("_resizeNodes"); + if (this.viewFunction === undefined) { this.viewFunction = this.simulationStep.bind(this); this.body.emitter.on('initRedraw', this.viewFunction); @@ -273,7 +279,7 @@ class PhysicsEngine { * * @private */ - updatePhysicsIndices() { + updatePhysicsData() { this.physicsBody.forces = {}; this.physicsBody.physicsNodeIndices = []; this.physicsBody.physicsEdgeIndices = []; @@ -478,6 +484,9 @@ class PhysicsEngine { iterations = this.options.stabilization.iterations; } + // this sets the width of all nodes initially which could be required for the avoidOverlap + this.body.emitter.emit("_resizeNodes"); + // stop the render loop this.stopSimulation(); diff --git a/lib/network/modules/View.js b/lib/network/modules/View.js index 70c426a4..68464b40 100644 --- a/lib/network/modules/View.js +++ b/lib/network/modules/View.js @@ -125,7 +125,7 @@ class View { zoomLevel *= factor; } else { - this.body.emitter.emit("_redraw", true); + this.body.emitter.emit("_resizeNodes"); range = this._getRange(options.nodes); var xDistance = Math.abs(range.maxX - range.minX) * 1.1; var yDistance = Math.abs(range.maxY - range.minY) * 1.1; diff --git a/lib/network/modules/components/Edge.js b/lib/network/modules/components/Edge.js index f8f78495..9e542539 100644 --- a/lib/network/modules/components/Edge.js +++ b/lib/network/modules/components/Edge.js @@ -90,7 +90,6 @@ class Edge { static parseOptions(parentOptions, newOptions, allowDeletion = false) { var fields = [ 'id', - 'font', 'from', 'hidden', 'hoverWidth', diff --git a/lib/network/modules/components/Node.js b/lib/network/modules/components/Node.js index 6f5b8472..95cd7cb9 100644 --- a/lib/network/modules/components/Node.js +++ b/lib/network/modules/components/Node.js @@ -162,6 +162,7 @@ class Node { static parseOptions(parentOptions, newOptions, allowDeletion = false) { var fields = [ 'color', + 'font', 'fixed', 'shadow' ]; @@ -194,6 +195,10 @@ class Node { } } } + + if (newOptions.font !== undefined) { + Label.parseOptions(parentOptions.font, newOptions); + } } updateLabelModule() { @@ -368,6 +373,7 @@ class Node { this.shape.draw(ctx, this.x, this.y, this.selected, this.hover); } + /** * Update the bounding box of the shape */ diff --git a/lib/network/modules/components/nodes/shapes/Box.js b/lib/network/modules/components/nodes/shapes/Box.js index 59d9e5eb..ef48b73d 100644 --- a/lib/network/modules/components/nodes/shapes/Box.js +++ b/lib/network/modules/components/nodes/shapes/Box.js @@ -13,6 +13,7 @@ class Box extends NodeBase { let textSize = this.labelModule.getTextSize(ctx,selected); this.width = textSize.width + 2 * margin; this.height = textSize.height + 2 * margin; + this.radius = 0.5*this.width; } } diff --git a/lib/network/modules/components/nodes/shapes/Circle.js b/lib/network/modules/components/nodes/shapes/Circle.js index 3c093a02..3bfb828f 100644 --- a/lib/network/modules/components/nodes/shapes/Circle.js +++ b/lib/network/modules/components/nodes/shapes/Circle.js @@ -16,6 +16,7 @@ class Circle extends CircleImageBase { this.width = diameter; this.height = diameter; + this.radius = 0.5*this.width; } } diff --git a/lib/network/modules/components/nodes/shapes/CircularImage.js b/lib/network/modules/components/nodes/shapes/CircularImage.js index 3f009ed9..d7c510ca 100644 --- a/lib/network/modules/components/nodes/shapes/CircularImage.js +++ b/lib/network/modules/components/nodes/shapes/CircularImage.js @@ -17,6 +17,7 @@ class CircularImage extends CircleImageBase { this.width = diameter; this.height = diameter; this._swapToImageResizeWhenImageLoaded = true; + this.radius = 0.5*this.width; } } else { diff --git a/lib/network/modules/components/nodes/shapes/Database.js b/lib/network/modules/components/nodes/shapes/Database.js index 2cc8e9c6..f5cc6f78 100644 --- a/lib/network/modules/components/nodes/shapes/Database.js +++ b/lib/network/modules/components/nodes/shapes/Database.js @@ -14,6 +14,7 @@ class Database extends NodeBase { var size = textSize.width + 2 * margin; this.width = size; this.height = size; + this.radius = 0.5*this.width; } } diff --git a/lib/network/modules/components/nodes/shapes/Ellipse.js b/lib/network/modules/components/nodes/shapes/Ellipse.js index 4fb9c644..480dae27 100644 --- a/lib/network/modules/components/nodes/shapes/Ellipse.js +++ b/lib/network/modules/components/nodes/shapes/Ellipse.js @@ -16,6 +16,7 @@ class Ellipse extends NodeBase { if (this.width < this.height) { this.width = this.height; } + this.radius = 0.5*this.width; } } diff --git a/lib/network/modules/components/nodes/shapes/Empty.js b/lib/network/modules/components/nodes/shapes/Empty.js deleted file mode 100644 index 5b27e5c4..00000000 --- a/lib/network/modules/components/nodes/shapes/Empty.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -import NodeBase from '../util/NodeBase' - -class Empty extends NodeBase { - constructor (options, body, labelModule) { - super(options, body, labelModule); - } - - setOptions() {} - - resize() {} - - draw() {} - - distanceToBorder() {} - - updateBoundingBox() {}} - - -export default Empty; \ No newline at end of file diff --git a/lib/network/modules/components/nodes/shapes/Icon.js b/lib/network/modules/components/nodes/shapes/Icon.js index 200176ca..b1a0e150 100644 --- a/lib/network/modules/components/nodes/shapes/Icon.js +++ b/lib/network/modules/components/nodes/shapes/Icon.js @@ -16,6 +16,7 @@ class Icon extends NodeBase { }; this.width = iconSize.width + 2 * margin; this.height = iconSize.height + 2 * margin; + this.radius = 0.5*this.width; } } diff --git a/lib/network/modules/components/nodes/shapes/Text.js b/lib/network/modules/components/nodes/shapes/Text.js index 7b6a3be2..f649dcba 100644 --- a/lib/network/modules/components/nodes/shapes/Text.js +++ b/lib/network/modules/components/nodes/shapes/Text.js @@ -13,6 +13,7 @@ class Text extends NodeBase { var textSize = this.labelModule.getTextSize(ctx,selected); this.width = textSize.width + 2 * margin; this.height = textSize.height + 2 * margin; + this.radius = 0.5*this.width; } } diff --git a/lib/network/modules/components/nodes/util/CircleImageBase.js b/lib/network/modules/components/nodes/util/CircleImageBase.js index b075b8ed..bff9e6dc 100644 --- a/lib/network/modules/components/nodes/util/CircleImageBase.js +++ b/lib/network/modules/components/nodes/util/CircleImageBase.js @@ -25,6 +25,7 @@ class CircleImageBase extends NodeBase { } this.width = width; this.height = height; + this.radius = 0.5*this.width; } } diff --git a/lib/network/modules/components/nodes/util/NodeBase.js b/lib/network/modules/components/nodes/util/NodeBase.js index 954a17b2..b718a7f1 100644 --- a/lib/network/modules/components/nodes/util/NodeBase.js +++ b/lib/network/modules/components/nodes/util/NodeBase.js @@ -6,6 +6,8 @@ class NodeBase { this.top = undefined; this.left = undefined; this.height = undefined; + this.width = undefined; + this.radius = undefined; this.boundingBox = {top: 0, left: 0, right: 0, bottom: 0}; } diff --git a/lib/network/modules/components/nodes/util/ShapeBase.js b/lib/network/modules/components/nodes/util/ShapeBase.js index 82cd86ba..8e635f2e 100644 --- a/lib/network/modules/components/nodes/util/ShapeBase.js +++ b/lib/network/modules/components/nodes/util/ShapeBase.js @@ -10,6 +10,7 @@ class ShapeBase extends NodeBase { var size = 2 * this.options.size; this.width = size; this.height = size; + this.radius = 0.5*this.width; } } diff --git a/lib/network/modules/components/physics/BarnesHutSolver.js b/lib/network/modules/components/physics/BarnesHutSolver.js index 447e4cca..e18a0d4b 100644 --- a/lib/network/modules/components/physics/BarnesHutSolver.js +++ b/lib/network/modules/components/physics/BarnesHutSolver.js @@ -9,7 +9,8 @@ class BarnesHutSolver { setOptions(options) { this.options = options; - this.thetaInversed = 1/ this.options.theta; + this.thetaInversed = 1 / this.options.theta; + this.overlapAvoidanceFactor = 1 - Math.max(0, Math.min(1,this.options.avoidOverlap)); // if 1 then min distance = 0.5, if 0.5 then min distance = 0.5 + 0.5*node.shape.radius } @@ -104,6 +105,11 @@ class BarnesHutSolver { distance = 0.1 * Math.random(); dx = distance; } + + if (this.overlapAvoidanceFactor < 1) { + distance = Math.max(0.1 + (this.overlapAvoidanceFactor * node.shape.radius), distance - node.shape.radius); + } + // the dividing by the distance cubed instead of squared allows us to get the fx and fy components without sines and cosines // it is shorthand for gravityforce with distance squared and fx = dx/distance * gravityForce let gravityForce = this.options.gravitationalConstant * parentBranch.mass * node.options.mass / Math.pow(distance,3); diff --git a/lib/network/modules/components/physics/FA2BasedRepulsionSolver.js b/lib/network/modules/components/physics/FA2BasedRepulsionSolver.js index 786ce392..24fe2742 100644 --- a/lib/network/modules/components/physics/FA2BasedRepulsionSolver.js +++ b/lib/network/modules/components/physics/FA2BasedRepulsionSolver.js @@ -20,6 +20,11 @@ class ForceAtlas2BasedRepulsionSolver extends BarnesHutSolver { distance = 0.1 * Math.random(); dx = distance; } + + if (this.overlapAvoidanceFactor < 1) { + distance = Math.max(0.1 + (this.overlapAvoidanceFactor * node.shape.radius), distance - node.shape.radius); + } + let degree = (node.edges.length + 1); // the dividing by the distance cubed instead of squared allows us to get the fx and fy components without sines and cosines // it is shorthand for gravityforce with distance squared and fx = dx/distance * gravityForce diff --git a/lib/network/modules/components/physics/SpringSolver.js b/lib/network/modules/components/physics/SpringSolver.js index 14bd4292..5998823a 100644 --- a/lib/network/modules/components/physics/SpringSolver.js +++ b/lib/network/modules/components/physics/SpringSolver.js @@ -7,6 +7,8 @@ class SpringSolver { setOptions(options) { this.options = options; + this.overlapAvoidanceFactor = 1 - Math.max(0, Math.min(1,this.options.avoidOverlap)); // if 1 then min distance = 0.5, if 0.5 then min distance = 0.5 + 0.5*node.shape.radius + } /** @@ -56,8 +58,17 @@ class SpringSolver { * @private */ _calculateSpringForce(node1, node2, edgeLength) { - let dx = (node1.x - node2.x); - let dy = (node1.y - node2.y); + let dx,dy; + if (this.overlapAvoidanceFactor < 1) { + let nodesWidth = this.overlapAvoidanceFactor * (node1.shape.radius + node2.shape.radius); + dx = (node1.x - node2.x) - nodesWidth; + dy = (node1.y - node2.y) - nodesWidth; + } + else { + dx = (node1.x - node2.x); + dy = (node1.y - node2.y); + } + let distance = Math.sqrt(dx * dx + dy * dy); distance = distance === 0 ? 0.01 : distance; diff --git a/lib/network/modules/components/shared/Label.js b/lib/network/modules/components/shared/Label.js index 89961bf5..47c19c4f 100644 --- a/lib/network/modules/components/shared/Label.js +++ b/lib/network/modules/components/shared/Label.js @@ -92,7 +92,7 @@ class Label { ctx.fillRect(-this.size.width * 0.5, lineMargin, this.size.width, this.size.height); break; default: - ctx.fillRect(this.size.left, this.size.top, this.size.width, this.size.height); + ctx.fillRect(this.size.left, this.size.top - 0.5*lineMargin, this.size.width, this.size.height); break; } } diff --git a/lib/network/options.js b/lib/network/options.js index c47c15b6..ddbb37d3 100644 --- a/lib/network/options.js +++ b/lib/network/options.js @@ -220,6 +220,7 @@ let allOptions = { springLength: {number}, springConstant: {number}, damping: {number}, + avoidOverlap: {number}, __type__: {object} }, forceAtlas2Based: { @@ -228,6 +229,7 @@ let allOptions = { springLength: {number}, springConstant: {number}, damping: {number}, + avoidOverlap: {number}, __type__: {object} }, repulsion: { @@ -236,6 +238,7 @@ let allOptions = { springConstant: {number}, nodeDistance: {number}, damping: {number}, + avoidOverlap: {number}, __type__: {object} }, hierarchicalRepulsion: { @@ -426,7 +429,8 @@ let configureOptions = { centralGravity: [0.3, 0, 10, 0.05], springLength: [95, 0, 500, 5], springConstant: [0.04, 0, 5, 0.005], - damping: [0.09, 0, 1, 0.01] + damping: [0.09, 0, 1, 0.01], + avoidOverlap: [0, 0, 1, 0.01] }, forceAtlas2Based: { //theta: [0.5, 0.1, 1, 0.05], @@ -434,14 +438,16 @@ let configureOptions = { centralGravity: [0.01, 0, 1, 0.005], springLength: [95, 0, 500, 5], springConstant: [0.08, 0, 5, 0.005], - damping: [0.4, 0, 1, 0.01] + damping: [0.4, 0, 1, 0.01], + avoidOverlap: [0, 0, 1, 0.01] }, repulsion: { centralGravity: [0.2, 0, 10, 0.05], springLength: [200, 0, 500, 5], springConstant: [0.05, 0, 5, 0.005], nodeDistance: [100, 0, 500, 5], - damping: [0.09, 0, 1, 0.01] + damping: [0.09, 0, 1, 0.01], + avoidOverlap: [0, 0, 1, 0.01] }, hierarchicalRepulsion: { centralGravity: [0.2, 0, 10, 0.05], diff --git a/test/timeline_groups.html b/test/timeline_groups.html index c6592c54..6da7baa5 100644 --- a/test/timeline_groups.html +++ b/test/timeline_groups.html @@ -64,7 +64,7 @@ var names = ['John (0)', 'Alston (1)', 'Lee (2)', 'Grant (3)']; var groups = new vis.DataSet(); for (var g = 0; g < groupCount; g++) { - groups.add({id: g, content: names[g], title: 'Title of group ' + g, 'className': 'myGroup'}); + groups.add({id: g, content: '' + names[g] + '', title: 'Title of group ' + g, 'className': 'myGroup'}); } // create a dataset with items @@ -77,7 +77,7 @@ id: i, group: group, content: 'item ' + i + - ' (' + names[group] + ')', + ' (' + names[group] + ') ', start: start, end: end, title: 'Title for item ' + i,