highcharts 10.2.0 → 10.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bower.json +1 -1
- package/css/highcharts.css +10 -20
- package/css/themes/dark-unica.css +10 -20
- package/css/themes/grid-light.css +10 -20
- package/css/themes/sand-signika.css +10 -20
- package/es-modules/Accessibility/Accessibility.js +6 -0
- package/es-modules/Accessibility/Components/LegendComponent.js +8 -8
- package/es-modules/Accessibility/Components/SeriesComponent/SeriesDescriber.js +3 -2
- package/es-modules/Accessibility/Options/A11yDefaults.js +1 -1
- package/es-modules/Core/Axis/Axis.js +3 -0
- package/es-modules/Core/Axis/Axis3D.js +1 -1
- package/es-modules/Core/Axis/AxisDefaults.js +1 -1
- package/es-modules/Core/Axis/BrokenAxis.js +1 -1
- package/es-modules/Core/Axis/Color/ColorAxisDefaults.js +4 -0
- package/es-modules/Core/Axis/NavigatorAxis.js +2 -2
- package/es-modules/Core/Axis/OrdinalAxis.js +2 -2
- package/es-modules/Core/Axis/RadialAxis.js +1 -1
- package/es-modules/Core/Axis/Stacking/StackItem.js +262 -0
- package/es-modules/Core/Axis/Stacking/StackingAxis.js +468 -0
- package/es-modules/Core/Axis/TreeGrid/TreeGridAxis.js +732 -0
- package/es-modules/Core/Axis/TreeGrid/TreeGridTick.js +313 -0
- package/es-modules/Core/Axis/WaterfallAxis.js +1 -1
- package/es-modules/Core/Axis/ZAxis.js +73 -70
- package/es-modules/Core/Chart/Chart.js +16 -2
- package/es-modules/Core/Chart/Chart3D.js +2 -2
- package/es-modules/Core/Chart/ChartDefaults.js +151 -2
- package/es-modules/Core/Chart/StockChart.js +5 -3
- package/es-modules/Core/DefaultOptions.js +2 -1
- package/es-modules/Core/Geometry/CircleUtilities.js +4 -4
- package/es-modules/Core/Globals.js +2 -1
- package/es-modules/{Extensions → Core}/Math3D.js +48 -43
- package/es-modules/Core/Navigator.js +24 -7
- package/es-modules/Core/Pointer.js +7 -9
- package/es-modules/Core/Renderer/HTML/AST.js +4 -1
- package/es-modules/Core/Renderer/SVG/SVGElement.js +103 -163
- package/es-modules/Core/Renderer/SVG/SVGLabel.js +29 -27
- package/es-modules/Core/Renderer/SVG/SVGRenderer.js +3 -3
- package/es-modules/Core/Renderer/SVG/SVGRenderer3D.js +1 -1
- package/es-modules/Core/Renderer/SVG/TextBuilder.js +5 -3
- package/es-modules/Core/Scrollbar.js +3 -1
- package/es-modules/Core/Series/DataLabel.js +8 -6
- package/es-modules/Core/Series/Point.js +2 -2
- package/es-modules/Core/Series/Series.js +36 -31
- package/es-modules/Core/Series/Series3D.js +1 -1
- package/es-modules/Core/Series/SeriesDefaults.js +8 -3
- package/es-modules/Core/Series/SeriesRegistry.js +6 -29
- package/es-modules/Core/Tooltip.js +14 -3
- package/es-modules/Core/Utilities.js +1 -3
- package/es-modules/Data/DataConverter.js +5 -0
- package/es-modules/Data/DataPromise.js +1 -1
- package/es-modules/Data/DataSeriesComposition.js +288 -0
- package/es-modules/Data/DataSeriesConverter.js +1 -1
- package/es-modules/Data/DataTable.js +2 -2
- package/es-modules/Data/Modifiers/ChainModifier.js +1 -1
- package/es-modules/Data/Modifiers/DataModifier.js +1 -1
- package/es-modules/Data/Modifiers/GroupModifier.js +1 -1
- package/es-modules/Data/Modifiers/InvertModifier.js +1 -1
- package/es-modules/Data/Modifiers/RangeModifier.js +1 -1
- package/es-modules/Data/Modifiers/SeriesPointsModifier.js +1 -1
- package/es-modules/Data/Modifiers/SortModifier.js +1 -1
- package/es-modules/Data/Parsers/DataParser.js +1 -1
- package/es-modules/Data/Stores/DataStore.js +1 -1
- package/es-modules/Extensions/Annotations/Annotation.js +347 -1156
- package/es-modules/Extensions/Annotations/AnnotationChart.js +291 -0
- package/es-modules/Extensions/Annotations/AnnotationDefaults.js +624 -0
- package/es-modules/Extensions/Annotations/ControlPoint.js +89 -64
- package/es-modules/Extensions/Annotations/{Mixins/ControllableMixin.js → Controllables/Controllable.js} +300 -241
- package/es-modules/Extensions/Annotations/Controllables/ControllableCircle.js +63 -50
- package/es-modules/Extensions/Annotations/Controllables/ControllableDefaults.js +95 -0
- package/es-modules/Extensions/Annotations/Controllables/ControllableEllipse.js +90 -61
- package/es-modules/Extensions/Annotations/Controllables/ControllableImage.js +50 -44
- package/es-modules/Extensions/Annotations/Controllables/ControllableLabel.js +95 -78
- package/es-modules/Extensions/Annotations/Controllables/ControllablePath.js +167 -51
- package/es-modules/Extensions/Annotations/Controllables/ControllableRect.js +53 -52
- package/es-modules/Extensions/Annotations/{Mixins/EventEmitterMixin.js → EventEmitter.js} +136 -116
- package/es-modules/Extensions/Annotations/MockPoint.js +210 -145
- package/es-modules/Extensions/Annotations/NavigationBindings.js +272 -674
- package/es-modules/Extensions/Annotations/NavigationBindingsDefaults.js +396 -0
- package/es-modules/Extensions/Annotations/NavigationBindingsUtilities.js +98 -0
- package/es-modules/Extensions/Annotations/Popup/Popup.js +295 -0
- package/es-modules/Extensions/Annotations/Popup/PopupAnnotations.js +177 -0
- package/es-modules/Extensions/Annotations/Popup/PopupComposition.js +81 -0
- package/es-modules/Extensions/Annotations/Popup/PopupIndicators.js +609 -0
- package/es-modules/Extensions/Annotations/Popup/PopupTabs.js +134 -0
- package/es-modules/Extensions/Annotations/Types/BasicAnnotation.js +10 -14
- package/es-modules/Extensions/Annotations/Types/CrookedLine.js +11 -19
- package/es-modules/Extensions/Annotations/Types/ElliottWave.js +10 -10
- package/es-modules/Extensions/Annotations/Types/Fibonacci.js +28 -20
- package/es-modules/Extensions/Annotations/Types/FibonacciTimeZones.js +63 -63
- package/es-modules/Extensions/Annotations/Types/InfinityLine.js +10 -19
- package/es-modules/Extensions/Annotations/Types/Measure.js +255 -249
- package/es-modules/Extensions/Annotations/Types/Pitchfork.js +11 -17
- package/es-modules/Extensions/Annotations/Types/TimeCycles.js +20 -17
- package/es-modules/Extensions/Annotations/Types/Tunnel.js +12 -13
- package/es-modules/Extensions/Annotations/Types/VerticalLine.js +11 -15
- package/es-modules/Extensions/Boost/Boost.js +320 -15
- package/es-modules/Extensions/Boost/BoostChart.js +245 -0
- package/es-modules/Extensions/Boost/BoostSeries.js +927 -0
- package/es-modules/Extensions/Boost/BoostableMap.js +21 -5
- package/es-modules/Extensions/Boost/Boostables.js +13 -2
- package/es-modules/Extensions/Boost/NamedColors.js +15 -6
- package/es-modules/Extensions/Boost/WGLDrawMode.js +36 -0
- package/es-modules/Extensions/Boost/WGLRenderer.js +288 -295
- package/es-modules/Extensions/Boost/WGLShader.js +370 -376
- package/es-modules/Extensions/Boost/WGLVertexBuffer.js +192 -0
- package/es-modules/Extensions/BoostCanvas.js +62 -46
- package/es-modules/Extensions/Breadcrumbs.js +4 -0
- package/es-modules/Extensions/DataGrouping.js +65 -27
- package/es-modules/Extensions/Debugger/Debugger.js +60 -22
- package/es-modules/Extensions/DraggablePoints.js +4 -3
- package/es-modules/Extensions/Drilldown.js +7 -8
- package/es-modules/Extensions/{ExportData.js → ExportData/ExportData.js} +341 -530
- package/es-modules/Extensions/ExportData/ExportDataDefaults.js +272 -0
- package/es-modules/Extensions/Exporting/Exporting.js +5 -1
- package/es-modules/Extensions/Exporting/ExportingDefaults.js +3 -1
- package/es-modules/Extensions/{FullScreen.js → Exporting/Fullscreen.js} +72 -27
- package/es-modules/Extensions/MarkerClusters.js +2 -0
- package/es-modules/Extensions/OfflineExporting/OfflineExportingDefaults.js +1 -1
- package/es-modules/Extensions/Oldie/Oldie.js +1 -1
- package/es-modules/Extensions/ParallelCoordinates.js +11 -7
- package/es-modules/Extensions/ScrollablePlotArea.js +1 -1
- package/es-modules/Extensions/SeriesLabel/SeriesLabel.js +2 -2
- package/es-modules/Extensions/Sonification/ChartSonify.js +1 -1
- package/es-modules/Maps/MapPointer.js +1 -1
- package/es-modules/Maps/MapView.js +2 -1
- package/es-modules/Series/{Area3DSeries.js → Area3D/Area3DSeries.js} +42 -20
- package/es-modules/Series/AreaRange/AreaRangeSeries.js +8 -2
- package/es-modules/Series/Bubble/BubbleLegendComposition.js +223 -231
- package/es-modules/Series/Bubble/BubbleLegendItem.js +46 -45
- package/es-modules/Series/Bubble/BubbleSeries.js +85 -66
- package/es-modules/Series/Column/ColumnSeries.js +2 -0
- package/es-modules/Series/Column3D/Column3DComposition.js +2 -2
- package/es-modules/Series/ColumnPyramid/ColumnPyramidSeries.js +1 -1
- package/es-modules/Series/Cylinder/CylinderComposition.js +1 -1
- package/es-modules/Series/DependencyWheel/DependencyWheelPoint.js +24 -11
- package/es-modules/Series/DependencyWheel/DependencyWheelSeries.js +16 -2
- package/es-modules/Series/DragNodesComposition.js +166 -0
- package/es-modules/Series/Funnel3D/Funnel3DSeries.js +1 -1
- package/es-modules/Series/Gantt/GanttSeries.js +1 -1
- package/es-modules/Series/GraphLayoutComposition.js +130 -0
- package/es-modules/Series/Heatmap/HeatmapSeries.js +5 -1
- package/es-modules/Series/Lollipop/LollipopPoint.js +21 -11
- package/es-modules/Series/Lollipop/LollipopSeries.js +15 -10
- package/es-modules/Series/Map/MapSeries.js +6 -1
- package/es-modules/Series/MapBubble/MapBubblePoint.js +15 -17
- package/es-modules/Series/MapBubble/MapBubbleSeries.js +19 -19
- package/es-modules/Series/Networkgraph/EulerIntegration.js +199 -0
- package/es-modules/Series/Networkgraph/NetworkgraphPoint.js +290 -0
- package/es-modules/Series/Networkgraph/NetworkgraphSeries.js +401 -0
- package/es-modules/Series/Networkgraph/NetworkgraphSeriesDefaults.js +545 -0
- package/es-modules/Series/Networkgraph/QuadTree.js +66 -272
- package/es-modules/Series/Networkgraph/QuadTreeNode.js +271 -0
- package/es-modules/Series/Networkgraph/{Layouts.js → ReingoldFruchtermanLayout.js} +240 -259
- package/es-modules/Series/Networkgraph/VerletIntegration.js +193 -0
- package/es-modules/Series/Organization/OrganizationSeries.js +9 -1
- package/es-modules/Series/PackedBubble/PackedBubbleIntegration.js +81 -0
- package/es-modules/Series/PackedBubble/{PackedBubbleComposition.js → PackedBubbleLayout.js} +114 -77
- package/es-modules/Series/PackedBubble/PackedBubblePoint.js +2 -2
- package/es-modules/Series/PackedBubble/PackedBubbleSeries.js +197 -570
- package/es-modules/Series/PackedBubble/PackedBubbleSeriesDefaults.js +394 -0
- package/es-modules/Series/Pie/PieSeries.js +3 -1
- package/es-modules/Series/PolarComposition.js +12 -12
- package/es-modules/Series/Sankey/SankeySeries.js +13 -1
- package/es-modules/Series/Scatter/ScatterSeries.js +4 -1
- package/es-modules/Series/Scatter3D/Scatter3DSeries.js +1 -1
- package/es-modules/Series/SeriesOnPointComposition.js +5 -1
- package/es-modules/Series/SolidGauge/SolidGaugeSeries.js +1 -1
- package/es-modules/Series/Sunburst/SunburstPoint.js +5 -6
- package/es-modules/Series/Sunburst/SunburstSeries.js +24 -2
- package/es-modules/Series/Timeline/TimelineSeries.js +2 -0
- package/es-modules/Series/Treemap/TreemapSeries.js +3 -3
- package/es-modules/Series/Vector/VectorSeries.js +2 -4
- package/es-modules/Series/Wordcloud/WordcloudSeries.js +1 -1
- package/es-modules/Series/Wordcloud/WordcloudUtils.js +1 -1
- package/es-modules/Series/XRange/XRangePoint.js +54 -45
- package/es-modules/Series/XRange/XRangeSeries.js +121 -273
- package/es-modules/Series/XRange/XRangeSeriesDefaults.js +211 -0
- package/es-modules/Stock/Indicators/ABands/ABandsIndicator.js +10 -2
- package/es-modules/Stock/Indicators/AD/ADIndicator.js +5 -0
- package/es-modules/Stock/Indicators/AO/AOIndicator.js +22 -11
- package/es-modules/Stock/Indicators/APO/APOIndicator.js +6 -1
- package/es-modules/Stock/Indicators/ATR/ATRIndicator.js +16 -3
- package/es-modules/Stock/Indicators/Aroon/AroonIndicator.js +15 -2
- package/es-modules/Stock/Indicators/AroonOscillator/AroonOscillatorIndicator.js +6 -2
- package/es-modules/Stock/Indicators/BB/BBIndicator.js +5 -1
- package/es-modules/Stock/Indicators/CCI/CCIIndicator.js +16 -3
- package/es-modules/Stock/Indicators/CMF/CMFIndicator.js +20 -0
- package/es-modules/Stock/Indicators/CMO/CMOIndicator.js +15 -1
- package/es-modules/Stock/Indicators/Chaikin/ChaikinIndicator.js +7 -2
- package/es-modules/Stock/Indicators/DEMA/DEMAIndicator.js +25 -0
- package/es-modules/Stock/Indicators/DMI/DMIIndicator.js +5 -0
- package/es-modules/Stock/Indicators/DPO/DPOIndicator.js +19 -8
- package/es-modules/Stock/Indicators/EMA/EMAIndicator.js +10 -0
- package/es-modules/Stock/Indicators/IKH/IKHIndicator.js +34 -15
- package/es-modules/Stock/Indicators/KeltnerChannels/KeltnerChannelsIndicator.js +25 -0
- package/es-modules/Stock/Indicators/Klinger/KlingerIndicator.js +12 -1
- package/es-modules/Stock/Indicators/LinearRegression/{LinearRegression.js → LinearRegressionIndicator.js} +11 -1
- package/es-modules/Stock/Indicators/LinearRegressionAngle/{LinearRegressionAngle.js → LinearRegressionAngleIndicator.js} +12 -7
- package/es-modules/Stock/Indicators/LinearRegressionIntercept/{LinearRegressionIntercept.js → LinearRegressionInterceptIndicator.js} +11 -1
- package/es-modules/Stock/Indicators/LinearRegressionSlopes/{LinearRegressionSlopes.js → LinearRegressionSlopesIndicator.js} +11 -1
- package/es-modules/Stock/Indicators/MACD/MACDIndicator.js +21 -10
- package/es-modules/Stock/Indicators/MFI/MFIIndicator.js +23 -10
- package/es-modules/Stock/Indicators/Momentum/MomentumIndicator.js +30 -2
- package/es-modules/Stock/Indicators/NATR/NATRIndicator.js +16 -1
- package/es-modules/Stock/Indicators/OBV/OBVIndicator.js +10 -0
- package/es-modules/Stock/Indicators/PC/PCIndicator.js +13 -8
- package/es-modules/Stock/Indicators/PPO/PPOIndicator.js +14 -4
- package/es-modules/Stock/Indicators/PSAR/PSARIndicator.js +16 -3
- package/es-modules/Stock/Indicators/PivotPoints/PivotPointsIndicator.js +16 -6
- package/es-modules/Stock/Indicators/PivotPoints/PivotPointsPoint.js +16 -12
- package/es-modules/Stock/Indicators/PriceEnvelopes/PriceEnvelopesIndicator.js +25 -0
- package/es-modules/Stock/Indicators/ROC/ROCIndicator.js +15 -2
- package/es-modules/Stock/Indicators/RSI/RSIIndicator.js +20 -2
- package/es-modules/Stock/Indicators/SMA/SMAIndicator.js +1 -1
- package/es-modules/Stock/Indicators/SlowStochastic/SlowStochasticIndicator.js +25 -0
- package/es-modules/Stock/Indicators/Stochastic/StochasticIndicator.js +15 -0
- package/es-modules/Stock/Indicators/Supertrend/SupertrendIndicator.js +17 -3
- package/es-modules/Stock/Indicators/TRIX/TRIXIndicator.js +25 -0
- package/es-modules/Stock/Indicators/TrendLine/TrendLineIndicator.js +14 -4
- package/es-modules/Stock/Indicators/VBP/VBPIndicator.js +32 -3
- package/es-modules/Stock/Indicators/VBP/VBPPoint.js +6 -6
- package/es-modules/Stock/Indicators/VWAP/VWAPIndicator.js +11 -1
- package/es-modules/Stock/Indicators/WMA/WMAIndicator.js +30 -2
- package/es-modules/Stock/Indicators/WilliamsR/WilliamsRIndicator.js +10 -0
- package/es-modules/Stock/Indicators/Zigzag/ZigzagIndicator.js +11 -1
- package/es-modules/Stock/StockToolbar.js +568 -0
- package/es-modules/Stock/StockTools.js +256 -0
- package/es-modules/Stock/StockToolsBindings.js +114 -629
- package/es-modules/Stock/StockToolsDefaults.js +1190 -0
- package/es-modules/Stock/StockToolsGui.js +150 -1771
- package/es-modules/Stock/StockToolsUtilities.js +423 -0
- package/es-modules/masters/highcharts-3d.src.js +5 -4
- package/es-modules/masters/highcharts-gantt.src.js +1 -1
- package/es-modules/masters/highcharts-more.src.js +4 -3
- package/es-modules/masters/highcharts.src.js +5 -2
- package/es-modules/masters/highmaps.src.js +1 -1
- package/es-modules/masters/highstock.src.js +1 -1
- package/es-modules/masters/indicators/acceleration-bands.src.js +1 -1
- package/es-modules/masters/indicators/accumulation-distribution.src.js +1 -1
- package/es-modules/masters/indicators/ao.src.js +1 -1
- package/es-modules/masters/indicators/apo.src.js +1 -1
- package/es-modules/masters/indicators/aroon-oscillator.src.js +1 -1
- package/es-modules/masters/indicators/aroon.src.js +1 -1
- package/es-modules/masters/indicators/atr.src.js +1 -1
- package/es-modules/masters/indicators/bollinger-bands.src.js +1 -1
- package/es-modules/masters/indicators/cci.src.js +1 -1
- package/es-modules/masters/indicators/chaikin.src.js +1 -1
- package/es-modules/masters/indicators/cmf.src.js +1 -1
- package/es-modules/masters/indicators/cmo.src.js +1 -1
- package/es-modules/masters/indicators/dema.src.js +1 -1
- package/es-modules/masters/indicators/disparity-index.src.js +1 -1
- package/es-modules/masters/indicators/dmi.src.js +1 -1
- package/es-modules/masters/indicators/dpo.src.js +1 -1
- package/es-modules/masters/indicators/ichimoku-kinko-hyo.src.js +1 -1
- package/es-modules/masters/indicators/indicators-all.src.js +5 -7
- package/es-modules/masters/indicators/indicators.src.js +1 -1
- package/es-modules/masters/indicators/keltner-channels.src.js +1 -1
- package/es-modules/masters/indicators/klinger.src.js +1 -1
- package/es-modules/masters/indicators/macd.src.js +1 -1
- package/es-modules/masters/indicators/mfi.src.js +1 -1
- package/es-modules/masters/indicators/momentum.src.js +1 -1
- package/es-modules/masters/indicators/natr.src.js +1 -1
- package/es-modules/masters/indicators/obv.src.js +1 -1
- package/es-modules/masters/indicators/pivot-points.src.js +1 -1
- package/es-modules/masters/indicators/ppo.src.js +1 -1
- package/es-modules/masters/indicators/price-channel.src.js +1 -1
- package/es-modules/masters/indicators/price-envelopes.src.js +1 -1
- package/es-modules/masters/indicators/psar.src.js +1 -1
- package/es-modules/masters/indicators/regressions.src.js +5 -5
- package/es-modules/masters/indicators/roc.src.js +1 -1
- package/es-modules/masters/indicators/rsi.src.js +1 -1
- package/es-modules/masters/indicators/slow-stochastic.src.js +1 -1
- package/es-modules/masters/indicators/stochastic.src.js +1 -1
- package/es-modules/masters/indicators/supertrend.src.js +1 -1
- package/es-modules/masters/indicators/tema.src.js +1 -1
- package/es-modules/masters/indicators/trendline.src.js +1 -1
- package/es-modules/masters/indicators/trix.src.js +1 -1
- package/es-modules/masters/indicators/volume-by-price.src.js +1 -1
- package/es-modules/masters/indicators/vwap.src.js +1 -1
- package/es-modules/masters/indicators/williams-r.src.js +1 -1
- package/es-modules/masters/indicators/wma.src.js +1 -1
- package/es-modules/masters/indicators/zigzag.src.js +1 -1
- package/es-modules/masters/modules/accessibility.src.js +1 -1
- package/es-modules/masters/modules/annotations-advanced.src.js +6 -4
- package/es-modules/masters/modules/annotations.src.js +6 -4
- package/es-modules/masters/modules/arc-diagram.src.js +1 -1
- package/es-modules/masters/modules/arrow-symbols.src.js +1 -1
- package/es-modules/masters/modules/boost-canvas.src.js +1 -1
- package/es-modules/masters/modules/boost.src.js +6 -2
- package/es-modules/masters/modules/broken-axis.src.js +1 -1
- package/es-modules/masters/modules/bullet.src.js +1 -1
- package/es-modules/masters/modules/coloraxis.src.js +1 -1
- package/es-modules/masters/modules/current-date-indicator.src.js +1 -1
- package/es-modules/masters/modules/cylinder.src.js +1 -1
- package/es-modules/masters/modules/data.src.js +1 -1
- package/es-modules/masters/modules/datagrouping.src.js +1 -1
- package/es-modules/masters/modules/debugger.src.js +5 -3
- package/es-modules/masters/modules/dependency-wheel.src.js +1 -1
- package/es-modules/masters/modules/dotplot.src.js +1 -1
- package/es-modules/masters/modules/drag-panes.src.js +1 -1
- package/es-modules/masters/modules/draggable-points.src.js +1 -1
- package/es-modules/masters/modules/drilldown.src.js +1 -1
- package/es-modules/masters/modules/dumbbell.src.js +1 -1
- package/es-modules/masters/modules/export-data.src.js +5 -2
- package/es-modules/masters/modules/exporting.src.js +1 -2
- package/es-modules/masters/modules/full-screen.src.js +6 -2
- package/es-modules/masters/modules/funnel.src.js +1 -1
- package/es-modules/masters/modules/funnel3d.src.js +1 -1
- package/es-modules/masters/modules/gantt.src.js +3 -2
- package/es-modules/masters/modules/grid-axis.src.js +1 -1
- package/es-modules/masters/modules/heatmap.src.js +1 -1
- package/es-modules/masters/modules/heikinashi.src.js +1 -1
- package/es-modules/masters/modules/histogram-bellcurve.src.js +1 -1
- package/es-modules/masters/modules/hollowcandlestick.src.js +1 -1
- package/es-modules/masters/modules/item-series.src.js +1 -1
- package/es-modules/masters/modules/lollipop.src.js +1 -1
- package/es-modules/masters/modules/map.src.js +2 -2
- package/es-modules/masters/modules/marker-clusters.src.js +1 -1
- package/es-modules/masters/modules/networkgraph.src.js +5 -2
- package/es-modules/masters/modules/no-data-to-display.src.js +1 -1
- package/es-modules/masters/modules/offline-exporting.src.js +1 -1
- package/es-modules/masters/modules/oldie-polyfills.src.js +1 -1
- package/es-modules/masters/modules/oldie.src.js +1 -1
- package/es-modules/masters/modules/organization.src.js +1 -1
- package/es-modules/masters/modules/overlapping-datalabels.src.js +1 -1
- package/es-modules/masters/modules/parallel-coordinates.src.js +1 -1
- package/es-modules/masters/modules/pareto.src.js +1 -1
- package/es-modules/masters/modules/pathfinder.src.js +1 -1
- package/es-modules/masters/modules/pattern-fill.src.js +1 -1
- package/es-modules/masters/modules/price-indicator.src.js +1 -1
- package/es-modules/masters/modules/pyramid3d.src.js +1 -1
- package/es-modules/masters/modules/sankey.src.js +1 -1
- package/es-modules/masters/modules/series-label.src.js +1 -1
- package/es-modules/masters/modules/series-on-point.src.js +1 -1
- package/es-modules/masters/modules/solid-gauge.src.js +1 -1
- package/es-modules/masters/modules/sonification.src.js +1 -1
- package/es-modules/masters/modules/static-scale.src.js +1 -1
- package/es-modules/masters/modules/stock-tools.src.js +10 -3
- package/es-modules/masters/modules/stock.src.js +1 -1
- package/es-modules/masters/modules/streamgraph.src.js +1 -1
- package/es-modules/masters/modules/sunburst.src.js +1 -1
- package/es-modules/masters/modules/tilemap.src.js +1 -1
- package/es-modules/masters/modules/timeline.src.js +1 -1
- package/es-modules/masters/modules/treegrid.src.js +2 -2
- package/es-modules/masters/modules/treemap.src.js +1 -1
- package/es-modules/masters/modules/variable-pie.src.js +1 -1
- package/es-modules/masters/modules/variwide.src.js +1 -1
- package/es-modules/masters/modules/vector.src.js +1 -1
- package/es-modules/masters/modules/venn.src.js +1 -1
- package/es-modules/masters/modules/windbarb.src.js +1 -1
- package/es-modules/masters/modules/wordcloud.src.js +1 -1
- package/es-modules/masters/modules/xrange.src.js +5 -2
- package/es-modules/masters/themes/avocado.src.js +1 -1
- package/es-modules/masters/themes/brand-dark.src.js +1 -1
- package/es-modules/masters/themes/brand-light.src.js +1 -1
- package/es-modules/masters/themes/dark-blue.src.js +1 -1
- package/es-modules/masters/themes/dark-green.src.js +1 -1
- package/es-modules/masters/themes/dark-unica.src.js +1 -1
- package/es-modules/masters/themes/gray.src.js +1 -1
- package/es-modules/masters/themes/grid-light.src.js +1 -1
- package/es-modules/masters/themes/grid.src.js +1 -1
- package/es-modules/masters/themes/high-contrast-dark.src.js +1 -1
- package/es-modules/masters/themes/high-contrast-light.src.js +1 -1
- package/es-modules/masters/themes/sand-signika.src.js +1 -1
- package/es-modules/masters/themes/skies.src.js +1 -1
- package/es-modules/masters/themes/sunset.src.js +1 -1
- package/highcharts-3d.js +98 -99
- package/highcharts-3d.js.map +1 -1
- package/highcharts-3d.src.js +232 -211
- package/highcharts-gantt.js +808 -809
- package/highcharts-gantt.js.map +1 -1
- package/highcharts-gantt.src.js +2308 -2136
- package/highcharts-more.d.ts +5 -8
- package/highcharts-more.js +201 -194
- package/highcharts-more.js.map +1 -1
- package/highcharts-more.src.d.ts +5 -8
- package/highcharts-more.src.js +3671 -3275
- package/highcharts.d.ts +1400 -885
- package/highcharts.js +593 -595
- package/highcharts.js.map +1 -1
- package/highcharts.src.d.ts +1400 -885
- package/highcharts.src.js +847 -716
- package/highmaps.js +762 -763
- package/highmaps.js.map +1 -1
- package/highmaps.src.js +1288 -1129
- package/highstock.js +796 -798
- package/highstock.js.map +1 -1
- package/highstock.src.js +953 -762
- package/indicators/acceleration-bands.js +1 -1
- package/indicators/acceleration-bands.js.map +1 -1
- package/indicators/acceleration-bands.src.js +11 -3
- package/indicators/accumulation-distribution.js +1 -1
- package/indicators/accumulation-distribution.js.map +1 -1
- package/indicators/accumulation-distribution.src.js +6 -1
- package/indicators/ao.js +6 -6
- package/indicators/ao.js.map +1 -1
- package/indicators/ao.src.js +23 -14
- package/indicators/apo.js +1 -1
- package/indicators/apo.js.map +1 -1
- package/indicators/apo.src.js +6 -1
- package/indicators/aroon-oscillator.js +10 -10
- package/indicators/aroon-oscillator.js.map +1 -1
- package/indicators/aroon-oscillator.src.js +7 -3
- package/indicators/aroon.js +1 -1
- package/indicators/aroon.js.map +1 -1
- package/indicators/aroon.src.js +16 -3
- package/indicators/atr.js +1 -1
- package/indicators/atr.js.map +1 -1
- package/indicators/atr.src.js +17 -4
- package/indicators/bollinger-bands.js +1 -1
- package/indicators/bollinger-bands.js.map +1 -1
- package/indicators/bollinger-bands.src.js +6 -2
- package/indicators/cci.js +1 -1
- package/indicators/cci.js.map +1 -1
- package/indicators/cci.src.js +17 -4
- package/indicators/chaikin.js +8 -8
- package/indicators/chaikin.js.map +1 -1
- package/indicators/chaikin.src.js +13 -5
- package/indicators/cmf.js +1 -1
- package/indicators/cmf.js.map +1 -1
- package/indicators/cmf.src.js +21 -1
- package/indicators/cmo.js +1 -1
- package/indicators/cmo.js.map +1 -1
- package/indicators/cmo.src.js +16 -2
- package/indicators/dema.js +1 -1
- package/indicators/dema.js.map +1 -1
- package/indicators/dema.src.js +26 -1
- package/indicators/disparity-index.js +1 -1
- package/indicators/disparity-index.src.js +1 -1
- package/indicators/dmi.js +1 -1
- package/indicators/dmi.js.map +1 -1
- package/indicators/dmi.src.js +6 -1
- package/indicators/dpo.js +1 -1
- package/indicators/dpo.js.map +1 -1
- package/indicators/dpo.src.js +20 -9
- package/indicators/ichimoku-kinko-hyo.js +1 -1
- package/indicators/ichimoku-kinko-hyo.js.map +1 -1
- package/indicators/ichimoku-kinko-hyo.src.js +35 -16
- package/indicators/indicators-all.js +199 -199
- package/indicators/indicators-all.js.map +1 -1
- package/indicators/indicators-all.src.js +754 -162
- package/indicators/indicators.js +1 -1
- package/indicators/indicators.js.map +1 -1
- package/indicators/indicators.src.js +12 -2
- package/indicators/keltner-channels.js +1 -1
- package/indicators/keltner-channels.js.map +1 -1
- package/indicators/keltner-channels.src.js +26 -1
- package/indicators/klinger.js +12 -12
- package/indicators/klinger.js.map +1 -1
- package/indicators/klinger.src.js +13 -4
- package/indicators/macd.js +1 -1
- package/indicators/macd.js.map +1 -1
- package/indicators/macd.src.js +22 -13
- package/indicators/mfi.js +1 -1
- package/indicators/mfi.js.map +1 -1
- package/indicators/mfi.src.js +24 -11
- package/indicators/momentum.js +1 -1
- package/indicators/momentum.js.map +1 -1
- package/indicators/momentum.src.js +31 -3
- package/indicators/natr.js +1 -1
- package/indicators/natr.js.map +1 -1
- package/indicators/natr.src.js +17 -3
- package/indicators/obv.js +1 -1
- package/indicators/obv.js.map +1 -1
- package/indicators/obv.src.js +11 -1
- package/indicators/pivot-points.js +1 -1
- package/indicators/pivot-points.js.map +1 -1
- package/indicators/pivot-points.src.js +32 -19
- package/indicators/ppo.js +1 -1
- package/indicators/ppo.js.map +1 -1
- package/indicators/ppo.src.js +15 -5
- package/indicators/price-channel.js +1 -1
- package/indicators/price-channel.js.map +1 -1
- package/indicators/price-channel.src.js +14 -9
- package/indicators/price-envelopes.js +1 -1
- package/indicators/price-envelopes.js.map +1 -1
- package/indicators/price-envelopes.src.js +26 -1
- package/indicators/psar.js +1 -1
- package/indicators/psar.js.map +1 -1
- package/indicators/psar.src.js +17 -4
- package/indicators/regressions.js +12 -11
- package/indicators/regressions.js.map +1 -1
- package/indicators/regressions.src.js +50 -15
- package/indicators/roc.js +1 -1
- package/indicators/roc.js.map +1 -1
- package/indicators/roc.src.js +16 -3
- package/indicators/rsi.js +1 -1
- package/indicators/rsi.js.map +1 -1
- package/indicators/rsi.src.js +21 -3
- package/indicators/slow-stochastic.js +1 -1
- package/indicators/slow-stochastic.js.map +1 -1
- package/indicators/slow-stochastic.src.js +26 -1
- package/indicators/stochastic.js +1 -1
- package/indicators/stochastic.js.map +1 -1
- package/indicators/stochastic.src.js +16 -1
- package/indicators/supertrend.js +7 -7
- package/indicators/supertrend.js.map +1 -1
- package/indicators/supertrend.src.js +18 -6
- package/indicators/tema.js +1 -1
- package/indicators/tema.src.js +1 -1
- package/indicators/trendline.js +1 -1
- package/indicators/trendline.js.map +1 -1
- package/indicators/trendline.src.js +15 -5
- package/indicators/trix.js +1 -1
- package/indicators/trix.js.map +1 -1
- package/indicators/trix.src.js +26 -1
- package/indicators/volume-by-price.js +17 -17
- package/indicators/volume-by-price.js.map +1 -1
- package/indicators/volume-by-price.src.js +38 -10
- package/indicators/vwap.js +1 -1
- package/indicators/vwap.js.map +1 -1
- package/indicators/vwap.src.js +12 -2
- package/indicators/williams-r.js +1 -1
- package/indicators/williams-r.js.map +1 -1
- package/indicators/williams-r.src.js +11 -1
- package/indicators/wma.js +1 -1
- package/indicators/wma.js.map +1 -1
- package/indicators/wma.src.js +31 -3
- package/indicators/zigzag.js +1 -1
- package/indicators/zigzag.js.map +1 -1
- package/indicators/zigzag.src.js +12 -2
- package/modules/accessibility.js +183 -182
- package/modules/accessibility.js.map +1 -1
- package/modules/accessibility.src.js +559 -554
- package/modules/annotations-advanced.d.ts +1 -1
- package/modules/annotations-advanced.js +193 -192
- package/modules/annotations-advanced.js.map +1 -1
- package/modules/annotations-advanced.src.d.ts +1 -1
- package/modules/annotations-advanced.src.js +9263 -8654
- package/modules/annotations.d.ts +1 -1
- package/modules/annotations.js +128 -126
- package/modules/annotations.js.map +1 -1
- package/modules/annotations.src.d.ts +1 -1
- package/modules/annotations.src.js +6699 -6063
- package/modules/arc-diagram.js +1 -1
- package/modules/arc-diagram.src.js +1 -1
- package/modules/arrow-symbols.js +1 -1
- package/modules/arrow-symbols.src.js +1 -1
- package/modules/boost-canvas.d.ts +19 -0
- package/modules/boost-canvas.js +81 -16
- package/modules/boost-canvas.js.map +1 -1
- package/modules/boost-canvas.src.d.ts +19 -0
- package/modules/boost-canvas.src.js +3334 -50
- package/modules/boost.d.ts +8 -26
- package/modules/boost.js +84 -77
- package/modules/boost.js.map +1 -1
- package/modules/boost.src.d.ts +8 -26
- package/modules/boost.src.js +2423 -1888
- package/modules/broken-axis.js +2 -2
- package/modules/broken-axis.js.map +1 -1
- package/modules/broken-axis.src.js +2 -2
- package/modules/bullet.js +1 -1
- package/modules/bullet.src.js +1 -1
- package/modules/coloraxis.js +1 -1
- package/modules/coloraxis.js.map +1 -1
- package/modules/coloraxis.src.js +5 -1
- package/modules/current-date-indicator.js +1 -1
- package/modules/current-date-indicator.src.js +1 -1
- package/modules/cylinder.js +9 -9
- package/modules/cylinder.js.map +1 -1
- package/modules/cylinder.src.js +2 -2
- package/modules/data.js +1 -1
- package/modules/data.src.js +1 -1
- package/modules/datagrouping.d.ts +22 -0
- package/modules/datagrouping.js +4 -4
- package/modules/datagrouping.js.map +1 -1
- package/modules/datagrouping.src.d.ts +22 -0
- package/modules/datagrouping.src.js +66 -28
- package/modules/debugger.js +6 -5
- package/modules/debugger.js.map +1 -1
- package/modules/debugger.src.js +81 -40
- package/modules/dependency-wheel.js +12 -12
- package/modules/dependency-wheel.js.map +1 -1
- package/modules/dependency-wheel.src.js +41 -14
- package/modules/dotplot.js +1 -1
- package/modules/dotplot.src.js +1 -1
- package/modules/drag-panes.js +1 -1
- package/modules/drag-panes.src.js +1 -1
- package/modules/draggable-points.js +5 -5
- package/modules/draggable-points.js.map +1 -1
- package/modules/draggable-points.src.js +5 -4
- package/modules/drilldown.d.ts +0 -10
- package/modules/drilldown.js +29 -29
- package/modules/drilldown.js.map +1 -1
- package/modules/drilldown.src.d.ts +0 -10
- package/modules/drilldown.src.js +12 -9
- package/modules/dumbbell.js +1 -1
- package/modules/dumbbell.src.js +1 -1
- package/modules/export-data.js +25 -24
- package/modules/export-data.js.map +1 -1
- package/modules/export-data.src.js +607 -499
- package/modules/exporting.js +38 -38
- package/modules/exporting.js.map +1 -1
- package/modules/exporting.src.js +559 -507
- package/modules/full-screen.js +8 -8
- package/modules/full-screen.js.map +1 -1
- package/modules/full-screen.src.js +76 -26
- package/modules/funnel.js +1 -1
- package/modules/funnel.src.js +1 -1
- package/modules/funnel3d.js +2 -2
- package/modules/funnel3d.js.map +1 -1
- package/modules/funnel3d.src.js +2 -2
- package/modules/gantt.js +217 -216
- package/modules/gantt.js.map +1 -1
- package/modules/gantt.src.js +1481 -1440
- package/modules/grid-axis.js +1 -1
- package/modules/grid-axis.src.js +1 -1
- package/modules/heatmap.js +1 -1
- package/modules/heatmap.js.map +1 -1
- package/modules/heatmap.src.js +10 -2
- package/modules/heikinashi.js +1 -1
- package/modules/heikinashi.src.js +1 -1
- package/modules/histogram-bellcurve.js +1 -1
- package/modules/histogram-bellcurve.src.js +1 -1
- package/modules/hollowcandlestick.js +1 -1
- package/modules/hollowcandlestick.src.js +1 -1
- package/modules/item-series.js +1 -1
- package/modules/item-series.src.js +1 -1
- package/modules/lollipop.js +6 -6
- package/modules/lollipop.js.map +1 -1
- package/modules/lollipop.src.js +37 -22
- package/modules/map.d.ts +3 -3
- package/modules/map.js +171 -171
- package/modules/map.js.map +1 -1
- package/modules/map.src.d.ts +3 -3
- package/modules/map.src.js +442 -414
- package/modules/marker-clusters.js +1 -1
- package/modules/marker-clusters.js.map +1 -1
- package/modules/marker-clusters.src.js +3 -1
- package/modules/networkgraph.js +55 -50
- package/modules/networkgraph.js.map +1 -1
- package/modules/networkgraph.src.js +2259 -1938
- package/modules/no-data-to-display.js +1 -1
- package/modules/no-data-to-display.src.js +1 -1
- package/modules/offline-exporting.js +2 -2
- package/modules/offline-exporting.src.js +2 -2
- package/modules/oldie-polyfills.js +1 -1
- package/modules/oldie-polyfills.src.js +1 -1
- package/modules/oldie.js +2 -2
- package/modules/oldie.src.js +2 -2
- package/modules/organization.js +15 -15
- package/modules/organization.js.map +1 -1
- package/modules/organization.src.js +10 -2
- package/modules/overlapping-datalabels.js +1 -1
- package/modules/overlapping-datalabels.src.js +1 -1
- package/modules/parallel-coordinates.js +11 -11
- package/modules/parallel-coordinates.js.map +1 -1
- package/modules/parallel-coordinates.src.js +13 -8
- package/modules/pareto.js +1 -1
- package/modules/pareto.src.js +1 -1
- package/modules/pathfinder.js +1 -1
- package/modules/pathfinder.src.js +1 -1
- package/modules/pattern-fill.js +1 -1
- package/modules/pattern-fill.src.js +1 -1
- package/modules/price-indicator.js +1 -1
- package/modules/price-indicator.src.js +1 -1
- package/modules/pyramid3d.js +1 -1
- package/modules/pyramid3d.src.js +1 -1
- package/modules/sankey.js +1 -1
- package/modules/sankey.js.map +1 -1
- package/modules/sankey.src.js +14 -2
- package/modules/series-label.js +5 -5
- package/modules/series-label.js.map +1 -1
- package/modules/series-label.src.js +3 -3
- package/modules/series-on-point.js +1 -1
- package/modules/series-on-point.js.map +1 -1
- package/modules/series-on-point.src.js +6 -2
- package/modules/solid-gauge.js +1 -1
- package/modules/solid-gauge.src.js +2 -2
- package/modules/sonification.d.ts +2 -2
- package/modules/sonification.js +1 -1
- package/modules/sonification.src.d.ts +2 -2
- package/modules/sonification.src.js +2 -2
- package/modules/static-scale.js +1 -1
- package/modules/static-scale.src.js +1 -1
- package/modules/stock-tools.d.ts +1 -23
- package/modules/stock-tools.js +109 -179
- package/modules/stock-tools.js.map +1 -1
- package/modules/stock-tools.src.d.ts +1 -23
- package/modules/stock-tools.src.js +2605 -6335
- package/modules/stock.d.ts +8 -0
- package/modules/stock.js +105 -105
- package/modules/stock.js.map +1 -1
- package/modules/stock.src.d.ts +8 -0
- package/modules/stock.src.js +105 -45
- package/modules/streamgraph.js +1 -1
- package/modules/streamgraph.src.js +1 -1
- package/modules/sunburst.js +72 -72
- package/modules/sunburst.js.map +1 -1
- package/modules/sunburst.src.js +38 -12
- package/modules/tilemap.js +1 -1
- package/modules/tilemap.src.js +1 -1
- package/modules/timeline.js +1 -1
- package/modules/timeline.js.map +1 -1
- package/modules/timeline.src.js +3 -1
- package/modules/treegrid.js +57 -57
- package/modules/treegrid.js.map +1 -1
- package/modules/treegrid.src.js +1022 -1014
- package/modules/treemap.js +1 -1
- package/modules/treemap.js.map +1 -1
- package/modules/treemap.src.js +8 -4
- package/modules/variable-pie.js +1 -1
- package/modules/variable-pie.src.js +1 -1
- package/modules/variwide.js +1 -1
- package/modules/variwide.src.js +1 -1
- package/modules/vector.js +2 -2
- package/modules/vector.js.map +1 -1
- package/modules/vector.src.js +3 -5
- package/modules/venn.js +1 -1
- package/modules/venn.src.js +5 -5
- package/modules/windbarb.js +1 -1
- package/modules/windbarb.src.js +1 -1
- package/modules/wordcloud.js +1 -1
- package/modules/wordcloud.src.js +3 -3
- package/modules/xrange.js +17 -17
- package/modules/xrange.js.map +1 -1
- package/modules/xrange.src.js +411 -397
- package/package.json +1 -1
- package/themes/avocado.js +1 -1
- package/themes/avocado.src.js +1 -1
- package/themes/brand-dark.js +1 -1
- package/themes/brand-dark.src.js +1 -1
- package/themes/brand-light.js +1 -1
- package/themes/brand-light.src.js +1 -1
- package/themes/dark-blue.js +1 -1
- package/themes/dark-blue.src.js +1 -1
- package/themes/dark-green.js +1 -1
- package/themes/dark-green.src.js +1 -1
- package/themes/dark-unica.js +1 -1
- package/themes/dark-unica.src.js +1 -1
- package/themes/gray.js +1 -1
- package/themes/gray.src.js +1 -1
- package/themes/grid-light.js +1 -1
- package/themes/grid-light.src.js +1 -1
- package/themes/grid.js +1 -1
- package/themes/grid.src.js +1 -1
- package/themes/high-contrast-dark.js +1 -1
- package/themes/high-contrast-dark.src.js +1 -1
- package/themes/high-contrast-light.js +1 -1
- package/themes/high-contrast-light.src.js +1 -1
- package/themes/sand-signika.js +1 -1
- package/themes/sand-signika.src.js +1 -1
- package/themes/skies.js +1 -1
- package/themes/skies.src.js +1 -1
- package/themes/sunset.js +1 -1
- package/themes/sunset.src.js +1 -1
- package/es-modules/Core/Axis/StackingAxis.js +0 -215
- package/es-modules/Core/Axis/TreeGridAxis.js +0 -720
- package/es-modules/Core/Axis/TreeGridTick.js +0 -317
- package/es-modules/Extensions/Annotations/AnnotationsDefaults.js +0 -0
- package/es-modules/Extensions/Annotations/Mixins/MarkerMixin.js +0 -179
- package/es-modules/Extensions/Annotations/Popup.js +0 -1123
- package/es-modules/Extensions/Boost/BoostAttach.js +0 -154
- package/es-modules/Extensions/Boost/BoostInit.js +0 -324
- package/es-modules/Extensions/Boost/BoostOptions.js +0 -245
- package/es-modules/Extensions/Boost/BoostOverrides.js +0 -386
- package/es-modules/Extensions/Boost/BoostUtils.js +0 -255
- package/es-modules/Extensions/Boost/WGLVBuffer.js +0 -153
- package/es-modules/Extensions/Stacking.js +0 -517
- package/es-modules/Series/Networkgraph/DraggableNodes.js +0 -132
- package/es-modules/Series/Networkgraph/Integrations.js +0 -348
- package/es-modules/Series/Networkgraph/Networkgraph.js +0 -1180
- package/es-modules/Series/XRange/XRangeComposition.js +0 -49
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Highcharts JS v10.2.
|
|
2
|
+
* @license Highcharts JS v10.2.1 (2022-08-29)
|
|
3
3
|
*
|
|
4
4
|
* Force directed graph module
|
|
5
5
|
*
|
|
@@ -37,6 +37,312 @@
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
+
_registerModule(_modules, 'Series/DragNodesComposition.js', [_modules['Core/Utilities.js']], function (U) {
|
|
41
|
+
/* *
|
|
42
|
+
*
|
|
43
|
+
* Networkgraph series
|
|
44
|
+
*
|
|
45
|
+
* (c) 2010-2021 Paweł Fus
|
|
46
|
+
*
|
|
47
|
+
* License: www.highcharts.com/license
|
|
48
|
+
*
|
|
49
|
+
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
50
|
+
*
|
|
51
|
+
* */
|
|
52
|
+
var addEvent = U.addEvent;
|
|
53
|
+
/* *
|
|
54
|
+
*
|
|
55
|
+
* Constants
|
|
56
|
+
*
|
|
57
|
+
* */
|
|
58
|
+
var composedClasses = [];
|
|
59
|
+
/* *
|
|
60
|
+
*
|
|
61
|
+
* Functions
|
|
62
|
+
*
|
|
63
|
+
* */
|
|
64
|
+
/**
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
function compose(ChartClass) {
|
|
68
|
+
if (composedClasses.indexOf(ChartClass) === -1) {
|
|
69
|
+
composedClasses.push(ChartClass);
|
|
70
|
+
addEvent(ChartClass, 'load', onChartLoad);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Draggable mode:
|
|
75
|
+
* @private
|
|
76
|
+
*/
|
|
77
|
+
function onChartLoad() {
|
|
78
|
+
var chart = this;
|
|
79
|
+
var mousedownUnbinder,
|
|
80
|
+
mousemoveUnbinder,
|
|
81
|
+
mouseupUnbinder;
|
|
82
|
+
if (chart.container) {
|
|
83
|
+
mousedownUnbinder = addEvent(chart.container, 'mousedown', function (event) {
|
|
84
|
+
var point = chart.hoverPoint;
|
|
85
|
+
if (point &&
|
|
86
|
+
point.series &&
|
|
87
|
+
point.series.hasDraggableNodes &&
|
|
88
|
+
point.series.options.draggable) {
|
|
89
|
+
point.series.onMouseDown(point, event);
|
|
90
|
+
mousemoveUnbinder = addEvent(chart.container, 'mousemove', function (e) { return (point &&
|
|
91
|
+
point.series &&
|
|
92
|
+
point.series.onMouseMove(point, e)); });
|
|
93
|
+
mouseupUnbinder = addEvent(chart.container.ownerDocument, 'mouseup', function (e) {
|
|
94
|
+
mousemoveUnbinder();
|
|
95
|
+
mouseupUnbinder();
|
|
96
|
+
return point &&
|
|
97
|
+
point.series &&
|
|
98
|
+
point.series.onMouseUp(point, e);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
addEvent(chart, 'destroy', function () {
|
|
104
|
+
mousedownUnbinder();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Mouse down action, initializing drag&drop mode.
|
|
109
|
+
*
|
|
110
|
+
* @private
|
|
111
|
+
* @param {Highcharts.Point} point
|
|
112
|
+
* The point that event occured.
|
|
113
|
+
* @param {Highcharts.PointerEventObject} event
|
|
114
|
+
* Browser event, before normalization.
|
|
115
|
+
*/
|
|
116
|
+
function onMouseDown(point, event) {
|
|
117
|
+
var normalizedEvent = this.chart.pointer.normalize(event);
|
|
118
|
+
point.fixedPosition = {
|
|
119
|
+
chartX: normalizedEvent.chartX,
|
|
120
|
+
chartY: normalizedEvent.chartY,
|
|
121
|
+
plotX: point.plotX,
|
|
122
|
+
plotY: point.plotY
|
|
123
|
+
};
|
|
124
|
+
point.inDragMode = true;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Mouse move action during drag&drop.
|
|
128
|
+
*
|
|
129
|
+
* @private
|
|
130
|
+
*
|
|
131
|
+
* @param {global.Event} event
|
|
132
|
+
* Browser event, before normalization.
|
|
133
|
+
* @param {Highcharts.Point} point
|
|
134
|
+
* The point that event occured.
|
|
135
|
+
*
|
|
136
|
+
*/
|
|
137
|
+
function onMouseMove(point, event) {
|
|
138
|
+
if (point.fixedPosition && point.inDragMode) {
|
|
139
|
+
var series = this,
|
|
140
|
+
chart = series.chart,
|
|
141
|
+
normalizedEvent = chart.pointer.normalize(event),
|
|
142
|
+
diffX = point.fixedPosition.chartX - normalizedEvent.chartX,
|
|
143
|
+
diffY = point.fixedPosition.chartY - normalizedEvent.chartY,
|
|
144
|
+
graphLayoutsLookup = chart.graphLayoutsLookup;
|
|
145
|
+
var newPlotX = void 0,
|
|
146
|
+
newPlotY = void 0;
|
|
147
|
+
// At least 5px to apply change (avoids simple click):
|
|
148
|
+
if (Math.abs(diffX) > 5 || Math.abs(diffY) > 5) {
|
|
149
|
+
newPlotX = point.fixedPosition.plotX - diffX;
|
|
150
|
+
newPlotY = point.fixedPosition.plotY - diffY;
|
|
151
|
+
if (chart.isInsidePlot(newPlotX, newPlotY)) {
|
|
152
|
+
point.plotX = newPlotX;
|
|
153
|
+
point.plotY = newPlotY;
|
|
154
|
+
point.hasDragged = true;
|
|
155
|
+
this.redrawHalo(point);
|
|
156
|
+
graphLayoutsLookup.forEach(function (layout) {
|
|
157
|
+
layout.restartSimulation();
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Mouse up action, finalizing drag&drop.
|
|
165
|
+
*
|
|
166
|
+
* @private
|
|
167
|
+
* @param {Highcharts.Point} point
|
|
168
|
+
* The point that event occured.
|
|
169
|
+
*/
|
|
170
|
+
function onMouseUp(point, _event) {
|
|
171
|
+
if (point.fixedPosition) {
|
|
172
|
+
if (point.hasDragged) {
|
|
173
|
+
if (this.layout.enableSimulation) {
|
|
174
|
+
this.layout.start();
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
this.chart.redraw();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
point.inDragMode = point.hasDragged = false;
|
|
181
|
+
if (!this.options.fixedDraggable) {
|
|
182
|
+
delete point.fixedPosition;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Redraw halo on mousemove during the drag&drop action.
|
|
188
|
+
*
|
|
189
|
+
* @private
|
|
190
|
+
* @param {Highcharts.Point} point
|
|
191
|
+
* The point that should show halo.
|
|
192
|
+
*/
|
|
193
|
+
function redrawHalo(point) {
|
|
194
|
+
if (point && this.halo) {
|
|
195
|
+
this.halo.attr({
|
|
196
|
+
d: point.haloPath(this.options.states.hover.halo.size)
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/* *
|
|
201
|
+
*
|
|
202
|
+
* Default Export
|
|
203
|
+
*
|
|
204
|
+
* */
|
|
205
|
+
var DragNodesComposition = {
|
|
206
|
+
compose: compose,
|
|
207
|
+
onMouseDown: onMouseDown,
|
|
208
|
+
onMouseMove: onMouseMove,
|
|
209
|
+
onMouseUp: onMouseUp,
|
|
210
|
+
redrawHalo: redrawHalo
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return DragNodesComposition;
|
|
214
|
+
});
|
|
215
|
+
_registerModule(_modules, 'Series/GraphLayoutComposition.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Utilities.js']], function (A, U) {
|
|
216
|
+
/* *
|
|
217
|
+
*
|
|
218
|
+
* Networkgraph series
|
|
219
|
+
*
|
|
220
|
+
* (c) 2010-2021 Paweł Fus
|
|
221
|
+
*
|
|
222
|
+
* License: www.highcharts.com/license
|
|
223
|
+
*
|
|
224
|
+
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
225
|
+
*
|
|
226
|
+
* */
|
|
227
|
+
var setAnimation = A.setAnimation;
|
|
228
|
+
var addEvent = U.addEvent;
|
|
229
|
+
/* *
|
|
230
|
+
*
|
|
231
|
+
* Constants
|
|
232
|
+
*
|
|
233
|
+
* */
|
|
234
|
+
var composedClasses = [];
|
|
235
|
+
var integrations = {};
|
|
236
|
+
var layouts = {};
|
|
237
|
+
/* *
|
|
238
|
+
*
|
|
239
|
+
* Functions
|
|
240
|
+
*
|
|
241
|
+
* */
|
|
242
|
+
/**
|
|
243
|
+
* @private
|
|
244
|
+
*/
|
|
245
|
+
function compose(ChartClass) {
|
|
246
|
+
if (composedClasses.indexOf(ChartClass)) {
|
|
247
|
+
composedClasses.push(ChartClass);
|
|
248
|
+
addEvent(ChartClass, 'afterPrint', onChartAfterPrint);
|
|
249
|
+
addEvent(ChartClass, 'beforePrint', onChartBeforePrint);
|
|
250
|
+
addEvent(ChartClass, 'predraw', onChartPredraw);
|
|
251
|
+
addEvent(ChartClass, 'render', onChartRender);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Re-enable simulation after print.
|
|
256
|
+
* @private
|
|
257
|
+
*/
|
|
258
|
+
function onChartAfterPrint() {
|
|
259
|
+
if (this.graphLayoutsLookup) {
|
|
260
|
+
this.graphLayoutsLookup.forEach(function (layout) {
|
|
261
|
+
// return to default simulation
|
|
262
|
+
layout.updateSimulation();
|
|
263
|
+
});
|
|
264
|
+
this.redraw();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Disable simulation before print if enabled.
|
|
269
|
+
* @private
|
|
270
|
+
*/
|
|
271
|
+
function onChartBeforePrint() {
|
|
272
|
+
if (this.graphLayoutsLookup) {
|
|
273
|
+
this.graphLayoutsLookup.forEach(function (layout) {
|
|
274
|
+
layout.updateSimulation(false);
|
|
275
|
+
});
|
|
276
|
+
this.redraw();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Clear previous layouts.
|
|
281
|
+
* @private
|
|
282
|
+
*/
|
|
283
|
+
function onChartPredraw() {
|
|
284
|
+
if (this.graphLayoutsLookup) {
|
|
285
|
+
this.graphLayoutsLookup.forEach(function (layout) {
|
|
286
|
+
layout.stop();
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* @private
|
|
292
|
+
*/
|
|
293
|
+
function onChartRender() {
|
|
294
|
+
var systemsStable,
|
|
295
|
+
afterRender = false;
|
|
296
|
+
var layoutStep = function (layout) {
|
|
297
|
+
if (layout.maxIterations-- &&
|
|
298
|
+
isFinite(layout.temperature) &&
|
|
299
|
+
!layout.isStable() &&
|
|
300
|
+
!layout.enableSimulation) {
|
|
301
|
+
// Hook similar to build-in addEvent, but instead of
|
|
302
|
+
// creating whole events logic, use just a function.
|
|
303
|
+
// It's faster which is important for rAF code.
|
|
304
|
+
// Used e.g. in packed-bubble series for bubble radius
|
|
305
|
+
// calculations
|
|
306
|
+
if (layout.beforeStep) {
|
|
307
|
+
layout.beforeStep();
|
|
308
|
+
}
|
|
309
|
+
layout.step();
|
|
310
|
+
systemsStable = false;
|
|
311
|
+
afterRender = true;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
if (this.graphLayoutsLookup) {
|
|
315
|
+
setAnimation(false, this);
|
|
316
|
+
// Start simulation
|
|
317
|
+
this.graphLayoutsLookup.forEach(function (layout) { return layout.start(); });
|
|
318
|
+
// Just one sync step, to run different layouts similar to
|
|
319
|
+
// async mode.
|
|
320
|
+
while (!systemsStable) {
|
|
321
|
+
systemsStable = true;
|
|
322
|
+
this.graphLayoutsLookup.forEach(layoutStep);
|
|
323
|
+
}
|
|
324
|
+
if (afterRender) {
|
|
325
|
+
this.series.forEach(function (series) {
|
|
326
|
+
if (series && series.layout) {
|
|
327
|
+
series.render();
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/* *
|
|
334
|
+
*
|
|
335
|
+
* Default Export
|
|
336
|
+
*
|
|
337
|
+
* */
|
|
338
|
+
var GraphLayoutComposition = {
|
|
339
|
+
compose: compose,
|
|
340
|
+
integrations: integrations,
|
|
341
|
+
layouts: layouts
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
return GraphLayoutComposition;
|
|
345
|
+
});
|
|
40
346
|
_registerModule(_modules, 'Series/NodesComposition.js', [_modules['Core/Series/SeriesRegistry.js'], _modules['Core/Utilities.js']], function (SeriesRegistry, U) {
|
|
41
347
|
/* *
|
|
42
348
|
*
|
|
@@ -340,7 +646,7 @@
|
|
|
340
646
|
|
|
341
647
|
return NodesComposition;
|
|
342
648
|
});
|
|
343
|
-
_registerModule(_modules, 'Series/Networkgraph/
|
|
649
|
+
_registerModule(_modules, 'Series/Networkgraph/NetworkgraphPoint.js', [_modules['Series/NodesComposition.js'], _modules['Core/Series/SeriesRegistry.js'], _modules['Core/Utilities.js']], function (NodesComposition, SeriesRegistry, U) {
|
|
344
650
|
/* *
|
|
345
651
|
*
|
|
346
652
|
* Networkgraph series
|
|
@@ -352,359 +658,1055 @@
|
|
|
352
658
|
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
353
659
|
*
|
|
354
660
|
* */
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
node.plotY -=
|
|
407
|
-
yFactor / node.mass / node.degree;
|
|
661
|
+
var __extends = (this && this.__extends) || (function () {
|
|
662
|
+
var extendStatics = function (d,
|
|
663
|
+
b) {
|
|
664
|
+
extendStatics = Object.setPrototypeOf ||
|
|
665
|
+
({ __proto__: [] } instanceof Array && function (d,
|
|
666
|
+
b) { d.__proto__ = b; }) ||
|
|
667
|
+
function (d,
|
|
668
|
+
b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
669
|
+
return extendStatics(d, b);
|
|
670
|
+
};
|
|
671
|
+
return function (d, b) {
|
|
672
|
+
extendStatics(d, b);
|
|
673
|
+
function __() { this.constructor = d; }
|
|
674
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
675
|
+
};
|
|
676
|
+
})();
|
|
677
|
+
var _a = SeriesRegistry.series,
|
|
678
|
+
seriesProto = _a.prototype,
|
|
679
|
+
Point = _a.prototype.pointClass;
|
|
680
|
+
var addEvent = U.addEvent,
|
|
681
|
+
css = U.css,
|
|
682
|
+
defined = U.defined,
|
|
683
|
+
extend = U.extend,
|
|
684
|
+
pick = U.pick;
|
|
685
|
+
/* *
|
|
686
|
+
*
|
|
687
|
+
* Class
|
|
688
|
+
*
|
|
689
|
+
* */
|
|
690
|
+
var NetworkgraphPoint = /** @class */ (function (_super) {
|
|
691
|
+
__extends(NetworkgraphPoint, _super);
|
|
692
|
+
function NetworkgraphPoint() {
|
|
693
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
694
|
+
}
|
|
695
|
+
/* *
|
|
696
|
+
*
|
|
697
|
+
* Functions
|
|
698
|
+
*
|
|
699
|
+
* */
|
|
700
|
+
/**
|
|
701
|
+
* Destroy point. If it's a node, remove all links coming out of this
|
|
702
|
+
* node. Then remove point from the layout.
|
|
703
|
+
* @private
|
|
704
|
+
*/
|
|
705
|
+
NetworkgraphPoint.prototype.destroy = function () {
|
|
706
|
+
if (this.isNode) {
|
|
707
|
+
this.linksFrom.concat(this.linksTo).forEach(function (link) {
|
|
708
|
+
// Removing multiple nodes at the same time
|
|
709
|
+
// will try to remove link between nodes twice
|
|
710
|
+
if (link.destroyElements) {
|
|
711
|
+
link.destroyElements();
|
|
408
712
|
}
|
|
409
713
|
});
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
714
|
+
}
|
|
715
|
+
this.series.layout.removeElementFromCollection(this, this.series.layout[this.isNode ? 'nodes' : 'links']);
|
|
716
|
+
return Point.prototype.destroy.apply(this, arguments);
|
|
717
|
+
};
|
|
718
|
+
/**
|
|
719
|
+
* Return degree of a node. If node has no connections, it still has
|
|
720
|
+
* deg=1.
|
|
721
|
+
* @private
|
|
722
|
+
*/
|
|
723
|
+
NetworkgraphPoint.prototype.getDegree = function () {
|
|
724
|
+
var deg = this.isNode ?
|
|
725
|
+
this.linksFrom.length + this.linksTo.length :
|
|
726
|
+
0;
|
|
727
|
+
return deg === 0 ? 1 : deg;
|
|
728
|
+
};
|
|
729
|
+
/**
|
|
730
|
+
* Get presentational attributes of link connecting two nodes.
|
|
731
|
+
* @private
|
|
732
|
+
*/
|
|
733
|
+
NetworkgraphPoint.prototype.getLinkAttributes = function () {
|
|
734
|
+
var linkOptions = this.series.options.link,
|
|
735
|
+
pointOptions = this.options;
|
|
736
|
+
return {
|
|
737
|
+
'stroke-width': pick(pointOptions.width, linkOptions.width),
|
|
738
|
+
stroke: (pointOptions.color || linkOptions.color),
|
|
739
|
+
dashstyle: (pointOptions.dashStyle || linkOptions.dashStyle),
|
|
740
|
+
opacity: pick(pointOptions.opacity, linkOptions.opacity, 1)
|
|
741
|
+
};
|
|
742
|
+
};
|
|
743
|
+
/**
|
|
744
|
+
* Get link path connecting two nodes.
|
|
745
|
+
* @private
|
|
746
|
+
* @return {Array<Highcharts.SVGPathArray>}
|
|
747
|
+
* Path: `['M', x, y, 'L', x, y]`
|
|
748
|
+
*/
|
|
749
|
+
NetworkgraphPoint.prototype.getLinkPath = function () {
|
|
750
|
+
var left = this.fromNode,
|
|
751
|
+
right = this.toNode;
|
|
752
|
+
// Start always from left to the right node, to prevent rendering
|
|
753
|
+
// labels upside down
|
|
754
|
+
if (left.plotX > right.plotX) {
|
|
755
|
+
left = this.toNode;
|
|
756
|
+
right = this.fromNode;
|
|
757
|
+
}
|
|
758
|
+
return [
|
|
759
|
+
['M', left.plotX || 0, left.plotY || 0],
|
|
760
|
+
['L', right.plotX || 0, right.plotY || 0]
|
|
761
|
+
];
|
|
762
|
+
/*
|
|
763
|
+
IDEA: different link shapes?
|
|
764
|
+
return [
|
|
765
|
+
'M',
|
|
766
|
+
from.plotX,
|
|
767
|
+
from.plotY,
|
|
768
|
+
'Q',
|
|
769
|
+
(to.plotX + from.plotX) / 2,
|
|
770
|
+
(to.plotY + from.plotY) / 2 + 15,
|
|
771
|
+
to.plotX,
|
|
772
|
+
to.plotY
|
|
773
|
+
];*/
|
|
774
|
+
};
|
|
775
|
+
/**
|
|
776
|
+
* Get mass fraction applied on two nodes connected to each other. By
|
|
777
|
+
* default, when mass is equal to `1`, mass fraction for both nodes
|
|
778
|
+
* equal to 0.5.
|
|
779
|
+
* @private
|
|
780
|
+
* @return {Highcharts.Dictionary<number>}
|
|
781
|
+
* For example `{ fromNode: 0.5, toNode: 0.5 }`
|
|
782
|
+
*/
|
|
783
|
+
NetworkgraphPoint.prototype.getMass = function () {
|
|
784
|
+
var m1 = this.fromNode.mass,
|
|
785
|
+
m2 = this.toNode.mass,
|
|
786
|
+
sum = m1 + m2;
|
|
787
|
+
return {
|
|
788
|
+
fromNode: 1 - m1 / sum,
|
|
789
|
+
toNode: 1 - m2 / sum
|
|
790
|
+
};
|
|
791
|
+
};
|
|
792
|
+
/**
|
|
793
|
+
* Basic `point.init()` and additional styles applied when
|
|
794
|
+
* `series.draggable` is enabled.
|
|
795
|
+
* @private
|
|
796
|
+
*/
|
|
797
|
+
NetworkgraphPoint.prototype.init = function (series, options, x) {
|
|
798
|
+
_super.prototype.init.call(this, series, options, x);
|
|
799
|
+
if (this.series.options.draggable &&
|
|
800
|
+
!this.series.chart.styledMode) {
|
|
801
|
+
addEvent(this, 'mouseOver', function () {
|
|
802
|
+
css(this.series.chart.container, { cursor: 'move' });
|
|
803
|
+
});
|
|
804
|
+
addEvent(this, 'mouseOut', function () {
|
|
805
|
+
css(this.series.chart.container, { cursor: 'default' });
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
return this;
|
|
809
|
+
};
|
|
810
|
+
/**
|
|
811
|
+
* @private
|
|
812
|
+
*/
|
|
813
|
+
NetworkgraphPoint.prototype.isValid = function () {
|
|
814
|
+
return !this.isNode || defined(this.id);
|
|
815
|
+
};
|
|
816
|
+
/**
|
|
817
|
+
* Redraw link's path.
|
|
818
|
+
* @private
|
|
819
|
+
*/
|
|
820
|
+
NetworkgraphPoint.prototype.redrawLink = function () {
|
|
821
|
+
var path = this.getLinkPath(),
|
|
822
|
+
attribs;
|
|
823
|
+
if (this.graphic) {
|
|
824
|
+
this.shapeArgs = {
|
|
825
|
+
d: path
|
|
826
|
+
};
|
|
827
|
+
if (!this.series.chart.styledMode) {
|
|
828
|
+
attribs = this.series.pointAttribs(this);
|
|
829
|
+
this.graphic.attr(attribs);
|
|
830
|
+
(this.dataLabels || []).forEach(function (label) {
|
|
831
|
+
if (label) {
|
|
832
|
+
label.attr({
|
|
833
|
+
opacity: attribs.opacity
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
this.graphic.animate(this.shapeArgs);
|
|
839
|
+
// Required for dataLabels
|
|
840
|
+
var start = path[0];
|
|
841
|
+
var end = path[1];
|
|
842
|
+
if (start[0] === 'M' && end[0] === 'L') {
|
|
843
|
+
this.plotX = (start[1] + end[1]) / 2;
|
|
844
|
+
this.plotY = (start[2] + end[2]) / 2;
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
/**
|
|
849
|
+
* Common method for removing points and nodes in networkgraph. To
|
|
850
|
+
* remove `link`, use `series.data[index].remove()`. To remove `node`
|
|
851
|
+
* with all connections, use `series.nodes[index].remove()`.
|
|
852
|
+
* @private
|
|
853
|
+
* @param {boolean} [redraw=true]
|
|
854
|
+
* Whether to redraw the chart or wait for an explicit call. When
|
|
855
|
+
* doing more operations on the chart, for example running
|
|
856
|
+
* `point.remove()` in a loop, it is best practice to set
|
|
857
|
+
* `redraw` to false and call `chart.redraw()` after.
|
|
858
|
+
* @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=false]
|
|
859
|
+
* Whether to apply animation, and optionally animation
|
|
860
|
+
* configuration.
|
|
861
|
+
*/
|
|
862
|
+
NetworkgraphPoint.prototype.remove = function (redraw, animation) {
|
|
863
|
+
var point = this,
|
|
864
|
+
series = point.series,
|
|
865
|
+
nodesOptions = series.options.nodes || [],
|
|
866
|
+
index,
|
|
867
|
+
i = nodesOptions.length;
|
|
868
|
+
// For nodes, remove all connected links:
|
|
869
|
+
if (point.isNode) {
|
|
870
|
+
// Temporary disable series.points array, because
|
|
871
|
+
// Series.removePoint() modifies it
|
|
872
|
+
series.points = [];
|
|
873
|
+
// Remove link from all nodes collections:
|
|
874
|
+
[]
|
|
875
|
+
.concat(point.linksFrom)
|
|
876
|
+
.concat(point.linksTo)
|
|
877
|
+
.forEach(function (linkFromTo) {
|
|
878
|
+
// Incoming links
|
|
879
|
+
index = linkFromTo.fromNode.linksFrom.indexOf(linkFromTo);
|
|
880
|
+
if (index > -1) {
|
|
881
|
+
linkFromTo.fromNode.linksFrom.splice(index, 1);
|
|
882
|
+
}
|
|
883
|
+
// Outcoming links
|
|
884
|
+
index = linkFromTo.toNode.linksTo.indexOf(linkFromTo);
|
|
885
|
+
if (index > -1) {
|
|
886
|
+
linkFromTo.toNode.linksTo.splice(index, 1);
|
|
887
|
+
}
|
|
888
|
+
// Remove link from data/points collections
|
|
889
|
+
seriesProto.removePoint.call(series, series.data.indexOf(linkFromTo), false, false);
|
|
890
|
+
});
|
|
891
|
+
// Restore points array, after links are removed
|
|
892
|
+
series.points = series.data.slice();
|
|
893
|
+
// Proceed with removing node. It's similar to
|
|
894
|
+
// Series.removePoint() method, but doesn't modify other arrays
|
|
895
|
+
series.nodes.splice(series.nodes.indexOf(point), 1);
|
|
896
|
+
// Remove node options from config
|
|
897
|
+
while (i--) {
|
|
898
|
+
if (nodesOptions[i].id === point.options.id) {
|
|
899
|
+
series.options.nodes.splice(i, 1);
|
|
900
|
+
break;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
if (point) {
|
|
904
|
+
point.destroy();
|
|
905
|
+
}
|
|
906
|
+
// Run redraw if requested
|
|
907
|
+
series.isDirty = true;
|
|
908
|
+
series.isDirtyData = true;
|
|
909
|
+
if (redraw) {
|
|
910
|
+
series.chart.redraw(redraw);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
else {
|
|
914
|
+
series.removePoint(series.data.indexOf(point), redraw, animation);
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
/**
|
|
918
|
+
* Render link and add it to the DOM.
|
|
919
|
+
* @private
|
|
920
|
+
*/
|
|
921
|
+
NetworkgraphPoint.prototype.renderLink = function () {
|
|
922
|
+
var attribs;
|
|
923
|
+
if (!this.graphic) {
|
|
924
|
+
this.graphic = this.series.chart.renderer
|
|
925
|
+
.path(this.getLinkPath())
|
|
926
|
+
.addClass(this.getClassName(), true)
|
|
927
|
+
.add(this.series.group);
|
|
928
|
+
if (!this.series.chart.styledMode) {
|
|
929
|
+
attribs = this.series.pointAttribs(this);
|
|
930
|
+
this.graphic.attr(attribs);
|
|
931
|
+
(this.dataLabels || []).forEach(function (label) {
|
|
932
|
+
if (label) {
|
|
933
|
+
label.attr({
|
|
934
|
+
opacity: attribs.opacity
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
return NetworkgraphPoint;
|
|
942
|
+
}(Point));
|
|
943
|
+
extend(NetworkgraphPoint.prototype, {
|
|
944
|
+
setState: NodesComposition.setNodeState
|
|
945
|
+
});
|
|
946
|
+
/* *
|
|
947
|
+
*
|
|
948
|
+
* Default Export
|
|
949
|
+
*
|
|
950
|
+
* */
|
|
951
|
+
|
|
952
|
+
return NetworkgraphPoint;
|
|
953
|
+
});
|
|
954
|
+
_registerModule(_modules, 'Series/Networkgraph/NetworkgraphSeriesDefaults.js', [], function () {
|
|
955
|
+
/* *
|
|
956
|
+
*
|
|
957
|
+
* Networkgraph series
|
|
958
|
+
*
|
|
959
|
+
* (c) 2010-2021 Paweł Fus
|
|
960
|
+
*
|
|
961
|
+
* License: www.highcharts.com/license
|
|
962
|
+
*
|
|
963
|
+
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
964
|
+
*
|
|
965
|
+
* */
|
|
966
|
+
/* *
|
|
967
|
+
*
|
|
968
|
+
* Constants
|
|
969
|
+
*
|
|
970
|
+
* */
|
|
971
|
+
/**
|
|
972
|
+
* A networkgraph is a type of relationship chart, where connnections
|
|
973
|
+
* (links) attracts nodes (points) and other nodes repulse each other.
|
|
974
|
+
*
|
|
975
|
+
* @extends plotOptions.line
|
|
976
|
+
* @product highcharts
|
|
977
|
+
* @sample highcharts/demo/network-graph/
|
|
978
|
+
* Networkgraph
|
|
979
|
+
* @since 7.0.0
|
|
980
|
+
* @excluding boostThreshold, animation, animationLimit, connectEnds,
|
|
981
|
+
* colorAxis, colorKey, connectNulls, cropThreshold, dragDrop,
|
|
982
|
+
* getExtremesFromAll, label, linecap, negativeColor,
|
|
983
|
+
* pointInterval, pointIntervalUnit, pointPlacement,
|
|
984
|
+
* pointStart, softThreshold, stack, stacking, step,
|
|
985
|
+
* threshold, xAxis, yAxis, zoneAxis, dataSorting,
|
|
986
|
+
* boostBlending
|
|
987
|
+
* @requires modules/networkgraph
|
|
988
|
+
* @optionparent plotOptions.networkgraph
|
|
989
|
+
*/
|
|
990
|
+
var NetworkgraphSeriesDefaults = {
|
|
991
|
+
stickyTracking: false,
|
|
992
|
+
/**
|
|
993
|
+
* @ignore-option
|
|
417
994
|
* @private
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
995
|
+
*/
|
|
996
|
+
inactiveOtherPoints: true,
|
|
997
|
+
marker: {
|
|
998
|
+
enabled: true,
|
|
999
|
+
states: {
|
|
1000
|
+
/**
|
|
1001
|
+
* The opposite state of a hover for a single point node.
|
|
1002
|
+
* Applied to all not connected nodes to the hovered one.
|
|
1003
|
+
*
|
|
1004
|
+
* @declare Highcharts.PointStatesInactiveOptionsObject
|
|
1005
|
+
*/
|
|
1006
|
+
inactive: {
|
|
1007
|
+
/**
|
|
1008
|
+
* Opacity of inactive markers.
|
|
1009
|
+
*/
|
|
1010
|
+
opacity: 0.3,
|
|
1011
|
+
/**
|
|
1012
|
+
* Animation when not hovering over the node.
|
|
1013
|
+
*
|
|
1014
|
+
* @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
|
|
1015
|
+
*/
|
|
1016
|
+
animation: {
|
|
1017
|
+
/** @internal */
|
|
1018
|
+
duration: 50
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
},
|
|
1023
|
+
states: {
|
|
1024
|
+
/**
|
|
1025
|
+
* The opposite state of a hover for a single point link. Applied
|
|
1026
|
+
* to all links that are not comming from the hovered node.
|
|
1027
|
+
*
|
|
1028
|
+
* @declare Highcharts.SeriesStatesInactiveOptionsObject
|
|
424
1029
|
*/
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
1030
|
+
inactive: {
|
|
1031
|
+
/**
|
|
1032
|
+
* Opacity of inactive links.
|
|
1033
|
+
*/
|
|
1034
|
+
linkOpacity: 0.3,
|
|
1035
|
+
/**
|
|
1036
|
+
* Animation when not hovering over the node.
|
|
1037
|
+
*
|
|
1038
|
+
* @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
|
|
1039
|
+
*/
|
|
1040
|
+
animation: {
|
|
1041
|
+
/** @internal */
|
|
1042
|
+
duration: 50
|
|
1043
|
+
}
|
|
430
1044
|
}
|
|
431
1045
|
},
|
|
432
1046
|
/**
|
|
433
|
-
*
|
|
1047
|
+
* @sample highcharts/series-networkgraph/link-datalabels
|
|
1048
|
+
* Networkgraph with labels on links
|
|
1049
|
+
* @sample highcharts/series-networkgraph/textpath-datalabels
|
|
1050
|
+
* Networkgraph with labels around nodes
|
|
1051
|
+
* @sample highcharts/series-networkgraph/link-datalabels
|
|
1052
|
+
* Data labels moved into the nodes
|
|
1053
|
+
* @sample highcharts/series-networkgraph/link-datalabels
|
|
1054
|
+
* Data labels moved under the links
|
|
434
1055
|
*
|
|
435
|
-
*
|
|
436
|
-
* `plotX` and `plotY` position.
|
|
1056
|
+
* @declare Highcharts.SeriesNetworkgraphDataLabelsOptionsObject
|
|
437
1057
|
*
|
|
438
1058
|
* @private
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
1059
|
+
*/
|
|
1060
|
+
dataLabels: {
|
|
1061
|
+
/**
|
|
1062
|
+
* The
|
|
1063
|
+
* [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
|
|
1064
|
+
* specifying what to show for _node_ in the networkgraph. In v7.0
|
|
1065
|
+
* defaults to `{key}`,
|
|
1066
|
+
since v7.1 defaults to `undefined` and
|
|
1067
|
+
* `formatter` is used instead.
|
|
1068
|
+
*
|
|
1069
|
+
* @type {string}
|
|
1070
|
+
* @since 7.0.0
|
|
1071
|
+
* @apioption plotOptions.networkgraph.dataLabels.format
|
|
445
1072
|
*/
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
translatedX * massFactor.toNode / link.toNode.degree;
|
|
459
|
-
link.toNode.plotY +=
|
|
460
|
-
translatedY * massFactor.toNode / link.toNode.degree;
|
|
461
|
-
}
|
|
1073
|
+
// eslint-disable-next-line valid-jsdoc
|
|
1074
|
+
/**
|
|
1075
|
+
* Callback JavaScript function to format the data label for a node.
|
|
1076
|
+
* Note that if a `format` is defined,
|
|
1077
|
+
the format takes precedence
|
|
1078
|
+
* and the formatter is ignored.
|
|
1079
|
+
*
|
|
1080
|
+
* @type {Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction}
|
|
1081
|
+
* @since 7.0.0
|
|
1082
|
+
*/
|
|
1083
|
+
formatter: function () {
|
|
1084
|
+
return this.key;
|
|
462
1085
|
},
|
|
463
1086
|
/**
|
|
464
|
-
*
|
|
1087
|
+
* The
|
|
1088
|
+
* [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
|
|
1089
|
+
* specifying what to show for _links_ in the networkgraph.
|
|
1090
|
+
* (Default: `undefined`)
|
|
465
1091
|
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
1092
|
+
* @type {string}
|
|
1093
|
+
* @since 7.1.0
|
|
1094
|
+
* @apioption plotOptions.networkgraph.dataLabels.linkFormat
|
|
1095
|
+
*/
|
|
1096
|
+
// eslint-disable-next-line valid-jsdoc
|
|
1097
|
+
/**
|
|
1098
|
+
* Callback to format data labels for _links_ in the sankey diagram.
|
|
1099
|
+
* The `linkFormat` option takes precedence over the
|
|
1100
|
+
* `linkFormatter`.
|
|
468
1101
|
*
|
|
469
|
-
*
|
|
1102
|
+
* @type {Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction}
|
|
1103
|
+
* @since 7.1.0
|
|
1104
|
+
*/
|
|
1105
|
+
linkFormatter: function () {
|
|
1106
|
+
return (this.point.fromNode.name +
|
|
1107
|
+
'<br>' +
|
|
1108
|
+
this.point.toNode.name);
|
|
1109
|
+
},
|
|
1110
|
+
/**
|
|
1111
|
+
* Options for a _link_ label text which should follow link
|
|
1112
|
+
* connection. Border and background are disabled for a label that
|
|
1113
|
+
* follows a path.
|
|
470
1114
|
*
|
|
471
|
-
*
|
|
1115
|
+
* **Note:** Only SVG-based renderer supports this option. Setting
|
|
1116
|
+
* `useHTML` to true will disable this option.
|
|
472
1117
|
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
|
|
476
|
-
|
|
1118
|
+
* @extends plotOptions.networkgraph.dataLabels.textPath
|
|
1119
|
+
* @since 7.1.0
|
|
1120
|
+
*/
|
|
1121
|
+
linkTextPath: {
|
|
1122
|
+
enabled: true
|
|
1123
|
+
},
|
|
1124
|
+
textPath: {
|
|
1125
|
+
enabled: false
|
|
1126
|
+
},
|
|
1127
|
+
style: {
|
|
1128
|
+
transition: 'opacity 2000ms'
|
|
1129
|
+
}
|
|
1130
|
+
},
|
|
1131
|
+
/**
|
|
1132
|
+
* Link style options
|
|
1133
|
+
* @private
|
|
1134
|
+
*/
|
|
1135
|
+
link: {
|
|
1136
|
+
/**
|
|
1137
|
+
* A name for the dash style to use for links.
|
|
477
1138
|
*
|
|
478
|
-
*
|
|
1139
|
+
* @type {string}
|
|
1140
|
+
* @apioption plotOptions.networkgraph.link.dashStyle
|
|
1141
|
+
*/
|
|
1142
|
+
/**
|
|
1143
|
+
* Opacity of the link between two nodes.
|
|
479
1144
|
*
|
|
480
|
-
*
|
|
1145
|
+
* @type {number}
|
|
1146
|
+
* @default 1
|
|
1147
|
+
* @apioption plotOptions.networkgraph.link.opacity
|
|
1148
|
+
*/
|
|
1149
|
+
/**
|
|
1150
|
+
* Color of the link between two nodes.
|
|
1151
|
+
*/
|
|
1152
|
+
color: 'rgba(100, 100, 100, 0.5)',
|
|
1153
|
+
/**
|
|
1154
|
+
* Width (px) of the link between two nodes.
|
|
1155
|
+
*/
|
|
1156
|
+
width: 1
|
|
1157
|
+
},
|
|
1158
|
+
/**
|
|
1159
|
+
* Flag to determine if nodes are draggable or not.
|
|
1160
|
+
* @private
|
|
1161
|
+
*/
|
|
1162
|
+
draggable: true,
|
|
1163
|
+
layoutAlgorithm: {
|
|
1164
|
+
/**
|
|
1165
|
+
* Repulsive force applied on a node. Passed are two arguments:
|
|
1166
|
+
* - `d` - which is current distance between two nodes
|
|
1167
|
+
* - `k` - which is desired distance between two nodes
|
|
481
1168
|
*
|
|
482
|
-
*
|
|
483
|
-
*
|
|
1169
|
+
* In `verlet` integration, defaults to:
|
|
1170
|
+
* `function (d, k) { return (k - d) / d * (k > d ? 1 : 0) }`
|
|
484
1171
|
*
|
|
485
|
-
*
|
|
486
|
-
* Consider Verlet with velocity to support additional
|
|
487
|
-
* forces. Or even Time-Corrected Verlet by Jonathan
|
|
488
|
-
* "lonesock" Dummer
|
|
1172
|
+
* @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration)
|
|
489
1173
|
*
|
|
490
|
-
* @
|
|
491
|
-
*
|
|
492
|
-
* @
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
prevY = node.prevY,
|
|
499
|
-
// Apply friciton:
|
|
500
|
-
diffX = ((node.plotX + node.dispX -
|
|
501
|
-
prevX) * friction),
|
|
502
|
-
diffY = ((node.plotY + node.dispY -
|
|
503
|
-
prevY) * friction),
|
|
504
|
-
abs = Math.abs,
|
|
505
|
-
signX = abs(diffX) / (diffX || 1), // need to deal with 0
|
|
506
|
-
signY = abs(diffY) / (diffY || 1);
|
|
507
|
-
// Apply max speed:
|
|
508
|
-
diffX = signX * Math.min(maxSpeed, Math.abs(diffX));
|
|
509
|
-
diffY = signY * Math.min(maxSpeed, Math.abs(diffY));
|
|
510
|
-
// Store for the next iteration:
|
|
511
|
-
node.prevX = node.plotX + node.dispX;
|
|
512
|
-
node.prevY = node.plotY + node.dispY;
|
|
513
|
-
// Update positions:
|
|
514
|
-
node.plotX += diffX;
|
|
515
|
-
node.plotY += diffY;
|
|
516
|
-
node.temperature = layout.vectorLength({
|
|
517
|
-
x: diffX,
|
|
518
|
-
y: diffY
|
|
519
|
-
});
|
|
520
|
-
},
|
|
521
|
-
/**
|
|
522
|
-
* Estiamte the best possible distance between two nodes, making graph
|
|
523
|
-
* readable.
|
|
524
|
-
* @private
|
|
1174
|
+
* @sample highcharts/series-networkgraph/forces/
|
|
1175
|
+
* Custom forces with Euler integration
|
|
1176
|
+
* @sample highcharts/series-networkgraph/cuboids/
|
|
1177
|
+
* Custom forces with Verlet integration
|
|
1178
|
+
*
|
|
1179
|
+
* @type {Function}
|
|
1180
|
+
* @default function (d, k) { return k * k / d; }
|
|
1181
|
+
* @apioption plotOptions.networkgraph.layoutAlgorithm.repulsiveForce
|
|
525
1182
|
*/
|
|
526
|
-
getK: function (layout) {
|
|
527
|
-
return Math.pow(layout.box.width * layout.box.height / layout.nodes.length, 0.5);
|
|
528
|
-
}
|
|
529
|
-
},
|
|
530
|
-
euler: {
|
|
531
1183
|
/**
|
|
532
|
-
*
|
|
533
|
-
*
|
|
1184
|
+
* Attraction force applied on a node which is conected to another
|
|
1185
|
+
* node by a link. Passed are two arguments:
|
|
1186
|
+
* - `d` - which is current distance between two nodes
|
|
1187
|
+
* - `k` - which is desired distance between two nodes
|
|
534
1188
|
*
|
|
535
|
-
*
|
|
1189
|
+
* In `verlet` integration, defaults to:
|
|
1190
|
+
* `function (d, k) { return (k - d) / d; }`
|
|
536
1191
|
*
|
|
537
|
-
*
|
|
538
|
-
* `function (d, k) { return d / k }`
|
|
1192
|
+
* @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration)
|
|
539
1193
|
*
|
|
540
|
-
* @
|
|
541
|
-
*
|
|
542
|
-
* @
|
|
543
|
-
*
|
|
1194
|
+
* @sample highcharts/series-networkgraph/forces/
|
|
1195
|
+
* Custom forces with Euler integration
|
|
1196
|
+
* @sample highcharts/series-networkgraph/cuboids/
|
|
1197
|
+
* Custom forces with Verlet integration
|
|
1198
|
+
*
|
|
1199
|
+
* @type {Function}
|
|
1200
|
+
* @default function (d, k) { return k * k / d; }
|
|
1201
|
+
* @apioption plotOptions.networkgraph.layoutAlgorithm.attractiveForce
|
|
544
1202
|
*/
|
|
545
|
-
attractiveForceFunction: function (d, k) {
|
|
546
|
-
return d * d / k;
|
|
547
|
-
},
|
|
548
1203
|
/**
|
|
549
|
-
*
|
|
550
|
-
*
|
|
1204
|
+
* Ideal length (px) of the link between two nodes. When not
|
|
1205
|
+
* defined, length is calculated as:
|
|
1206
|
+
* `Math.pow(availableWidth * availableHeight / nodesLength, 0.4);`
|
|
551
1207
|
*
|
|
552
|
-
*
|
|
1208
|
+
* Note: Because of the algorithm specification, length of each link
|
|
1209
|
+
* might be not exactly as specified.
|
|
553
1210
|
*
|
|
554
|
-
*
|
|
555
|
-
*
|
|
1211
|
+
* @sample highcharts/series-networkgraph/styled-links/
|
|
1212
|
+
* Numerical values
|
|
556
1213
|
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
1214
|
+
* @type {number}
|
|
1215
|
+
* @apioption plotOptions.networkgraph.layoutAlgorithm.linkLength
|
|
1216
|
+
*/
|
|
1217
|
+
/**
|
|
1218
|
+
* Initial layout algorithm for positioning nodes. Can be one of
|
|
1219
|
+
* built-in options ("circle", "random") or a function where
|
|
1220
|
+
* positions should be set on each node (`this.nodes`) as
|
|
1221
|
+
* `node.plotX` and `node.plotY`
|
|
559
1222
|
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
1223
|
+
* @sample highcharts/series-networkgraph/initial-positions/
|
|
1224
|
+
* Initial positions with callback
|
|
562
1225
|
*
|
|
563
|
-
* @
|
|
564
|
-
* @param {number} d current distance between two nodes
|
|
565
|
-
* @param {number} k expected distance between two nodes
|
|
566
|
-
* @return {number} force
|
|
1226
|
+
* @type {"circle"|"random"|Function}
|
|
567
1227
|
*/
|
|
568
|
-
|
|
569
|
-
return k * k / d;
|
|
570
|
-
},
|
|
1228
|
+
initialPositions: 'circle',
|
|
571
1229
|
/**
|
|
572
|
-
*
|
|
573
|
-
*
|
|
1230
|
+
* When `initialPositions` are set to 'circle',
|
|
1231
|
+
* `initialPositionRadius` is a distance from the center of circle,
|
|
1232
|
+
* in which nodes are created.
|
|
574
1233
|
*
|
|
575
|
-
*
|
|
576
|
-
*
|
|
1234
|
+
* @type {number}
|
|
1235
|
+
* @default 1
|
|
1236
|
+
* @since 7.1.0
|
|
1237
|
+
*/
|
|
1238
|
+
initialPositionRadius: 1,
|
|
1239
|
+
/**
|
|
1240
|
+
* Experimental. Enables live simulation of the algorithm
|
|
1241
|
+
* implementation. All nodes are animated as the forces applies on
|
|
1242
|
+
* them.
|
|
577
1243
|
*
|
|
578
|
-
* @
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
xFactor = this.barycenter.xFactor,
|
|
583
|
-
yFactor = this.barycenter.yFactor;
|
|
584
|
-
this.nodes.forEach(function (node) {
|
|
585
|
-
if (!node.fixedPosition) {
|
|
586
|
-
var degree = node.getDegree(),
|
|
587
|
-
phi = degree * (1 + degree / 2);
|
|
588
|
-
node.dispX += ((xFactor - node.plotX) *
|
|
589
|
-
gravitationalConstant *
|
|
590
|
-
phi / node.degree);
|
|
591
|
-
node.dispY += ((yFactor - node.plotY) *
|
|
592
|
-
gravitationalConstant *
|
|
593
|
-
phi / node.degree);
|
|
594
|
-
}
|
|
595
|
-
});
|
|
596
|
-
},
|
|
1244
|
+
* @sample highcharts/demo/network-graph/
|
|
1245
|
+
* Live simulation enabled
|
|
1246
|
+
*/
|
|
1247
|
+
enableSimulation: false,
|
|
597
1248
|
/**
|
|
598
|
-
*
|
|
1249
|
+
* Barnes-Hut approximation only.
|
|
1250
|
+
* Deteremines when distance between cell and node is small enough
|
|
1251
|
+
* to caculate forces. Value of `theta` is compared directly with
|
|
1252
|
+
* quotient `s / d`, where `s` is the size of the cell, and `d` is
|
|
1253
|
+
* distance between center of cell's mass and currently compared
|
|
1254
|
+
* node.
|
|
599
1255
|
*
|
|
600
|
-
* @
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
* @param {Highcharts.PositionObject} distanceXY
|
|
606
|
-
* Distance between two nodes e.g. `{x, y}`
|
|
607
|
-
*/
|
|
608
|
-
repulsive: function (node, force, distanceXY, distanceR) {
|
|
609
|
-
node.dispX +=
|
|
610
|
-
(distanceXY.x / distanceR) * force / node.degree;
|
|
611
|
-
node.dispY +=
|
|
612
|
-
(distanceXY.y / distanceR) * force / node.degree;
|
|
613
|
-
},
|
|
1256
|
+
* @see [layoutAlgorithm.approximation](#series.networkgraph.layoutAlgorithm.approximation)
|
|
1257
|
+
*
|
|
1258
|
+
* @since 7.1.0
|
|
1259
|
+
*/
|
|
1260
|
+
theta: 0.5,
|
|
614
1261
|
/**
|
|
615
|
-
*
|
|
1262
|
+
* Verlet integration only.
|
|
1263
|
+
* Max speed that node can get in one iteration. In terms of
|
|
1264
|
+
* simulation, it's a maximum translation (in pixels) that node can
|
|
1265
|
+
* move (in both, x and y, dimensions). While `friction` is applied
|
|
1266
|
+
* on all nodes, max speed is applied only for nodes that move very
|
|
1267
|
+
* fast, for example small or disconnected ones.
|
|
616
1268
|
*
|
|
617
|
-
*
|
|
618
|
-
*
|
|
1269
|
+
* @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration)
|
|
1270
|
+
* @see [layoutAlgorithm.friction](#series.networkgraph.layoutAlgorithm.friction)
|
|
619
1271
|
*
|
|
620
|
-
* @
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
* @param {number} force
|
|
624
|
-
* Force calcualated in `repulsiveForceFunction`
|
|
625
|
-
* @param {Highcharts.PositionObject} distanceXY
|
|
626
|
-
* Distance between two nodes e.g. `{x, y}`
|
|
627
|
-
* @param {number} distanceR
|
|
628
|
-
*/
|
|
629
|
-
attractive: function (link, force, distanceXY, distanceR) {
|
|
630
|
-
var massFactor = link.getMass(),
|
|
631
|
-
translatedX = (distanceXY.x / distanceR) * force,
|
|
632
|
-
translatedY = (distanceXY.y / distanceR) * force;
|
|
633
|
-
if (!link.fromNode.fixedPosition) {
|
|
634
|
-
link.fromNode.dispX -=
|
|
635
|
-
translatedX * massFactor.fromNode / link.fromNode.degree;
|
|
636
|
-
link.fromNode.dispY -=
|
|
637
|
-
translatedY * massFactor.fromNode / link.fromNode.degree;
|
|
638
|
-
}
|
|
639
|
-
if (!link.toNode.fixedPosition) {
|
|
640
|
-
link.toNode.dispX +=
|
|
641
|
-
translatedX * massFactor.toNode / link.toNode.degree;
|
|
642
|
-
link.toNode.dispY +=
|
|
643
|
-
translatedY * massFactor.toNode / link.toNode.degree;
|
|
644
|
-
}
|
|
645
|
-
},
|
|
1272
|
+
* @since 7.1.0
|
|
1273
|
+
*/
|
|
1274
|
+
maxSpeed: 10,
|
|
646
1275
|
/**
|
|
647
|
-
*
|
|
1276
|
+
* Approximation used to calculate repulsive forces affecting nodes.
|
|
1277
|
+
* By default, when calculateing net force, nodes are compared
|
|
1278
|
+
* against each other, which gives O(N^2) complexity. Using
|
|
1279
|
+
* Barnes-Hut approximation, we decrease this to O(N log N), but the
|
|
1280
|
+
* resulting graph will have different layout. Barnes-Hut
|
|
1281
|
+
* approximation divides space into rectangles via quad tree, where
|
|
1282
|
+
* forces exerted on nodes are calculated directly for nearby cells,
|
|
1283
|
+
* and for all others, cells are treated as a separate node with
|
|
1284
|
+
* center of mass.
|
|
648
1285
|
*
|
|
649
|
-
*
|
|
650
|
-
* position. Now, in the integrator method, we apply changes.
|
|
1286
|
+
* @see [layoutAlgorithm.theta](#series.networkgraph.layoutAlgorithm.theta)
|
|
651
1287
|
*
|
|
652
|
-
*
|
|
1288
|
+
* @sample highcharts/series-networkgraph/barnes-hut-approximation/
|
|
1289
|
+
* A graph with Barnes-Hut approximation
|
|
653
1290
|
*
|
|
654
|
-
*
|
|
1291
|
+
* @type {string}
|
|
1292
|
+
* @validvalue ["barnes-hut", "none"]
|
|
1293
|
+
* @since 7.1.0
|
|
1294
|
+
*/
|
|
1295
|
+
approximation: 'none',
|
|
1296
|
+
/**
|
|
1297
|
+
* Type of the algorithm used when positioning nodes.
|
|
655
1298
|
*
|
|
656
|
-
*
|
|
657
|
-
*
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
*
|
|
662
|
-
*
|
|
1299
|
+
* @type {string}
|
|
1300
|
+
* @validvalue ["reingold-fruchterman"]
|
|
1301
|
+
*/
|
|
1302
|
+
type: 'reingold-fruchterman',
|
|
1303
|
+
/**
|
|
1304
|
+
* Integration type. Available options are `'euler'` and `'verlet'`.
|
|
1305
|
+
* Integration determines how forces are applied on particles. In
|
|
1306
|
+
* Euler integration, force is applied direct as
|
|
1307
|
+
* `newPosition += velocity;`.
|
|
1308
|
+
* In Verlet integration, new position is based on a previous
|
|
1309
|
+
* posittion without velocity:
|
|
1310
|
+
* `newPosition += previousPosition - newPosition`.
|
|
663
1311
|
*
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
* direction in the next step. Potentially solved by decreasing force by
|
|
667
|
-
* `v * (1 / node.degree)`
|
|
1312
|
+
* Note that different integrations give different results as forces
|
|
1313
|
+
* are different.
|
|
668
1314
|
*
|
|
669
|
-
*
|
|
670
|
-
* Actually `min(v(n), temperature(n))` replaces simulated annealing.
|
|
1315
|
+
* In Highcharts v7.0.x only `'euler'` integration was supported.
|
|
671
1316
|
*
|
|
672
|
-
* @
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
* @
|
|
676
|
-
*
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
node.dispX +=
|
|
681
|
-
node.dispX * layout.options.friction;
|
|
682
|
-
node.dispY +=
|
|
683
|
-
node.dispY * layout.options.friction;
|
|
684
|
-
distanceR = node.temperature = layout.vectorLength({
|
|
685
|
-
x: node.dispX,
|
|
686
|
-
y: node.dispY
|
|
687
|
-
});
|
|
688
|
-
if (distanceR !== 0) {
|
|
689
|
-
node.plotX += (node.dispX / distanceR *
|
|
690
|
-
Math.min(Math.abs(node.dispX), layout.temperature));
|
|
691
|
-
node.plotY += (node.dispY / distanceR *
|
|
692
|
-
Math.min(Math.abs(node.dispY), layout.temperature));
|
|
693
|
-
}
|
|
694
|
-
},
|
|
1317
|
+
* @sample highcharts/series-networkgraph/integration-comparison/
|
|
1318
|
+
* Comparison of Verlet and Euler integrations
|
|
1319
|
+
*
|
|
1320
|
+
* @type {string}
|
|
1321
|
+
* @validvalue ["euler", "verlet"]
|
|
1322
|
+
* @since 7.1.0
|
|
1323
|
+
*/
|
|
1324
|
+
integration: 'euler',
|
|
695
1325
|
/**
|
|
696
|
-
*
|
|
697
|
-
*
|
|
698
|
-
*
|
|
1326
|
+
* Max number of iterations before algorithm will stop. In general,
|
|
1327
|
+
* algorithm should find positions sooner, but when rendering huge
|
|
1328
|
+
* number of nodes, it is recommended to increase this value as
|
|
1329
|
+
* finding perfect graph positions can require more time.
|
|
699
1330
|
*/
|
|
700
|
-
|
|
701
|
-
|
|
1331
|
+
maxIterations: 1000,
|
|
1332
|
+
/**
|
|
1333
|
+
* Gravitational const used in the barycenter force of the
|
|
1334
|
+
* algorithm.
|
|
1335
|
+
*
|
|
1336
|
+
* @sample highcharts/series-networkgraph/forces/
|
|
1337
|
+
* Custom forces with Euler integration
|
|
1338
|
+
*/
|
|
1339
|
+
gravitationalConstant: 0.0625,
|
|
1340
|
+
/**
|
|
1341
|
+
* Friction applied on forces to prevent nodes rushing to fast to
|
|
1342
|
+
* the desired positions.
|
|
1343
|
+
*/
|
|
1344
|
+
friction: -0.981
|
|
1345
|
+
},
|
|
1346
|
+
showInLegend: false
|
|
1347
|
+
};
|
|
1348
|
+
/* *
|
|
1349
|
+
*
|
|
1350
|
+
* Default Export
|
|
1351
|
+
*
|
|
1352
|
+
* */
|
|
1353
|
+
/* *
|
|
1354
|
+
*
|
|
1355
|
+
* API Options
|
|
1356
|
+
*
|
|
1357
|
+
* */
|
|
1358
|
+
/**
|
|
1359
|
+
* A `networkgraph` series. If the [type](#series.networkgraph.type) option is
|
|
1360
|
+
* not specified, it is inherited from [chart.type](#chart.type).
|
|
1361
|
+
*
|
|
1362
|
+
* @extends series,plotOptions.networkgraph
|
|
1363
|
+
* @excluding boostThreshold, animation, animationLimit, connectEnds,
|
|
1364
|
+
* connectNulls, cropThreshold, dragDrop, getExtremesFromAll, label,
|
|
1365
|
+
* linecap, negativeColor, pointInterval, pointIntervalUnit,
|
|
1366
|
+
* pointPlacement, pointStart, softThreshold, stack, stacking,
|
|
1367
|
+
* step, threshold, xAxis, yAxis, zoneAxis, dataSorting,
|
|
1368
|
+
* boostBlending
|
|
1369
|
+
* @product highcharts
|
|
1370
|
+
* @requires modules/networkgraph
|
|
1371
|
+
* @apioption series.networkgraph
|
|
1372
|
+
*/
|
|
1373
|
+
/**
|
|
1374
|
+
* An array of data points for the series. For the `networkgraph` series type,
|
|
1375
|
+
* points can be given in the following way:
|
|
1376
|
+
*
|
|
1377
|
+
* An array of objects with named values. The following snippet shows only a
|
|
1378
|
+
* few settings, see the complete options set below. If the total number of
|
|
1379
|
+
* data points exceeds the series'
|
|
1380
|
+
* [turboThreshold](#series.area.turboThreshold), this option is not available.
|
|
1381
|
+
*
|
|
1382
|
+
* ```js
|
|
1383
|
+
* data: [{
|
|
1384
|
+
* from: 'Category1',
|
|
1385
|
+
* to: 'Category2'
|
|
1386
|
+
* }, {
|
|
1387
|
+
* from: 'Category1',
|
|
1388
|
+
* to: 'Category3'
|
|
1389
|
+
* }]
|
|
1390
|
+
* ```
|
|
1391
|
+
*
|
|
1392
|
+
* @type {Array<Object|Array|number>}
|
|
1393
|
+
* @extends series.line.data
|
|
1394
|
+
* @excluding drilldown,marker,x,y,draDrop
|
|
1395
|
+
* @sample {highcharts} highcharts/chart/reflow-true/
|
|
1396
|
+
* Numerical values
|
|
1397
|
+
* @sample {highcharts} highcharts/series/data-array-of-arrays/
|
|
1398
|
+
* Arrays of numeric x and y
|
|
1399
|
+
* @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
|
|
1400
|
+
* Arrays of datetime x and y
|
|
1401
|
+
* @sample {highcharts} highcharts/series/data-array-of-name-value/
|
|
1402
|
+
* Arrays of point.name and y
|
|
1403
|
+
* @sample {highcharts} highcharts/series/data-array-of-objects/
|
|
1404
|
+
* Config objects
|
|
1405
|
+
* @product highcharts
|
|
1406
|
+
* @apioption series.networkgraph.data
|
|
1407
|
+
*/
|
|
1408
|
+
/**
|
|
1409
|
+
* @type {Highcharts.SeriesNetworkgraphDataLabelsOptionsObject|Array<Highcharts.SeriesNetworkgraphDataLabelsOptionsObject>}
|
|
1410
|
+
* @product highcharts
|
|
1411
|
+
* @apioption series.networkgraph.data.dataLabels
|
|
1412
|
+
*/
|
|
1413
|
+
/**
|
|
1414
|
+
* The node that the link runs from.
|
|
1415
|
+
*
|
|
1416
|
+
* @type {string}
|
|
1417
|
+
* @product highcharts
|
|
1418
|
+
* @apioption series.networkgraph.data.from
|
|
1419
|
+
*/
|
|
1420
|
+
/**
|
|
1421
|
+
* The node that the link runs to.
|
|
1422
|
+
*
|
|
1423
|
+
* @type {string}
|
|
1424
|
+
* @product highcharts
|
|
1425
|
+
* @apioption series.networkgraph.data.to
|
|
1426
|
+
*/
|
|
1427
|
+
/**
|
|
1428
|
+
* A collection of options for the individual nodes. The nodes in a
|
|
1429
|
+
* networkgraph diagram are auto-generated instances of `Highcharts.Point`,
|
|
1430
|
+
* but options can be applied here and linked by the `id`.
|
|
1431
|
+
*
|
|
1432
|
+
* @sample highcharts/series-networkgraph/data-options/
|
|
1433
|
+
* Networkgraph diagram with node options
|
|
1434
|
+
*
|
|
1435
|
+
* @type {Array<*>}
|
|
1436
|
+
* @product highcharts
|
|
1437
|
+
* @apioption series.networkgraph.nodes
|
|
1438
|
+
*/
|
|
1439
|
+
/**
|
|
1440
|
+
* The id of the auto-generated node, refering to the `from` or `to` setting of
|
|
1441
|
+
* the link.
|
|
1442
|
+
*
|
|
1443
|
+
* @type {string}
|
|
1444
|
+
* @product highcharts
|
|
1445
|
+
* @apioption series.networkgraph.nodes.id
|
|
1446
|
+
*/
|
|
1447
|
+
/**
|
|
1448
|
+
* The color of the auto generated node.
|
|
1449
|
+
*
|
|
1450
|
+
* @type {Highcharts.ColorString}
|
|
1451
|
+
* @product highcharts
|
|
1452
|
+
* @apioption series.networkgraph.nodes.color
|
|
1453
|
+
*/
|
|
1454
|
+
/**
|
|
1455
|
+
* The color index of the auto generated node, especially for use in styled
|
|
1456
|
+
* mode.
|
|
1457
|
+
*
|
|
1458
|
+
* @type {number}
|
|
1459
|
+
* @product highcharts
|
|
1460
|
+
* @apioption series.networkgraph.nodes.colorIndex
|
|
1461
|
+
*/
|
|
1462
|
+
/**
|
|
1463
|
+
* The name to display for the node in data labels and tooltips. Use this when
|
|
1464
|
+
* the name is different from the `id`. Where the id must be unique for each
|
|
1465
|
+
* node, this is not necessary for the name.
|
|
1466
|
+
*
|
|
1467
|
+
* @sample highcharts/series-networkgraph/data-options/
|
|
1468
|
+
* Networkgraph diagram with node options
|
|
1469
|
+
*
|
|
1470
|
+
* @type {string}
|
|
1471
|
+
* @product highcharts
|
|
1472
|
+
* @apioption series.networkgraph.nodes.name
|
|
1473
|
+
*/
|
|
1474
|
+
/**
|
|
1475
|
+
* Mass of the node. By default, each node has mass equal to it's marker radius
|
|
1476
|
+
* . Mass is used to determine how two connected nodes should affect
|
|
1477
|
+
* each other:
|
|
1478
|
+
*
|
|
1479
|
+
* Attractive force is multiplied by the ratio of two connected
|
|
1480
|
+
* nodes; if a big node has weights twice as the small one, then the small one
|
|
1481
|
+
* will move towards the big one twice faster than the big one to the small one
|
|
1482
|
+
* .
|
|
1483
|
+
*
|
|
1484
|
+
* @sample highcharts/series-networkgraph/ragdoll/
|
|
1485
|
+
* Mass determined by marker.radius
|
|
1486
|
+
*
|
|
1487
|
+
* @type {number}
|
|
1488
|
+
* @product highcharts
|
|
1489
|
+
* @apioption series.networkgraph.nodes.mass
|
|
1490
|
+
*/
|
|
1491
|
+
/**
|
|
1492
|
+
* Individual data label for each node. The options are the same as
|
|
1493
|
+
* the ones for [series.networkgraph.dataLabels](#series.networkgraph.dataLabels).
|
|
1494
|
+
*
|
|
1495
|
+
* @type {Highcharts.SeriesNetworkgraphDataLabelsOptionsObject|Array<Highcharts.SeriesNetworkgraphDataLabelsOptionsObject>}
|
|
1496
|
+
*
|
|
1497
|
+
* @apioption series.networkgraph.nodes.dataLabels
|
|
1498
|
+
*/
|
|
1499
|
+
''; // adds doclets above to transpiled file
|
|
1500
|
+
|
|
1501
|
+
return NetworkgraphSeriesDefaults;
|
|
1502
|
+
});
|
|
1503
|
+
_registerModule(_modules, 'Series/Networkgraph/EulerIntegration.js', [], function () {
|
|
1504
|
+
/* *
|
|
1505
|
+
*
|
|
1506
|
+
* Networkgraph series
|
|
1507
|
+
*
|
|
1508
|
+
* (c) 2010-2021 Paweł Fus
|
|
1509
|
+
*
|
|
1510
|
+
* License: www.highcharts.com/license
|
|
1511
|
+
*
|
|
1512
|
+
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
1513
|
+
*
|
|
1514
|
+
* */
|
|
1515
|
+
/* *
|
|
1516
|
+
*
|
|
1517
|
+
* Functions
|
|
1518
|
+
*
|
|
1519
|
+
* */
|
|
1520
|
+
/**
|
|
1521
|
+
* Attractive force.
|
|
1522
|
+
*
|
|
1523
|
+
* In Euler integration, force is stored in a node, not changing it's
|
|
1524
|
+
* position. Later, in `integrate()` forces are applied on nodes.
|
|
1525
|
+
*
|
|
1526
|
+
* @private
|
|
1527
|
+
* @param {Highcharts.Point} link
|
|
1528
|
+
* Link that connects two nodes
|
|
1529
|
+
* @param {number} force
|
|
1530
|
+
* Force calcualated in `repulsiveForceFunction`
|
|
1531
|
+
* @param {Highcharts.PositionObject} distanceXY
|
|
1532
|
+
* Distance between two nodes e.g. `{x, y}`
|
|
1533
|
+
* @param {number} distanceR
|
|
1534
|
+
*/
|
|
1535
|
+
function attractive(link, force, distanceXY, distanceR) {
|
|
1536
|
+
var massFactor = link.getMass(),
|
|
1537
|
+
translatedX = (distanceXY.x / distanceR) * force,
|
|
1538
|
+
translatedY = (distanceXY.y / distanceR) * force;
|
|
1539
|
+
if (!link.fromNode.fixedPosition) {
|
|
1540
|
+
link.fromNode.dispX -=
|
|
1541
|
+
translatedX * massFactor.fromNode / link.fromNode.degree;
|
|
1542
|
+
link.fromNode.dispY -=
|
|
1543
|
+
translatedY * massFactor.fromNode / link.fromNode.degree;
|
|
1544
|
+
}
|
|
1545
|
+
if (!link.toNode.fixedPosition) {
|
|
1546
|
+
link.toNode.dispX +=
|
|
1547
|
+
translatedX * massFactor.toNode / link.toNode.degree;
|
|
1548
|
+
link.toNode.dispY +=
|
|
1549
|
+
translatedY * massFactor.toNode / link.toNode.degree;
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Attractive force funtion. Can be replaced by API's
|
|
1554
|
+
* `layoutAlgorithm.attractiveForce`
|
|
1555
|
+
*
|
|
1556
|
+
* Other forces that can be used:
|
|
1557
|
+
*
|
|
1558
|
+
* basic, not recommended:
|
|
1559
|
+
* `function (d, k) { return d / k }`
|
|
1560
|
+
*
|
|
1561
|
+
* @private
|
|
1562
|
+
* @param {number} d current distance between two nodes
|
|
1563
|
+
* @param {number} k expected distance between two nodes
|
|
1564
|
+
* @return {number} force
|
|
1565
|
+
*/
|
|
1566
|
+
function attractiveForceFunction(d, k) {
|
|
1567
|
+
return d * d / k;
|
|
1568
|
+
}
|
|
1569
|
+
/**
|
|
1570
|
+
* Barycenter force. Calculate and applys barycenter forces on the
|
|
1571
|
+
* nodes. Making them closer to the center of their barycenter point.
|
|
1572
|
+
*
|
|
1573
|
+
* In Euler integration, force is stored in a node, not changing it's
|
|
1574
|
+
* position. Later, in `integrate()` forces are applied on nodes.
|
|
1575
|
+
*
|
|
1576
|
+
* @private
|
|
1577
|
+
*/
|
|
1578
|
+
function barycenter() {
|
|
1579
|
+
var gravitationalConstant = this.options.gravitationalConstant,
|
|
1580
|
+
xFactor = this.barycenter.xFactor,
|
|
1581
|
+
yFactor = this.barycenter.yFactor;
|
|
1582
|
+
this.nodes.forEach(function (node) {
|
|
1583
|
+
if (!node.fixedPosition) {
|
|
1584
|
+
var degree = node.getDegree(),
|
|
1585
|
+
phi = degree * (1 + degree / 2);
|
|
1586
|
+
node.dispX += ((xFactor - node.plotX) *
|
|
1587
|
+
gravitationalConstant *
|
|
1588
|
+
phi / node.degree);
|
|
1589
|
+
node.dispY += ((yFactor - node.plotY) *
|
|
1590
|
+
gravitationalConstant *
|
|
1591
|
+
phi / node.degree);
|
|
702
1592
|
}
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
/**
|
|
1596
|
+
* Estiamte the best possible distance between two nodes, making graph
|
|
1597
|
+
* readable.
|
|
1598
|
+
* @private
|
|
1599
|
+
*/
|
|
1600
|
+
function getK(layout) {
|
|
1601
|
+
return Math.pow(layout.box.width * layout.box.height / layout.nodes.length, 0.3);
|
|
1602
|
+
}
|
|
1603
|
+
/**
|
|
1604
|
+
* Integration method.
|
|
1605
|
+
*
|
|
1606
|
+
* In Euler integration, force were stored in a node, not changing it's
|
|
1607
|
+
* position. Now, in the integrator method, we apply changes.
|
|
1608
|
+
*
|
|
1609
|
+
* Euler:
|
|
1610
|
+
*
|
|
1611
|
+
* Basic form: `x(n+1) = x(n) + v(n)`
|
|
1612
|
+
*
|
|
1613
|
+
* With Rengoild-Fruchterman we get:
|
|
1614
|
+
* `x(n+1) = x(n) + v(n) / length(v(n)) * min(v(n), temperature(n))`
|
|
1615
|
+
* where:
|
|
1616
|
+
* - `x(n+1)`: next position
|
|
1617
|
+
* - `x(n)`: current position
|
|
1618
|
+
* - `v(n)`: velocity (comes from net force)
|
|
1619
|
+
* - `temperature(n)`: current temperature
|
|
1620
|
+
*
|
|
1621
|
+
* Known issues:
|
|
1622
|
+
* Oscillations when force vector has the same magnitude but opposite
|
|
1623
|
+
* direction in the next step. Potentially solved by decreasing force by
|
|
1624
|
+
* `v * (1 / node.degree)`
|
|
1625
|
+
*
|
|
1626
|
+
* Note:
|
|
1627
|
+
* Actually `min(v(n), temperature(n))` replaces simulated annealing.
|
|
1628
|
+
*
|
|
1629
|
+
* @private
|
|
1630
|
+
* @param {Highcharts.NetworkgraphLayout} layout
|
|
1631
|
+
* Layout object
|
|
1632
|
+
* @param {Highcharts.Point} node
|
|
1633
|
+
* Node that should be translated
|
|
1634
|
+
*/
|
|
1635
|
+
function integrate(layout, node) {
|
|
1636
|
+
var distanceR;
|
|
1637
|
+
node.dispX +=
|
|
1638
|
+
node.dispX * layout.options.friction;
|
|
1639
|
+
node.dispY +=
|
|
1640
|
+
node.dispY * layout.options.friction;
|
|
1641
|
+
distanceR = node.temperature = layout.vectorLength({
|
|
1642
|
+
x: node.dispX,
|
|
1643
|
+
y: node.dispY
|
|
1644
|
+
});
|
|
1645
|
+
if (distanceR !== 0) {
|
|
1646
|
+
node.plotX += (node.dispX / distanceR *
|
|
1647
|
+
Math.min(Math.abs(node.dispX), layout.temperature));
|
|
1648
|
+
node.plotY += (node.dispY / distanceR *
|
|
1649
|
+
Math.min(Math.abs(node.dispY), layout.temperature));
|
|
703
1650
|
}
|
|
704
|
-
}
|
|
1651
|
+
}
|
|
1652
|
+
/**
|
|
1653
|
+
* Repulsive force.
|
|
1654
|
+
*
|
|
1655
|
+
* @private
|
|
1656
|
+
* @param {Highcharts.Point} node
|
|
1657
|
+
* Node that should be translated by force.
|
|
1658
|
+
* @param {number} force
|
|
1659
|
+
* Force calcualated in `repulsiveForceFunction`
|
|
1660
|
+
* @param {Highcharts.PositionObject} distanceXY
|
|
1661
|
+
* Distance between two nodes e.g. `{x, y}`
|
|
1662
|
+
*/
|
|
1663
|
+
function repulsive(node, force, distanceXY, distanceR) {
|
|
1664
|
+
node.dispX +=
|
|
1665
|
+
(distanceXY.x / distanceR) * force / node.degree;
|
|
1666
|
+
node.dispY +=
|
|
1667
|
+
(distanceXY.y / distanceR) * force / node.degree;
|
|
1668
|
+
}
|
|
1669
|
+
/**
|
|
1670
|
+
* Repulsive force funtion. Can be replaced by API's
|
|
1671
|
+
* `layoutAlgorithm.repulsiveForce`.
|
|
1672
|
+
*
|
|
1673
|
+
* Other forces that can be used:
|
|
1674
|
+
*
|
|
1675
|
+
* basic, not recommended:
|
|
1676
|
+
* `function (d, k) { return k / d }`
|
|
1677
|
+
*
|
|
1678
|
+
* standard:
|
|
1679
|
+
* `function (d, k) { return k * k / d }`
|
|
1680
|
+
*
|
|
1681
|
+
* grid-variant:
|
|
1682
|
+
* `function (d, k) { return k * k / d * (2 * k - d > 0 ? 1 : 0) }`
|
|
1683
|
+
*
|
|
1684
|
+
* @private
|
|
1685
|
+
* @param {number} d current distance between two nodes
|
|
1686
|
+
* @param {number} k expected distance between two nodes
|
|
1687
|
+
* @return {number} force
|
|
1688
|
+
*/
|
|
1689
|
+
function repulsiveForceFunction(d, k) {
|
|
1690
|
+
return k * k / d;
|
|
1691
|
+
}
|
|
1692
|
+
/* *
|
|
1693
|
+
*
|
|
1694
|
+
* Default Export
|
|
1695
|
+
*
|
|
1696
|
+
* */
|
|
1697
|
+
var EulerIntegration = {
|
|
1698
|
+
attractive: attractive,
|
|
1699
|
+
attractiveForceFunction: attractiveForceFunction,
|
|
1700
|
+
barycenter: barycenter,
|
|
1701
|
+
getK: getK,
|
|
1702
|
+
integrate: integrate,
|
|
1703
|
+
repulsive: repulsive,
|
|
1704
|
+
repulsiveForceFunction: repulsiveForceFunction
|
|
1705
|
+
};
|
|
705
1706
|
|
|
1707
|
+
return EulerIntegration;
|
|
706
1708
|
});
|
|
707
|
-
_registerModule(_modules, 'Series/Networkgraph/
|
|
1709
|
+
_registerModule(_modules, 'Series/Networkgraph/QuadTreeNode.js', [], function () {
|
|
708
1710
|
/* *
|
|
709
1711
|
*
|
|
710
1712
|
* Networkgraph series
|
|
@@ -716,8 +1718,11 @@
|
|
|
716
1718
|
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
717
1719
|
*
|
|
718
1720
|
* */
|
|
719
|
-
|
|
720
|
-
|
|
1721
|
+
/* *
|
|
1722
|
+
*
|
|
1723
|
+
* Class
|
|
1724
|
+
*
|
|
1725
|
+
* */
|
|
721
1726
|
/**
|
|
722
1727
|
* The QuadTree node class. Used in Networkgraph chart as a base for Barnes-Hut
|
|
723
1728
|
* approximation.
|
|
@@ -726,9 +1731,56 @@
|
|
|
726
1731
|
* @class
|
|
727
1732
|
* @name Highcharts.QuadTreeNode
|
|
728
1733
|
*
|
|
729
|
-
* @param {Highcharts.Dictionary<number>} box
|
|
1734
|
+
* @param {Highcharts.Dictionary<number>} box
|
|
1735
|
+
* Available space for the node
|
|
730
1736
|
*/
|
|
731
|
-
var QuadTreeNode =
|
|
1737
|
+
var QuadTreeNode = /** @class */ (function () {
|
|
1738
|
+
/* *
|
|
1739
|
+
*
|
|
1740
|
+
* Constructor
|
|
1741
|
+
*
|
|
1742
|
+
* */
|
|
1743
|
+
function QuadTreeNode(box) {
|
|
1744
|
+
/* *
|
|
1745
|
+
*
|
|
1746
|
+
* Properties
|
|
1747
|
+
*
|
|
1748
|
+
* */
|
|
1749
|
+
/**
|
|
1750
|
+
* Read only. If QuadTreeNode is an external node, Point is stored in
|
|
1751
|
+
* `this.body`.
|
|
1752
|
+
*
|
|
1753
|
+
* @name Highcharts.QuadTreeNode#body
|
|
1754
|
+
* @type {boolean|Highcharts.Point}
|
|
1755
|
+
*/
|
|
1756
|
+
this.body = false;
|
|
1757
|
+
/**
|
|
1758
|
+
* Read only. Internal nodes when created are empty to reserve the
|
|
1759
|
+
* space. If Point is added to this QuadTreeNode, QuadTreeNode is no
|
|
1760
|
+
* longer empty.
|
|
1761
|
+
*
|
|
1762
|
+
* @name Highcharts.QuadTreeNode#isEmpty
|
|
1763
|
+
* @type {boolean}
|
|
1764
|
+
*/
|
|
1765
|
+
this.isEmpty = false;
|
|
1766
|
+
/**
|
|
1767
|
+
* Read only. Flag to determine if QuadTreeNode is internal (and has
|
|
1768
|
+
* subnodes with mass and central position) or external (bound to
|
|
1769
|
+
* Point).
|
|
1770
|
+
*
|
|
1771
|
+
* @name Highcharts.QuadTreeNode#isInternal
|
|
1772
|
+
* @type {boolean}
|
|
1773
|
+
*/
|
|
1774
|
+
this.isInternal = false;
|
|
1775
|
+
/**
|
|
1776
|
+
* Read only. Array of subnodes. Empty if QuadTreeNode has just one
|
|
1777
|
+
* Point. When added another Point to this QuadTreeNode, array is
|
|
1778
|
+
* filled with four subnodes.
|
|
1779
|
+
*
|
|
1780
|
+
* @name Highcharts.QuadTreeNode#nodes
|
|
1781
|
+
* @type {Array<Highcharts.QuadTreeNode>}
|
|
1782
|
+
*/
|
|
1783
|
+
this.nodes = [];
|
|
732
1784
|
/**
|
|
733
1785
|
* Read only. The available space for node.
|
|
734
1786
|
*
|
|
@@ -736,50 +1788,99 @@
|
|
|
736
1788
|
* @type {Highcharts.Dictionary<number>}
|
|
737
1789
|
*/
|
|
738
1790
|
this.box = box;
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
* When added another Point to this QuadTreeNode, array is filled with four
|
|
749
|
-
* subnodes.
|
|
1791
|
+
/**
|
|
1792
|
+
* Read only. The minium of width and height values.
|
|
1793
|
+
*
|
|
1794
|
+
* @name Highcharts.QuadTreeNode#boxSize
|
|
1795
|
+
* @type {number}
|
|
1796
|
+
*/
|
|
1797
|
+
this.boxSize = Math.min(box.width, box.height);
|
|
1798
|
+
}
|
|
1799
|
+
/* *
|
|
750
1800
|
*
|
|
751
|
-
*
|
|
752
|
-
* @type {Array<Highcharts.QuadTreeNode>}
|
|
753
|
-
*/
|
|
754
|
-
this.nodes = [];
|
|
755
|
-
/**
|
|
756
|
-
* Read only. Flag to determine if QuadTreeNode is internal (and has
|
|
757
|
-
* subnodes with mass and central position) or external (bound to Point).
|
|
1801
|
+
* Functions
|
|
758
1802
|
*
|
|
759
|
-
*
|
|
760
|
-
* @type {boolean}
|
|
761
|
-
*/
|
|
762
|
-
this.isInternal = false;
|
|
1803
|
+
* */
|
|
763
1804
|
/**
|
|
764
|
-
*
|
|
765
|
-
*
|
|
1805
|
+
* When inserting another node into the box, that already hove one node,
|
|
1806
|
+
* divide the available space into another four quadrants.
|
|
766
1807
|
*
|
|
767
|
-
*
|
|
768
|
-
*
|
|
1808
|
+
* Indexes of quadrants are:
|
|
1809
|
+
* ```
|
|
1810
|
+
* ------------- -------------
|
|
1811
|
+
* | | | | |
|
|
1812
|
+
* | | | 0 | 1 |
|
|
1813
|
+
* | | divide() | | |
|
|
1814
|
+
* | 1 | -----------> -------------
|
|
1815
|
+
* | | | | |
|
|
1816
|
+
* | | | 3 | 2 |
|
|
1817
|
+
* | | | | |
|
|
1818
|
+
* ------------- -------------
|
|
1819
|
+
* ```
|
|
769
1820
|
*/
|
|
770
|
-
|
|
1821
|
+
QuadTreeNode.prototype.divideBox = function () {
|
|
1822
|
+
var halfWidth = this.box.width / 2,
|
|
1823
|
+
halfHeight = this.box.height / 2;
|
|
1824
|
+
// Top left
|
|
1825
|
+
this.nodes[0] = new QuadTreeNode({
|
|
1826
|
+
left: this.box.left,
|
|
1827
|
+
top: this.box.top,
|
|
1828
|
+
width: halfWidth,
|
|
1829
|
+
height: halfHeight
|
|
1830
|
+
});
|
|
1831
|
+
// Top right
|
|
1832
|
+
this.nodes[1] = new QuadTreeNode({
|
|
1833
|
+
left: this.box.left + halfWidth,
|
|
1834
|
+
top: this.box.top,
|
|
1835
|
+
width: halfWidth,
|
|
1836
|
+
height: halfHeight
|
|
1837
|
+
});
|
|
1838
|
+
// Bottom right
|
|
1839
|
+
this.nodes[2] = new QuadTreeNode({
|
|
1840
|
+
left: this.box.left + halfWidth,
|
|
1841
|
+
top: this.box.top + halfHeight,
|
|
1842
|
+
width: halfWidth,
|
|
1843
|
+
height: halfHeight
|
|
1844
|
+
});
|
|
1845
|
+
// Bottom left
|
|
1846
|
+
this.nodes[3] = new QuadTreeNode({
|
|
1847
|
+
left: this.box.left,
|
|
1848
|
+
top: this.box.top + halfHeight,
|
|
1849
|
+
width: halfWidth,
|
|
1850
|
+
height: halfHeight
|
|
1851
|
+
});
|
|
1852
|
+
};
|
|
771
1853
|
/**
|
|
772
|
-
*
|
|
773
|
-
*
|
|
774
|
-
*
|
|
775
|
-
* @name Highcharts.QuadTreeNode#isEmpty
|
|
776
|
-
* @type {boolean}
|
|
1854
|
+
* Determine which of the quadrants should be used when placing node in
|
|
1855
|
+
* the QuadTree. Returned index is always in range `< 0 , 3 >`.
|
|
1856
|
+
* @private
|
|
777
1857
|
*/
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
1858
|
+
QuadTreeNode.prototype.getBoxPosition = function (point) {
|
|
1859
|
+
var left = point.plotX < this.box.left + this.box.width / 2,
|
|
1860
|
+
top = point.plotY < this.box.top + this.box.height / 2;
|
|
1861
|
+
var index;
|
|
1862
|
+
if (left) {
|
|
1863
|
+
if (top) {
|
|
1864
|
+
// Top left
|
|
1865
|
+
index = 0;
|
|
1866
|
+
}
|
|
1867
|
+
else {
|
|
1868
|
+
// Bottom left
|
|
1869
|
+
index = 3;
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
else {
|
|
1873
|
+
if (top) {
|
|
1874
|
+
// Top right
|
|
1875
|
+
index = 1;
|
|
1876
|
+
}
|
|
1877
|
+
else {
|
|
1878
|
+
// Bottom right
|
|
1879
|
+
index = 2;
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
return index;
|
|
1883
|
+
};
|
|
783
1884
|
/**
|
|
784
1885
|
* Insert recursively point(node) into the QuadTree. If the given
|
|
785
1886
|
* quadrant is already occupied, divide it into smaller quadrants.
|
|
@@ -789,7 +1890,7 @@
|
|
|
789
1890
|
* @param {number} depth
|
|
790
1891
|
* Max depth of the QuadTree
|
|
791
1892
|
*/
|
|
792
|
-
insert
|
|
1893
|
+
QuadTreeNode.prototype.insert = function (point, depth) {
|
|
793
1894
|
var newQuadTreeNode;
|
|
794
1895
|
if (this.isInternal) {
|
|
795
1896
|
// Internal node:
|
|
@@ -827,8 +1928,8 @@
|
|
|
827
1928
|
// position, but that could result in different
|
|
828
1929
|
// rendered chart in exporting.
|
|
829
1930
|
newQuadTreeNode = new QuadTreeNode({
|
|
830
|
-
top: point.plotX,
|
|
831
|
-
left: point.plotY,
|
|
1931
|
+
top: point.plotX || NaN,
|
|
1932
|
+
left: point.plotY || NaN,
|
|
832
1933
|
// Width/height below 1px
|
|
833
1934
|
width: 0.1,
|
|
834
1935
|
height: 0.1
|
|
@@ -839,26 +1940,25 @@
|
|
|
839
1940
|
}
|
|
840
1941
|
}
|
|
841
1942
|
}
|
|
842
|
-
}
|
|
1943
|
+
};
|
|
843
1944
|
/**
|
|
844
1945
|
* Each quad node requires it's mass and center position. That mass and
|
|
845
1946
|
* position is used to imitate real node in the layout by approximation.
|
|
846
1947
|
*/
|
|
847
|
-
updateMassAndCenter
|
|
1948
|
+
QuadTreeNode.prototype.updateMassAndCenter = function () {
|
|
848
1949
|
var mass = 0,
|
|
849
1950
|
plotX = 0,
|
|
850
1951
|
plotY = 0;
|
|
851
1952
|
if (this.isInternal) {
|
|
852
1953
|
// Calcualte weightened mass of the quad node:
|
|
853
|
-
this.nodes.
|
|
1954
|
+
for (var _i = 0, _a = this.nodes; _i < _a.length; _i++) {
|
|
1955
|
+
var pointMass = _a[_i];
|
|
854
1956
|
if (!pointMass.isEmpty) {
|
|
855
1957
|
mass += pointMass.mass;
|
|
856
|
-
plotX +=
|
|
857
|
-
|
|
858
|
-
plotY +=
|
|
859
|
-
pointMass.plotY * pointMass.mass;
|
|
1958
|
+
plotX += pointMass.plotX * pointMass.mass;
|
|
1959
|
+
plotY += pointMass.plotY * pointMass.mass;
|
|
860
1960
|
}
|
|
861
|
-
}
|
|
1961
|
+
}
|
|
862
1962
|
plotX /= mass;
|
|
863
1963
|
plotY /= mass;
|
|
864
1964
|
}
|
|
@@ -872,88 +1972,34 @@
|
|
|
872
1972
|
this.mass = mass;
|
|
873
1973
|
this.plotX = plotX;
|
|
874
1974
|
this.plotY = plotY;
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
// Top right
|
|
904
|
-
this.nodes[1] = new QuadTreeNode({
|
|
905
|
-
left: this.box.left + halfWidth,
|
|
906
|
-
top: this.box.top,
|
|
907
|
-
width: halfWidth,
|
|
908
|
-
height: halfHeight
|
|
909
|
-
});
|
|
910
|
-
// Bottom right
|
|
911
|
-
this.nodes[2] = new QuadTreeNode({
|
|
912
|
-
left: this.box.left + halfWidth,
|
|
913
|
-
top: this.box.top + halfHeight,
|
|
914
|
-
width: halfWidth,
|
|
915
|
-
height: halfHeight
|
|
916
|
-
});
|
|
917
|
-
// Bottom left
|
|
918
|
-
this.nodes[3] = new QuadTreeNode({
|
|
919
|
-
left: this.box.left,
|
|
920
|
-
top: this.box.top + halfHeight,
|
|
921
|
-
width: halfWidth,
|
|
922
|
-
height: halfHeight
|
|
923
|
-
});
|
|
924
|
-
},
|
|
925
|
-
/**
|
|
926
|
-
* Determine which of the quadrants should be used when placing node in
|
|
927
|
-
* the QuadTree. Returned index is always in range `< 0 , 3 >`.
|
|
928
|
-
* @private
|
|
929
|
-
*/
|
|
930
|
-
getBoxPosition: function (point) {
|
|
931
|
-
var left = point.plotX < this.box.left + this.box.width / 2,
|
|
932
|
-
top = point.plotY < this.box.top + this.box.height / 2,
|
|
933
|
-
index;
|
|
934
|
-
if (left) {
|
|
935
|
-
if (top) {
|
|
936
|
-
// Top left
|
|
937
|
-
index = 0;
|
|
938
|
-
}
|
|
939
|
-
else {
|
|
940
|
-
// Bottom left
|
|
941
|
-
index = 3;
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
else {
|
|
945
|
-
if (top) {
|
|
946
|
-
// Top right
|
|
947
|
-
index = 1;
|
|
948
|
-
}
|
|
949
|
-
else {
|
|
950
|
-
// Bottom right
|
|
951
|
-
index = 2;
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
return index;
|
|
955
|
-
}
|
|
956
|
-
});
|
|
1975
|
+
};
|
|
1976
|
+
return QuadTreeNode;
|
|
1977
|
+
}());
|
|
1978
|
+
/* *
|
|
1979
|
+
*
|
|
1980
|
+
* Default Export
|
|
1981
|
+
*
|
|
1982
|
+
* */
|
|
1983
|
+
|
|
1984
|
+
return QuadTreeNode;
|
|
1985
|
+
});
|
|
1986
|
+
_registerModule(_modules, 'Series/Networkgraph/QuadTree.js', [_modules['Series/Networkgraph/QuadTreeNode.js']], function (QuadTreeNode) {
|
|
1987
|
+
/* *
|
|
1988
|
+
*
|
|
1989
|
+
* Networkgraph series
|
|
1990
|
+
*
|
|
1991
|
+
* (c) 2010-2021 Paweł Fus
|
|
1992
|
+
*
|
|
1993
|
+
* License: www.highcharts.com/license
|
|
1994
|
+
*
|
|
1995
|
+
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
1996
|
+
*
|
|
1997
|
+
* */
|
|
1998
|
+
/* *
|
|
1999
|
+
*
|
|
2000
|
+
* Class
|
|
2001
|
+
*
|
|
2002
|
+
* */
|
|
957
2003
|
/**
|
|
958
2004
|
* The QuadTree class. Used in Networkgraph chart as a base for Barnes-Hut
|
|
959
2005
|
* approximation.
|
|
@@ -962,41 +2008,60 @@
|
|
|
962
2008
|
* @class
|
|
963
2009
|
* @name Highcharts.QuadTree
|
|
964
2010
|
*
|
|
965
|
-
* @param {number} x
|
|
966
|
-
*
|
|
967
|
-
* @param {number}
|
|
968
|
-
*
|
|
2011
|
+
* @param {number} x
|
|
2012
|
+
* Left position of the plotting area
|
|
2013
|
+
* @param {number} y
|
|
2014
|
+
* Top position of the plotting area
|
|
2015
|
+
* @param {number} width
|
|
2016
|
+
* Width of the plotting area
|
|
2017
|
+
* @param {number} height
|
|
2018
|
+
* Height of the plotting area
|
|
969
2019
|
*/
|
|
970
|
-
var QuadTree =
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
2020
|
+
var QuadTree = /** @class */ (function () {
|
|
2021
|
+
/* *
|
|
2022
|
+
*
|
|
2023
|
+
* Constructor
|
|
2024
|
+
*
|
|
2025
|
+
* */
|
|
2026
|
+
function QuadTree(x, y, width, height) {
|
|
2027
|
+
// Boundary rectangle:
|
|
2028
|
+
this.box = {
|
|
2029
|
+
left: x,
|
|
2030
|
+
top: y,
|
|
2031
|
+
width: width,
|
|
2032
|
+
height: height
|
|
2033
|
+
};
|
|
2034
|
+
this.maxDepth = 25;
|
|
2035
|
+
this.root = new QuadTreeNode(this.box);
|
|
2036
|
+
this.root.isInternal = true;
|
|
2037
|
+
this.root.isRoot = true;
|
|
2038
|
+
this.root.divideBox();
|
|
2039
|
+
}
|
|
2040
|
+
/* *
|
|
2041
|
+
*
|
|
2042
|
+
* Functions
|
|
2043
|
+
*
|
|
2044
|
+
* */
|
|
2045
|
+
/**
|
|
2046
|
+
* Calculate mass of the each QuadNode in the tree.
|
|
2047
|
+
*/
|
|
2048
|
+
QuadTree.prototype.calculateMassAndCenter = function () {
|
|
2049
|
+
this.visitNodeRecursive(null, null, function (node) {
|
|
2050
|
+
node.updateMassAndCenter();
|
|
2051
|
+
});
|
|
2052
|
+
};
|
|
990
2053
|
/**
|
|
991
2054
|
* Insert nodes into the QuadTree
|
|
992
2055
|
*
|
|
993
2056
|
* @param {Array<Highcharts.Point>} points
|
|
2057
|
+
* Points as nodes
|
|
994
2058
|
*/
|
|
995
|
-
insertNodes
|
|
996
|
-
points.
|
|
2059
|
+
QuadTree.prototype.insertNodes = function (points) {
|
|
2060
|
+
for (var _i = 0, points_1 = points; _i < points_1.length; _i++) {
|
|
2061
|
+
var point = points_1[_i];
|
|
997
2062
|
this.root.insert(point, this.maxDepth);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
2063
|
+
}
|
|
2064
|
+
};
|
|
1000
2065
|
/**
|
|
1001
2066
|
* Depfth first treversal (DFS). Using `before` and `after` callbacks,
|
|
1002
2067
|
* we can get two results: preorder and postorder traversals, reminder:
|
|
@@ -1014,12 +2079,13 @@
|
|
|
1014
2079
|
* DFS (postorder): `d -> e -> b -> c -> a`
|
|
1015
2080
|
*
|
|
1016
2081
|
* @param {Highcharts.QuadTreeNode|null} node
|
|
1017
|
-
*
|
|
1018
|
-
*
|
|
1019
|
-
*
|
|
1020
|
-
*
|
|
2082
|
+
* QuadTree node
|
|
2083
|
+
* @param {Function} [beforeCallback]
|
|
2084
|
+
* Function to be called before visiting children nodes.
|
|
2085
|
+
* @param {Function} [afterCallback]
|
|
2086
|
+
* Function to be called after visiting children nodes.
|
|
1021
2087
|
*/
|
|
1022
|
-
visitNodeRecursive
|
|
2088
|
+
QuadTree.prototype.visitNodeRecursive = function (node, beforeCallback, afterCallback) {
|
|
1023
2089
|
var goFurther;
|
|
1024
2090
|
if (!node) {
|
|
1025
2091
|
node = this.root;
|
|
@@ -1030,13 +2096,14 @@
|
|
|
1030
2096
|
if (goFurther === false) {
|
|
1031
2097
|
return;
|
|
1032
2098
|
}
|
|
1033
|
-
node.nodes.
|
|
2099
|
+
for (var _i = 0, _a = node.nodes; _i < _a.length; _i++) {
|
|
2100
|
+
var qtNode = _a[_i];
|
|
1034
2101
|
if (qtNode.isInternal) {
|
|
1035
2102
|
if (beforeCallback) {
|
|
1036
2103
|
goFurther = beforeCallback(qtNode);
|
|
1037
2104
|
}
|
|
1038
2105
|
if (goFurther === false) {
|
|
1039
|
-
|
|
2106
|
+
continue;
|
|
1040
2107
|
}
|
|
1041
2108
|
this.visitNodeRecursive(qtNode, beforeCallback, afterCallback);
|
|
1042
2109
|
}
|
|
@@ -1048,23 +2115,227 @@
|
|
|
1048
2115
|
if (afterCallback) {
|
|
1049
2116
|
afterCallback(qtNode);
|
|
1050
2117
|
}
|
|
1051
|
-
}
|
|
2118
|
+
}
|
|
1052
2119
|
if (node === this.root && afterCallback) {
|
|
1053
2120
|
afterCallback(node);
|
|
1054
2121
|
}
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
2122
|
+
};
|
|
2123
|
+
return QuadTree;
|
|
2124
|
+
}());
|
|
2125
|
+
/* *
|
|
2126
|
+
*
|
|
2127
|
+
* Default Export
|
|
2128
|
+
*
|
|
2129
|
+
* */
|
|
2130
|
+
|
|
2131
|
+
return QuadTree;
|
|
2132
|
+
});
|
|
2133
|
+
_registerModule(_modules, 'Series/Networkgraph/VerletIntegration.js', [], function () {
|
|
2134
|
+
/* *
|
|
2135
|
+
*
|
|
2136
|
+
* Networkgraph series
|
|
2137
|
+
*
|
|
2138
|
+
* (c) 2010-2021 Paweł Fus
|
|
2139
|
+
*
|
|
2140
|
+
* License: www.highcharts.com/license
|
|
2141
|
+
*
|
|
2142
|
+
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
2143
|
+
*
|
|
2144
|
+
* */
|
|
2145
|
+
/* *
|
|
2146
|
+
*
|
|
2147
|
+
* Functions
|
|
2148
|
+
*
|
|
2149
|
+
* */
|
|
2150
|
+
/**
|
|
2151
|
+
* Attractive force.
|
|
2152
|
+
*
|
|
2153
|
+
* In Verlet integration, force is applied on a node immidatelly to it's
|
|
2154
|
+
* `plotX` and `plotY` position.
|
|
2155
|
+
*
|
|
2156
|
+
* @private
|
|
2157
|
+
* @param {Highcharts.Point} link
|
|
2158
|
+
* Link that connects two nodes
|
|
2159
|
+
* @param {number} force
|
|
2160
|
+
* Force calcualated in `repulsiveForceFunction`
|
|
2161
|
+
* @param {Highcharts.PositionObject} distance
|
|
2162
|
+
* Distance between two nodes e.g. `{x, y}`
|
|
2163
|
+
*/
|
|
2164
|
+
function attractive(link, force, distanceXY) {
|
|
2165
|
+
var massFactor = link.getMass(),
|
|
2166
|
+
translatedX = -distanceXY.x * force * this.diffTemperature,
|
|
2167
|
+
translatedY = -distanceXY.y * force * this.diffTemperature;
|
|
2168
|
+
if (!link.fromNode.fixedPosition) {
|
|
2169
|
+
link.fromNode.plotX -=
|
|
2170
|
+
translatedX * massFactor.fromNode / link.fromNode.degree;
|
|
2171
|
+
link.fromNode.plotY -=
|
|
2172
|
+
translatedY * massFactor.fromNode / link.fromNode.degree;
|
|
1063
2173
|
}
|
|
1064
|
-
|
|
2174
|
+
if (!link.toNode.fixedPosition) {
|
|
2175
|
+
link.toNode.plotX +=
|
|
2176
|
+
translatedX * massFactor.toNode / link.toNode.degree;
|
|
2177
|
+
link.toNode.plotY +=
|
|
2178
|
+
translatedY * massFactor.toNode / link.toNode.degree;
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
/**
|
|
2182
|
+
* Attractive force funtion. Can be replaced by API's
|
|
2183
|
+
* `layoutAlgorithm.attractiveForce`
|
|
2184
|
+
*
|
|
2185
|
+
* @private
|
|
2186
|
+
* @param {number} d current distance between two nodes
|
|
2187
|
+
* @param {number} k expected distance between two nodes
|
|
2188
|
+
* @return {number} force
|
|
2189
|
+
*/
|
|
2190
|
+
function attractiveForceFunction(d, k) {
|
|
2191
|
+
// Used in API:
|
|
2192
|
+
return (k - d) / d;
|
|
2193
|
+
}
|
|
2194
|
+
/**
|
|
2195
|
+
* Barycenter force. Calculate and applys barycenter forces on the
|
|
2196
|
+
* nodes. Making them closer to the center of their barycenter point.
|
|
2197
|
+
*
|
|
2198
|
+
* In Verlet integration, force is applied on a node immidatelly to it's
|
|
2199
|
+
* `plotX` and `plotY` position.
|
|
2200
|
+
*
|
|
2201
|
+
* @private
|
|
2202
|
+
*/
|
|
2203
|
+
function barycenter() {
|
|
2204
|
+
var gravitationalConstant = this.options.gravitationalConstant,
|
|
2205
|
+
xFactor = this.barycenter.xFactor,
|
|
2206
|
+
yFactor = this.barycenter.yFactor;
|
|
2207
|
+
// To consider:
|
|
2208
|
+
xFactor = (xFactor - (this.box.left + this.box.width) / 2) *
|
|
2209
|
+
gravitationalConstant;
|
|
2210
|
+
yFactor = (yFactor - (this.box.top + this.box.height) / 2) *
|
|
2211
|
+
gravitationalConstant;
|
|
2212
|
+
this.nodes.forEach(function (node) {
|
|
2213
|
+
if (!node.fixedPosition) {
|
|
2214
|
+
node.plotX -=
|
|
2215
|
+
xFactor / node.mass / node.degree;
|
|
2216
|
+
node.plotY -=
|
|
2217
|
+
yFactor / node.mass / node.degree;
|
|
2218
|
+
}
|
|
2219
|
+
});
|
|
2220
|
+
}
|
|
2221
|
+
/**
|
|
2222
|
+
* Estiamte the best possible distance between two nodes, making graph
|
|
2223
|
+
* readable.
|
|
2224
|
+
* @private
|
|
2225
|
+
*/
|
|
2226
|
+
function getK(layout) {
|
|
2227
|
+
return Math.pow(layout.box.width * layout.box.height / layout.nodes.length, 0.5);
|
|
2228
|
+
}
|
|
2229
|
+
/**
|
|
2230
|
+
* Integration method.
|
|
2231
|
+
*
|
|
2232
|
+
* In Verlet integration, forces are applied on node immidatelly to it's
|
|
2233
|
+
* `plotX` and `plotY` position.
|
|
2234
|
+
*
|
|
2235
|
+
* Verlet without velocity:
|
|
2236
|
+
*
|
|
2237
|
+
* x(n+1) = 2 * x(n) - x(n-1) + A(T) * deltaT ^ 2
|
|
2238
|
+
*
|
|
2239
|
+
* where:
|
|
2240
|
+
* - x(n+1) - new position
|
|
2241
|
+
* - x(n) - current position
|
|
2242
|
+
* - x(n-1) - previous position
|
|
2243
|
+
*
|
|
2244
|
+
* Assuming A(t) = 0 (no acceleration) and (deltaT = 1) we get:
|
|
2245
|
+
*
|
|
2246
|
+
* x(n+1) = x(n) + (x(n) - x(n-1))
|
|
2247
|
+
*
|
|
2248
|
+
* where:
|
|
2249
|
+
* - (x(n) - x(n-1)) - position change
|
|
2250
|
+
*
|
|
2251
|
+
* TO DO:
|
|
2252
|
+
* Consider Verlet with velocity to support additional
|
|
2253
|
+
* forces. Or even Time-Corrected Verlet by Jonathan
|
|
2254
|
+
* "lonesock" Dummer
|
|
2255
|
+
*
|
|
2256
|
+
* @private
|
|
2257
|
+
* @param {Highcharts.NetworkgraphLayout} layout layout object
|
|
2258
|
+
* @param {Highcharts.Point} node node that should be translated
|
|
2259
|
+
*/
|
|
2260
|
+
function integrate(layout, node) {
|
|
2261
|
+
var friction = -layout.options.friction,
|
|
2262
|
+
maxSpeed = layout.options.maxSpeed,
|
|
2263
|
+
prevX = node.prevX,
|
|
2264
|
+
prevY = node.prevY,
|
|
2265
|
+
// Apply friciton:
|
|
2266
|
+
diffX = ((node.plotX + node.dispX -
|
|
2267
|
+
prevX) * friction),
|
|
2268
|
+
diffY = ((node.plotY + node.dispY -
|
|
2269
|
+
prevY) * friction),
|
|
2270
|
+
abs = Math.abs,
|
|
2271
|
+
signX = abs(diffX) / (diffX || 1), // need to deal with 0
|
|
2272
|
+
signY = abs(diffY) / (diffY || 1);
|
|
2273
|
+
// Apply max speed:
|
|
2274
|
+
diffX = signX * Math.min(maxSpeed, Math.abs(diffX));
|
|
2275
|
+
diffY = signY * Math.min(maxSpeed, Math.abs(diffY));
|
|
2276
|
+
// Store for the next iteration:
|
|
2277
|
+
node.prevX = node.plotX + node.dispX;
|
|
2278
|
+
node.prevY = node.plotY + node.dispY;
|
|
2279
|
+
// Update positions:
|
|
2280
|
+
node.plotX += diffX;
|
|
2281
|
+
node.plotY += diffY;
|
|
2282
|
+
node.temperature = layout.vectorLength({
|
|
2283
|
+
x: diffX,
|
|
2284
|
+
y: diffY
|
|
2285
|
+
});
|
|
2286
|
+
}
|
|
2287
|
+
/**
|
|
2288
|
+
* Repulsive force.
|
|
2289
|
+
*
|
|
2290
|
+
* In Verlet integration, force is applied on a node immidatelly to it's
|
|
2291
|
+
* `plotX` and `plotY` position.
|
|
2292
|
+
*
|
|
2293
|
+
* @private
|
|
2294
|
+
* @param {Highcharts.Point} node
|
|
2295
|
+
* Node that should be translated by force.
|
|
2296
|
+
* @param {number} force
|
|
2297
|
+
* Force calcualated in `repulsiveForceFunction`
|
|
2298
|
+
* @param {Highcharts.PositionObject} distance
|
|
2299
|
+
* Distance between two nodes e.g. `{x, y}`
|
|
2300
|
+
*/
|
|
2301
|
+
function repulsive(node, force, distanceXY) {
|
|
2302
|
+
var factor = force * this.diffTemperature / node.mass / node.degree;
|
|
2303
|
+
if (!node.fixedPosition) {
|
|
2304
|
+
node.plotX += distanceXY.x * factor;
|
|
2305
|
+
node.plotY += distanceXY.y * factor;
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
/**
|
|
2309
|
+
* Repulsive force funtion. Can be replaced by API's
|
|
2310
|
+
* `layoutAlgorithm.repulsiveForce`
|
|
2311
|
+
*
|
|
2312
|
+
* @private
|
|
2313
|
+
* @param {number} d current distance between two nodes
|
|
2314
|
+
* @param {number} k expected distance between two nodes
|
|
2315
|
+
* @return {number} force
|
|
2316
|
+
*/
|
|
2317
|
+
function repulsiveForceFunction(d, k) {
|
|
2318
|
+
// Used in API:
|
|
2319
|
+
return (k - d) / d * (k > d ? 1 : 0); // Force only for close nodes
|
|
2320
|
+
}
|
|
2321
|
+
/* *
|
|
2322
|
+
*
|
|
2323
|
+
* Default Export
|
|
2324
|
+
*
|
|
2325
|
+
* */
|
|
2326
|
+
var VerletIntegration = {
|
|
2327
|
+
attractive: attractive,
|
|
2328
|
+
attractiveForceFunction: attractiveForceFunction,
|
|
2329
|
+
barycenter: barycenter,
|
|
2330
|
+
getK: getK,
|
|
2331
|
+
integrate: integrate,
|
|
2332
|
+
repulsive: repulsive,
|
|
2333
|
+
repulsiveForceFunction: repulsiveForceFunction
|
|
2334
|
+
};
|
|
1065
2335
|
|
|
2336
|
+
return VerletIntegration;
|
|
1066
2337
|
});
|
|
1067
|
-
_registerModule(_modules, 'Series/Networkgraph/
|
|
2338
|
+
_registerModule(_modules, 'Series/Networkgraph/ReingoldFruchtermanLayout.js', [_modules['Series/Networkgraph/EulerIntegration.js'], _modules['Core/Globals.js'], _modules['Series/GraphLayoutComposition.js'], _modules['Series/Networkgraph/QuadTree.js'], _modules['Core/Utilities.js'], _modules['Series/Networkgraph/VerletIntegration.js']], function (EulerIntegration, H, GraphLayout, QuadTree, U, VerletIntegration) {
|
|
1068
2339
|
/* *
|
|
1069
2340
|
*
|
|
1070
2341
|
* Networkgraph series
|
|
@@ -1076,26 +2347,49 @@
|
|
|
1076
2347
|
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
1077
2348
|
*
|
|
1078
2349
|
* */
|
|
1079
|
-
var
|
|
1080
|
-
var
|
|
1081
|
-
clamp = U.clamp,
|
|
2350
|
+
var win = H.win;
|
|
2351
|
+
var clamp = U.clamp,
|
|
1082
2352
|
defined = U.defined,
|
|
1083
|
-
extend = U.extend,
|
|
1084
2353
|
isFunction = U.isFunction,
|
|
1085
2354
|
pick = U.pick;
|
|
1086
|
-
/*
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
extend(
|
|
2355
|
+
/* *
|
|
2356
|
+
*
|
|
2357
|
+
* Class
|
|
2358
|
+
*
|
|
2359
|
+
* */
|
|
1092
2360
|
/**
|
|
1093
2361
|
* Reingold-Fruchterman algorithm from
|
|
1094
2362
|
* "Graph Drawing by Force-directed Placement" paper.
|
|
1095
2363
|
* @private
|
|
1096
2364
|
*/
|
|
1097
|
-
|
|
1098
|
-
|
|
2365
|
+
var ReingoldFruchtermanLayout = /** @class */ (function () {
|
|
2366
|
+
function ReingoldFruchtermanLayout() {
|
|
2367
|
+
/* *
|
|
2368
|
+
*
|
|
2369
|
+
* Static Functions
|
|
2370
|
+
*
|
|
2371
|
+
* */
|
|
2372
|
+
this.attractiveForce = void 0;
|
|
2373
|
+
this.box = {};
|
|
2374
|
+
this.currentStep = 0;
|
|
2375
|
+
this.initialRendering = true;
|
|
2376
|
+
this.integration = void 0;
|
|
2377
|
+
this.links = [];
|
|
2378
|
+
this.nodes = [];
|
|
2379
|
+
this.options = void 0;
|
|
2380
|
+
this.quadTree = void 0;
|
|
2381
|
+
this.repulsiveForce = void 0;
|
|
2382
|
+
this.series = [];
|
|
2383
|
+
this.simulation = false;
|
|
2384
|
+
}
|
|
2385
|
+
ReingoldFruchtermanLayout.compose = function (ChartClass) {
|
|
2386
|
+
GraphLayout.compose(ChartClass);
|
|
2387
|
+
GraphLayout.integrations.euler = EulerIntegration;
|
|
2388
|
+
GraphLayout.integrations.verlet = VerletIntegration;
|
|
2389
|
+
GraphLayout.layouts['reingold-fruchterman'] =
|
|
2390
|
+
ReingoldFruchtermanLayout;
|
|
2391
|
+
};
|
|
2392
|
+
ReingoldFruchtermanLayout.prototype.init = function (options) {
|
|
1099
2393
|
this.options = options;
|
|
1100
2394
|
this.nodes = [];
|
|
1101
2395
|
this.links = [];
|
|
@@ -1108,16 +2402,16 @@
|
|
|
1108
2402
|
};
|
|
1109
2403
|
this.setInitialRendering(true);
|
|
1110
2404
|
this.integration =
|
|
1111
|
-
|
|
2405
|
+
GraphLayout.integrations[options.integration];
|
|
1112
2406
|
this.enableSimulation = options.enableSimulation;
|
|
1113
2407
|
this.attractiveForce = pick(options.attractiveForce, this.integration.attractiveForceFunction);
|
|
1114
2408
|
this.repulsiveForce = pick(options.repulsiveForce, this.integration.repulsiveForceFunction);
|
|
1115
2409
|
this.approximation = options.approximation;
|
|
1116
|
-
}
|
|
1117
|
-
updateSimulation
|
|
2410
|
+
};
|
|
2411
|
+
ReingoldFruchtermanLayout.prototype.updateSimulation = function (enable) {
|
|
1118
2412
|
this.enableSimulation = pick(enable, this.options.enableSimulation);
|
|
1119
|
-
}
|
|
1120
|
-
start
|
|
2413
|
+
};
|
|
2414
|
+
ReingoldFruchtermanLayout.prototype.start = function () {
|
|
1121
2415
|
var layout = this,
|
|
1122
2416
|
series = this.series,
|
|
1123
2417
|
options = this.options;
|
|
@@ -1137,93 +2431,94 @@
|
|
|
1137
2431
|
if (layout.enableSimulation) {
|
|
1138
2432
|
layout.step();
|
|
1139
2433
|
}
|
|
1140
|
-
}
|
|
1141
|
-
step
|
|
1142
|
-
var
|
|
1143
|
-
|
|
1144
|
-
|
|
2434
|
+
};
|
|
2435
|
+
ReingoldFruchtermanLayout.prototype.step = function () {
|
|
2436
|
+
var _this = this;
|
|
2437
|
+
var anyLayout = this,
|
|
2438
|
+
allSeries = this.series;
|
|
1145
2439
|
// Algorithm:
|
|
1146
|
-
|
|
1147
|
-
if (
|
|
1148
|
-
|
|
1149
|
-
|
|
2440
|
+
this.currentStep++;
|
|
2441
|
+
if (this.approximation === 'barnes-hut') {
|
|
2442
|
+
this.createQuadTree();
|
|
2443
|
+
this.quadTree.calculateMassAndCenter();
|
|
2444
|
+
}
|
|
2445
|
+
for (var _i = 0, _a = this.forces || []; _i < _a.length; _i++) {
|
|
2446
|
+
var forceName = _a[_i];
|
|
2447
|
+
anyLayout[forceName + 'Forces'](this.temperature);
|
|
1150
2448
|
}
|
|
1151
|
-
layout.forces.forEach(function (forceName) {
|
|
1152
|
-
layout[forceName + 'Forces'](layout.temperature);
|
|
1153
|
-
});
|
|
1154
2449
|
// Limit to the plotting area and cool down:
|
|
1155
|
-
|
|
2450
|
+
this.applyLimits();
|
|
1156
2451
|
// Cool down the system:
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
if (
|
|
1161
|
-
|
|
2452
|
+
this.temperature = this.coolDown(this.startTemperature, this.diffTemperature, this.currentStep);
|
|
2453
|
+
this.prevSystemTemperature = this.systemTemperature;
|
|
2454
|
+
this.systemTemperature = this.getSystemTemperature();
|
|
2455
|
+
if (this.enableSimulation) {
|
|
2456
|
+
for (var _b = 0, allSeries_1 = allSeries; _b < allSeries_1.length; _b++) {
|
|
2457
|
+
var series = allSeries_1[_b];
|
|
1162
2458
|
// Chart could be destroyed during the simulation
|
|
1163
|
-
if (
|
|
1164
|
-
|
|
2459
|
+
if (series.chart) {
|
|
2460
|
+
series.render();
|
|
1165
2461
|
}
|
|
1166
|
-
}
|
|
1167
|
-
if (
|
|
1168
|
-
isFinite(
|
|
1169
|
-
!
|
|
1170
|
-
if (
|
|
1171
|
-
|
|
2462
|
+
}
|
|
2463
|
+
if (this.maxIterations-- &&
|
|
2464
|
+
isFinite(this.temperature) &&
|
|
2465
|
+
!this.isStable()) {
|
|
2466
|
+
if (this.simulation) {
|
|
2467
|
+
win.cancelAnimationFrame(this.simulation);
|
|
1172
2468
|
}
|
|
1173
|
-
|
|
1174
|
-
layout.step();
|
|
1175
|
-
});
|
|
2469
|
+
this.simulation = win.requestAnimationFrame(function () { return _this.step(); });
|
|
1176
2470
|
}
|
|
1177
2471
|
else {
|
|
1178
|
-
|
|
2472
|
+
this.simulation = false;
|
|
1179
2473
|
}
|
|
1180
2474
|
}
|
|
1181
|
-
}
|
|
1182
|
-
stop
|
|
2475
|
+
};
|
|
2476
|
+
ReingoldFruchtermanLayout.prototype.stop = function () {
|
|
1183
2477
|
if (this.simulation) {
|
|
1184
|
-
|
|
2478
|
+
win.cancelAnimationFrame(this.simulation);
|
|
1185
2479
|
}
|
|
1186
|
-
}
|
|
1187
|
-
setArea
|
|
2480
|
+
};
|
|
2481
|
+
ReingoldFruchtermanLayout.prototype.setArea = function (x, y, w, h) {
|
|
1188
2482
|
this.box = {
|
|
1189
2483
|
left: x,
|
|
1190
2484
|
top: y,
|
|
1191
2485
|
width: w,
|
|
1192
2486
|
height: h
|
|
1193
2487
|
};
|
|
1194
|
-
}
|
|
1195
|
-
setK
|
|
2488
|
+
};
|
|
2489
|
+
ReingoldFruchtermanLayout.prototype.setK = function () {
|
|
1196
2490
|
// Optimal distance between nodes,
|
|
1197
2491
|
// available space around the node:
|
|
1198
2492
|
this.k = this.options.linkLength || this.integration.getK(this);
|
|
1199
|
-
}
|
|
1200
|
-
addElementsToCollection
|
|
1201
|
-
elements.
|
|
1202
|
-
|
|
1203
|
-
|
|
2493
|
+
};
|
|
2494
|
+
ReingoldFruchtermanLayout.prototype.addElementsToCollection = function (elements, collection) {
|
|
2495
|
+
for (var _i = 0, elements_1 = elements; _i < elements_1.length; _i++) {
|
|
2496
|
+
var element = elements_1[_i];
|
|
2497
|
+
if (collection.indexOf(element) === -1) {
|
|
2498
|
+
collection.push(element);
|
|
1204
2499
|
}
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
removeElementFromCollection
|
|
2500
|
+
}
|
|
2501
|
+
};
|
|
2502
|
+
ReingoldFruchtermanLayout.prototype.removeElementFromCollection = function (element, collection) {
|
|
1208
2503
|
var index = collection.indexOf(element);
|
|
1209
2504
|
if (index !== -1) {
|
|
1210
2505
|
collection.splice(index, 1);
|
|
1211
2506
|
}
|
|
1212
|
-
}
|
|
1213
|
-
clear
|
|
2507
|
+
};
|
|
2508
|
+
ReingoldFruchtermanLayout.prototype.clear = function () {
|
|
1214
2509
|
this.nodes.length = 0;
|
|
1215
2510
|
this.links.length = 0;
|
|
1216
2511
|
this.series.length = 0;
|
|
1217
2512
|
this.resetSimulation();
|
|
1218
|
-
}
|
|
1219
|
-
resetSimulation
|
|
2513
|
+
};
|
|
2514
|
+
ReingoldFruchtermanLayout.prototype.resetSimulation = function () {
|
|
1220
2515
|
this.forcedStop = false;
|
|
1221
2516
|
this.systemTemperature = 0;
|
|
1222
2517
|
this.setMaxIterations();
|
|
1223
2518
|
this.setTemperature();
|
|
1224
2519
|
this.setDiffTemperature();
|
|
1225
|
-
}
|
|
1226
|
-
restartSimulation
|
|
2520
|
+
};
|
|
2521
|
+
ReingoldFruchtermanLayout.prototype.restartSimulation = function () {
|
|
1227
2522
|
if (!this.simulation) {
|
|
1228
2523
|
// When dragging nodes, we don't need to calculate
|
|
1229
2524
|
// initial positions and rendering nodes:
|
|
@@ -1246,30 +2541,31 @@
|
|
|
1246
2541
|
// Extend current simulation:
|
|
1247
2542
|
this.resetSimulation();
|
|
1248
2543
|
}
|
|
1249
|
-
}
|
|
1250
|
-
setMaxIterations
|
|
2544
|
+
};
|
|
2545
|
+
ReingoldFruchtermanLayout.prototype.setMaxIterations = function (maxIterations) {
|
|
1251
2546
|
this.maxIterations = pick(maxIterations, this.options.maxIterations);
|
|
1252
|
-
}
|
|
1253
|
-
setTemperature
|
|
2547
|
+
};
|
|
2548
|
+
ReingoldFruchtermanLayout.prototype.setTemperature = function () {
|
|
1254
2549
|
this.temperature = this.startTemperature =
|
|
1255
2550
|
Math.sqrt(this.nodes.length);
|
|
1256
|
-
}
|
|
1257
|
-
setDiffTemperature
|
|
2551
|
+
};
|
|
2552
|
+
ReingoldFruchtermanLayout.prototype.setDiffTemperature = function () {
|
|
1258
2553
|
this.diffTemperature = this.startTemperature /
|
|
1259
2554
|
(this.options.maxIterations + 1);
|
|
1260
|
-
}
|
|
1261
|
-
setInitialRendering
|
|
2555
|
+
};
|
|
2556
|
+
ReingoldFruchtermanLayout.prototype.setInitialRendering = function (enable) {
|
|
1262
2557
|
this.initialRendering = enable;
|
|
1263
|
-
}
|
|
1264
|
-
createQuadTree
|
|
1265
|
-
this.quadTree = new
|
|
2558
|
+
};
|
|
2559
|
+
ReingoldFruchtermanLayout.prototype.createQuadTree = function () {
|
|
2560
|
+
this.quadTree = new QuadTree(this.box.left, this.box.top, this.box.width, this.box.height);
|
|
1266
2561
|
this.quadTree.insertNodes(this.nodes);
|
|
1267
|
-
}
|
|
1268
|
-
initPositions
|
|
2562
|
+
};
|
|
2563
|
+
ReingoldFruchtermanLayout.prototype.initPositions = function () {
|
|
1269
2564
|
var initialPositions = this.options.initialPositions;
|
|
1270
2565
|
if (isFunction(initialPositions)) {
|
|
1271
2566
|
initialPositions.call(this);
|
|
1272
|
-
this.nodes.
|
|
2567
|
+
for (var _i = 0, _a = this.nodes; _i < _a.length; _i++) {
|
|
2568
|
+
var node = _a[_i];
|
|
1273
2569
|
if (!defined(node.prevX)) {
|
|
1274
2570
|
node.prevX = node.plotX;
|
|
1275
2571
|
}
|
|
@@ -1278,7 +2574,7 @@
|
|
|
1278
2574
|
}
|
|
1279
2575
|
node.dispX = 0;
|
|
1280
2576
|
node.dispY = 0;
|
|
1281
|
-
}
|
|
2577
|
+
}
|
|
1282
2578
|
}
|
|
1283
2579
|
else if (initialPositions === 'circle') {
|
|
1284
2580
|
this.setCircularPositions();
|
|
@@ -1286,93 +2582,103 @@
|
|
|
1286
2582
|
else {
|
|
1287
2583
|
this.setRandomPositions();
|
|
1288
2584
|
}
|
|
1289
|
-
}
|
|
1290
|
-
setCircularPositions
|
|
2585
|
+
};
|
|
2586
|
+
ReingoldFruchtermanLayout.prototype.setCircularPositions = function () {
|
|
1291
2587
|
var box = this.box,
|
|
1292
2588
|
nodes = this.nodes,
|
|
1293
2589
|
nodesLength = nodes.length + 1,
|
|
1294
2590
|
angle = 2 * Math.PI / nodesLength,
|
|
1295
2591
|
rootNodes = nodes.filter(function (node) {
|
|
1296
2592
|
return node.linksTo.length === 0;
|
|
1297
|
-
}),
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
*/
|
|
1301
|
-
function addToNodes(node) {
|
|
1302
|
-
node.linksFrom.forEach(function (link) {
|
|
2593
|
+
}), visitedNodes = {}, radius = this.options.initialPositionRadius, addToNodes = function (node) {
|
|
2594
|
+
for (var _i = 0, _a = node.linksFrom || []; _i < _a.length; _i++) {
|
|
2595
|
+
var link = _a[_i];
|
|
1303
2596
|
if (!visitedNodes[link.toNode.id]) {
|
|
1304
2597
|
visitedNodes[link.toNode.id] = true;
|
|
1305
2598
|
sortedNodes.push(link.toNode);
|
|
1306
2599
|
addToNodes(link.toNode);
|
|
1307
2600
|
}
|
|
1308
|
-
}
|
|
1309
|
-
}
|
|
2601
|
+
}
|
|
2602
|
+
};
|
|
2603
|
+
var sortedNodes = [];
|
|
1310
2604
|
// Start with identified root nodes an sort the nodes by their
|
|
1311
2605
|
// hierarchy. In trees, this ensures that branches don't cross
|
|
1312
2606
|
// eachother.
|
|
1313
|
-
rootNodes.
|
|
2607
|
+
for (var _i = 0, rootNodes_1 = rootNodes; _i < rootNodes_1.length; _i++) {
|
|
2608
|
+
var rootNode = rootNodes_1[_i];
|
|
1314
2609
|
sortedNodes.push(rootNode);
|
|
1315
2610
|
addToNodes(rootNode);
|
|
1316
|
-
}
|
|
2611
|
+
}
|
|
1317
2612
|
// Cyclic tree, no root node found
|
|
1318
2613
|
if (!sortedNodes.length) {
|
|
1319
2614
|
sortedNodes = nodes;
|
|
1320
2615
|
// Dangling, cyclic trees
|
|
1321
2616
|
}
|
|
1322
2617
|
else {
|
|
1323
|
-
nodes.
|
|
1324
|
-
|
|
1325
|
-
|
|
2618
|
+
for (var _a = 0, nodes_1 = nodes; _a < nodes_1.length; _a++) {
|
|
2619
|
+
var node_1 = nodes_1[_a];
|
|
2620
|
+
if (sortedNodes.indexOf(node_1) === -1) {
|
|
2621
|
+
sortedNodes.push(node_1);
|
|
1326
2622
|
}
|
|
1327
|
-
}
|
|
2623
|
+
}
|
|
1328
2624
|
}
|
|
2625
|
+
var node;
|
|
1329
2626
|
// Initial positions are laid out along a small circle, appearing
|
|
1330
2627
|
// as a cluster in the middle
|
|
1331
|
-
|
|
1332
|
-
node
|
|
1333
|
-
node.
|
|
2628
|
+
for (var i = 0, iEnd = sortedNodes.length; i < iEnd; ++i) {
|
|
2629
|
+
node = sortedNodes[i];
|
|
2630
|
+
node.plotX = node.prevX = pick(node.plotX, box.width / 2 + radius * Math.cos(i * angle));
|
|
2631
|
+
node.plotY = node.prevY = pick(node.plotY, box.height / 2 + radius * Math.sin(i * angle));
|
|
1334
2632
|
node.dispX = 0;
|
|
1335
2633
|
node.dispY = 0;
|
|
1336
|
-
}
|
|
1337
|
-
}
|
|
1338
|
-
setRandomPositions
|
|
2634
|
+
}
|
|
2635
|
+
};
|
|
2636
|
+
ReingoldFruchtermanLayout.prototype.setRandomPositions = function () {
|
|
1339
2637
|
var box = this.box,
|
|
1340
2638
|
nodes = this.nodes,
|
|
1341
|
-
nodesLength = nodes.length + 1
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
2639
|
+
nodesLength = nodes.length + 1,
|
|
2640
|
+
/**
|
|
2641
|
+
* Return a repeatable,
|
|
2642
|
+
quasi-random number based on an integer
|
|
2643
|
+
* input. For the initial positions
|
|
2644
|
+
* @private
|
|
2645
|
+
*/
|
|
2646
|
+
unrandom = function (n) {
|
|
2647
|
+
var rand = n * n / Math.PI;
|
|
1349
2648
|
rand = rand - Math.floor(rand);
|
|
1350
2649
|
return rand;
|
|
1351
|
-
}
|
|
2650
|
+
};
|
|
2651
|
+
var node;
|
|
1352
2652
|
// Initial positions:
|
|
1353
|
-
|
|
1354
|
-
node
|
|
1355
|
-
node.
|
|
2653
|
+
for (var i = 0, iEnd = nodes.length; i < iEnd; ++i) {
|
|
2654
|
+
node = nodes[i];
|
|
2655
|
+
node.plotX = node.prevX = pick(node.plotX, box.width * unrandom(i));
|
|
2656
|
+
node.plotY = node.prevY = pick(node.plotY, box.height * unrandom(nodesLength + i));
|
|
1356
2657
|
node.dispX = 0;
|
|
1357
2658
|
node.dispY = 0;
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
force
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
2659
|
+
}
|
|
2660
|
+
};
|
|
2661
|
+
ReingoldFruchtermanLayout.prototype.force = function (name) {
|
|
2662
|
+
var args = [];
|
|
2663
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
2664
|
+
args[_i - 1] = arguments[_i];
|
|
2665
|
+
}
|
|
2666
|
+
this.integration[name].apply(this, args);
|
|
2667
|
+
};
|
|
2668
|
+
ReingoldFruchtermanLayout.prototype.barycenterForces = function () {
|
|
1364
2669
|
this.getBarycenter();
|
|
1365
2670
|
this.force('barycenter');
|
|
1366
|
-
}
|
|
1367
|
-
getBarycenter
|
|
2671
|
+
};
|
|
2672
|
+
ReingoldFruchtermanLayout.prototype.getBarycenter = function () {
|
|
1368
2673
|
var systemMass = 0,
|
|
1369
2674
|
cx = 0,
|
|
1370
2675
|
cy = 0;
|
|
1371
|
-
this.nodes.
|
|
2676
|
+
for (var _i = 0, _a = this.nodes; _i < _a.length; _i++) {
|
|
2677
|
+
var node = _a[_i];
|
|
1372
2678
|
cx += node.plotX * node.mass;
|
|
1373
2679
|
cy += node.plotY * node.mass;
|
|
1374
2680
|
systemMass += node.mass;
|
|
1375
|
-
}
|
|
2681
|
+
}
|
|
1376
2682
|
this.barycenter = {
|
|
1377
2683
|
x: cx,
|
|
1378
2684
|
y: cy,
|
|
@@ -1380,23 +2686,22 @@
|
|
|
1380
2686
|
yFactor: cy / systemMass
|
|
1381
2687
|
};
|
|
1382
2688
|
return this.barycenter;
|
|
1383
|
-
}
|
|
1384
|
-
barnesHutApproximation
|
|
1385
|
-
var
|
|
1386
|
-
distanceXY = layout.getDistXY(node,
|
|
2689
|
+
};
|
|
2690
|
+
ReingoldFruchtermanLayout.prototype.barnesHutApproximation = function (node, quadNode) {
|
|
2691
|
+
var distanceXY = this.getDistXY(node,
|
|
1387
2692
|
quadNode),
|
|
1388
|
-
distanceR =
|
|
1389
|
-
|
|
2693
|
+
distanceR = this.vectorLength(distanceXY);
|
|
2694
|
+
var goDeeper,
|
|
1390
2695
|
force;
|
|
1391
2696
|
if (node !== quadNode && distanceR !== 0) {
|
|
1392
2697
|
if (quadNode.isInternal) {
|
|
1393
2698
|
// Internal node:
|
|
1394
2699
|
if (quadNode.boxSize / distanceR <
|
|
1395
|
-
|
|
2700
|
+
this.options.theta &&
|
|
1396
2701
|
distanceR !== 0) {
|
|
1397
2702
|
// Treat as an external node:
|
|
1398
|
-
force =
|
|
1399
|
-
|
|
2703
|
+
force = this.repulsiveForce(distanceR, this.k);
|
|
2704
|
+
this.force('repulsive', node, force * quadNode.mass, distanceXY, distanceR);
|
|
1400
2705
|
goDeeper = false;
|
|
1401
2706
|
}
|
|
1402
2707
|
else {
|
|
@@ -1406,81 +2711,88 @@
|
|
|
1406
2711
|
}
|
|
1407
2712
|
else {
|
|
1408
2713
|
// External node, direct force:
|
|
1409
|
-
force =
|
|
1410
|
-
|
|
2714
|
+
force = this.repulsiveForce(distanceR, this.k);
|
|
2715
|
+
this.force('repulsive', node, force * quadNode.mass, distanceXY, distanceR);
|
|
1411
2716
|
}
|
|
1412
2717
|
}
|
|
1413
2718
|
return goDeeper;
|
|
1414
|
-
}
|
|
1415
|
-
repulsiveForces
|
|
1416
|
-
var
|
|
1417
|
-
if (
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
});
|
|
1422
|
-
}
|
|
2719
|
+
};
|
|
2720
|
+
ReingoldFruchtermanLayout.prototype.repulsiveForces = function () {
|
|
2721
|
+
var _this = this;
|
|
2722
|
+
if (this.approximation === 'barnes-hut') {
|
|
2723
|
+
var _loop_1 = function (node) {
|
|
2724
|
+
this_1.quadTree.visitNodeRecursive(null,
|
|
2725
|
+
function (quadNode) { return (_this.barnesHutApproximation(node,
|
|
2726
|
+
quadNode)); });
|
|
2727
|
+
};
|
|
2728
|
+
var this_1 = this;
|
|
2729
|
+
for (var _i = 0, _a = this.nodes; _i < _a.length; _i++) {
|
|
2730
|
+
var node = _a[_i];
|
|
2731
|
+
_loop_1(node);
|
|
2732
|
+
}
|
|
1423
2733
|
}
|
|
1424
2734
|
else {
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
2735
|
+
var force = void 0,
|
|
2736
|
+
distanceR = void 0,
|
|
2737
|
+
distanceXY = void 0;
|
|
2738
|
+
for (var _b = 0, _c = this.nodes; _b < _c.length; _b++) {
|
|
2739
|
+
var node = _c[_b];
|
|
2740
|
+
for (var _d = 0, _e = this.nodes; _d < _e.length; _d++) {
|
|
2741
|
+
var repNode = _e[_d];
|
|
1430
2742
|
if (
|
|
1431
|
-
// Node
|
|
2743
|
+
// Node cannot repulse itself:
|
|
1432
2744
|
node !== repNode &&
|
|
1433
2745
|
// Only close nodes affect each other:
|
|
1434
2746
|
// layout.getDistR(node, repNode) < 2 * k &&
|
|
1435
2747
|
// Not dragged:
|
|
1436
2748
|
!node.fixedPosition) {
|
|
1437
|
-
distanceXY =
|
|
1438
|
-
distanceR =
|
|
2749
|
+
distanceXY = this.getDistXY(node, repNode);
|
|
2750
|
+
distanceR = this.vectorLength(distanceXY);
|
|
1439
2751
|
if (distanceR !== 0) {
|
|
1440
|
-
force =
|
|
1441
|
-
|
|
2752
|
+
force = this.repulsiveForce(distanceR, this.k);
|
|
2753
|
+
this.force('repulsive', node, force * repNode.mass, distanceXY, distanceR);
|
|
1442
2754
|
}
|
|
1443
2755
|
}
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
1446
2758
|
}
|
|
1447
|
-
}
|
|
1448
|
-
attractiveForces
|
|
1449
|
-
var
|
|
1450
|
-
distanceXY,
|
|
2759
|
+
};
|
|
2760
|
+
ReingoldFruchtermanLayout.prototype.attractiveForces = function () {
|
|
2761
|
+
var distanceXY,
|
|
1451
2762
|
distanceR,
|
|
1452
2763
|
force;
|
|
1453
|
-
|
|
2764
|
+
for (var _i = 0, _a = this.links; _i < _a.length; _i++) {
|
|
2765
|
+
var link = _a[_i];
|
|
1454
2766
|
if (link.fromNode && link.toNode) {
|
|
1455
|
-
distanceXY =
|
|
1456
|
-
distanceR =
|
|
2767
|
+
distanceXY = this.getDistXY(link.fromNode, link.toNode);
|
|
2768
|
+
distanceR = this.vectorLength(distanceXY);
|
|
1457
2769
|
if (distanceR !== 0) {
|
|
1458
|
-
force =
|
|
1459
|
-
|
|
2770
|
+
force = this.attractiveForce(distanceR, this.k);
|
|
2771
|
+
this.force('attractive', link, force, distanceXY, distanceR);
|
|
1460
2772
|
}
|
|
1461
2773
|
}
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
applyLimits
|
|
1465
|
-
var
|
|
1466
|
-
|
|
1467
|
-
|
|
2774
|
+
}
|
|
2775
|
+
};
|
|
2776
|
+
ReingoldFruchtermanLayout.prototype.applyLimits = function () {
|
|
2777
|
+
var nodes = this.nodes;
|
|
2778
|
+
for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) {
|
|
2779
|
+
var node = nodes_2[_i];
|
|
1468
2780
|
if (node.fixedPosition) {
|
|
1469
2781
|
return;
|
|
1470
2782
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
2783
|
+
this.integration.integrate(this, node);
|
|
2784
|
+
this.applyLimitBox(node, this.box);
|
|
1473
2785
|
// Reset displacement:
|
|
1474
2786
|
node.dispX = 0;
|
|
1475
2787
|
node.dispY = 0;
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
2788
|
+
}
|
|
2789
|
+
};
|
|
1478
2790
|
/**
|
|
1479
2791
|
* External box that nodes should fall. When hitting an edge, node
|
|
1480
2792
|
* should stop or bounce.
|
|
1481
2793
|
* @private
|
|
1482
2794
|
*/
|
|
1483
|
-
applyLimitBox
|
|
2795
|
+
ReingoldFruchtermanLayout.prototype.applyLimitBox = function (node, box) {
|
|
1484
2796
|
var radius = node.radius;
|
|
1485
2797
|
/*
|
|
1486
2798
|
TO DO: Consider elastic collision instead of stopping.
|
|
@@ -1488,7 +2800,7 @@
|
|
|
1488
2800
|
|
|
1489
2801
|
- "inelastic":
|
|
1490
2802
|
o
|
|
1491
|
-
|
|
2803
|
+
\
|
|
1492
2804
|
______
|
|
1493
2805
|
| o'
|
|
1494
2806
|
| \
|
|
@@ -1496,7 +2808,7 @@
|
|
|
1496
2808
|
|
|
1497
2809
|
- "elastic"/"bounced":
|
|
1498
2810
|
o
|
|
1499
|
-
|
|
2811
|
+
\
|
|
1500
2812
|
______
|
|
1501
2813
|
| ^
|
|
1502
2814
|
| / \
|
|
@@ -1518,13 +2830,13 @@
|
|
|
1518
2830
|
node.plotX = clamp(node.plotX, box.left + radius, box.width - radius);
|
|
1519
2831
|
// Limit Y-coordinates:
|
|
1520
2832
|
node.plotY = clamp(node.plotY, box.top + radius, box.height - radius);
|
|
1521
|
-
}
|
|
2833
|
+
};
|
|
1522
2834
|
/**
|
|
1523
2835
|
* From "A comparison of simulated annealing cooling strategies" by
|
|
1524
2836
|
* Nourani and Andresen work.
|
|
1525
2837
|
* @private
|
|
1526
2838
|
*/
|
|
1527
|
-
coolDown
|
|
2839
|
+
ReingoldFruchtermanLayout.prototype.coolDown = function (temperature, temperatureStep, currentStep) {
|
|
1528
2840
|
// Logarithmic:
|
|
1529
2841
|
/*
|
|
1530
2842
|
return Math.sqrt(this.nodes.length) -
|
|
@@ -1540,25 +2852,28 @@
|
|
|
1540
2852
|
*/
|
|
1541
2853
|
// Linear:
|
|
1542
2854
|
return temperature - temperatureStep * currentStep;
|
|
1543
|
-
}
|
|
1544
|
-
isStable
|
|
2855
|
+
};
|
|
2856
|
+
ReingoldFruchtermanLayout.prototype.isStable = function () {
|
|
1545
2857
|
return Math.abs(this.systemTemperature -
|
|
1546
2858
|
this.prevSystemTemperature) < 0.00001 || this.temperature <= 0;
|
|
1547
|
-
}
|
|
1548
|
-
getSystemTemperature
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
2859
|
+
};
|
|
2860
|
+
ReingoldFruchtermanLayout.prototype.getSystemTemperature = function () {
|
|
2861
|
+
var value = 0;
|
|
2862
|
+
for (var _i = 0, _a = this.nodes; _i < _a.length; _i++) {
|
|
2863
|
+
var node = _a[_i];
|
|
2864
|
+
value += node.temperature;
|
|
2865
|
+
}
|
|
2866
|
+
return value;
|
|
2867
|
+
};
|
|
2868
|
+
ReingoldFruchtermanLayout.prototype.vectorLength = function (vector) {
|
|
1554
2869
|
return Math.sqrt(vector.x * vector.x + vector.y * vector.y);
|
|
1555
|
-
}
|
|
1556
|
-
getDistR
|
|
2870
|
+
};
|
|
2871
|
+
ReingoldFruchtermanLayout.prototype.getDistR = function (nodeA, nodeB) {
|
|
1557
2872
|
var distance = this.getDistXY(nodeA,
|
|
1558
2873
|
nodeB);
|
|
1559
2874
|
return this.vectorLength(distance);
|
|
1560
|
-
}
|
|
1561
|
-
getDistXY
|
|
2875
|
+
};
|
|
2876
|
+
ReingoldFruchtermanLayout.prototype.getDistXY = function (nodeA, nodeB) {
|
|
1562
2877
|
var xDist = nodeA.plotX - nodeB.plotX,
|
|
1563
2878
|
yDist = nodeA.plotY - nodeB.plotY;
|
|
1564
2879
|
return {
|
|
@@ -1567,227 +2882,18 @@
|
|
|
1567
2882
|
absX: Math.abs(xDist),
|
|
1568
2883
|
absY: Math.abs(yDist)
|
|
1569
2884
|
};
|
|
1570
|
-
}
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
* Multiple series support:
|
|
1574
|
-
* ************************************************************************** */
|
|
1575
|
-
// Clear previous layouts
|
|
1576
|
-
addEvent(Chart, 'predraw', function () {
|
|
1577
|
-
if (this.graphLayoutsLookup) {
|
|
1578
|
-
this.graphLayoutsLookup.forEach(function (layout) {
|
|
1579
|
-
layout.stop();
|
|
1580
|
-
});
|
|
1581
|
-
}
|
|
1582
|
-
});
|
|
1583
|
-
addEvent(Chart, 'render', function () {
|
|
1584
|
-
var systemsStable,
|
|
1585
|
-
afterRender = false;
|
|
1586
|
-
/**
|
|
1587
|
-
* @private
|
|
1588
|
-
*/
|
|
1589
|
-
function layoutStep(layout) {
|
|
1590
|
-
if (layout.maxIterations-- &&
|
|
1591
|
-
isFinite(layout.temperature) &&
|
|
1592
|
-
!layout.isStable() &&
|
|
1593
|
-
!layout.enableSimulation) {
|
|
1594
|
-
// Hook similar to build-in addEvent, but instead of
|
|
1595
|
-
// creating whole events logic, use just a function.
|
|
1596
|
-
// It's faster which is important for rAF code.
|
|
1597
|
-
// Used e.g. in packed-bubble series for bubble radius
|
|
1598
|
-
// calculations
|
|
1599
|
-
if (layout.beforeStep) {
|
|
1600
|
-
layout.beforeStep();
|
|
1601
|
-
}
|
|
1602
|
-
layout.step();
|
|
1603
|
-
systemsStable = false;
|
|
1604
|
-
afterRender = true;
|
|
1605
|
-
}
|
|
1606
|
-
}
|
|
1607
|
-
if (this.graphLayoutsLookup) {
|
|
1608
|
-
setAnimation(false, this);
|
|
1609
|
-
// Start simulation
|
|
1610
|
-
this.graphLayoutsLookup.forEach(function (layout) {
|
|
1611
|
-
layout.start();
|
|
1612
|
-
});
|
|
1613
|
-
// Just one sync step, to run different layouts similar to
|
|
1614
|
-
// async mode.
|
|
1615
|
-
while (!systemsStable) {
|
|
1616
|
-
systemsStable = true;
|
|
1617
|
-
this.graphLayoutsLookup.forEach(layoutStep);
|
|
1618
|
-
}
|
|
1619
|
-
if (afterRender) {
|
|
1620
|
-
this.series.forEach(function (s) {
|
|
1621
|
-
if (s && s.layout) {
|
|
1622
|
-
s.render();
|
|
1623
|
-
}
|
|
1624
|
-
});
|
|
1625
|
-
}
|
|
1626
|
-
}
|
|
1627
|
-
});
|
|
1628
|
-
// disable simulation before print if enabled
|
|
1629
|
-
addEvent(Chart, 'beforePrint', function () {
|
|
1630
|
-
if (this.graphLayoutsLookup) {
|
|
1631
|
-
this.graphLayoutsLookup.forEach(function (layout) {
|
|
1632
|
-
layout.updateSimulation(false);
|
|
1633
|
-
});
|
|
1634
|
-
this.redraw();
|
|
1635
|
-
}
|
|
1636
|
-
});
|
|
1637
|
-
// re-enable simulation after print
|
|
1638
|
-
addEvent(Chart, 'afterPrint', function () {
|
|
1639
|
-
if (this.graphLayoutsLookup) {
|
|
1640
|
-
this.graphLayoutsLookup.forEach(function (layout) {
|
|
1641
|
-
// return to default simulation
|
|
1642
|
-
layout.updateSimulation();
|
|
1643
|
-
});
|
|
1644
|
-
}
|
|
1645
|
-
this.redraw();
|
|
1646
|
-
});
|
|
1647
|
-
|
|
1648
|
-
});
|
|
1649
|
-
_registerModule(_modules, 'Series/Networkgraph/DraggableNodes.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (Chart, H, U) {
|
|
2885
|
+
};
|
|
2886
|
+
return ReingoldFruchtermanLayout;
|
|
2887
|
+
}());
|
|
1650
2888
|
/* *
|
|
1651
2889
|
*
|
|
1652
|
-
*
|
|
1653
|
-
*
|
|
1654
|
-
* (c) 2010-2021 Paweł Fus
|
|
1655
|
-
*
|
|
1656
|
-
* License: www.highcharts.com/license
|
|
1657
|
-
*
|
|
1658
|
-
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
2890
|
+
* Default Export
|
|
1659
2891
|
*
|
|
1660
|
-
* */
|
|
1661
|
-
var addEvent = U.addEvent;
|
|
1662
|
-
/* eslint-disable no-invalid-this, valid-jsdoc */
|
|
1663
|
-
H.dragNodesMixin = {
|
|
1664
|
-
/**
|
|
1665
|
-
* Mouse down action, initializing drag&drop mode.
|
|
1666
|
-
*
|
|
1667
|
-
* @private
|
|
1668
|
-
* @param {Highcharts.Point} point The point that event occured.
|
|
1669
|
-
* @param {Highcharts.PointerEventObject} event Browser event, before normalization.
|
|
1670
|
-
*/
|
|
1671
|
-
onMouseDown: function (point, event) {
|
|
1672
|
-
var normalizedEvent = this.chart.pointer.normalize(event);
|
|
1673
|
-
point.fixedPosition = {
|
|
1674
|
-
chartX: normalizedEvent.chartX,
|
|
1675
|
-
chartY: normalizedEvent.chartY,
|
|
1676
|
-
plotX: point.plotX,
|
|
1677
|
-
plotY: point.plotY
|
|
1678
|
-
};
|
|
1679
|
-
point.inDragMode = true;
|
|
1680
|
-
},
|
|
1681
|
-
/**
|
|
1682
|
-
* Mouse move action during drag&drop.
|
|
1683
|
-
*
|
|
1684
|
-
* @private
|
|
1685
|
-
*
|
|
1686
|
-
* @param {global.Event} event Browser event, before normalization.
|
|
1687
|
-
* @param {Highcharts.Point} point The point that event occured.
|
|
1688
|
-
*
|
|
1689
|
-
*/
|
|
1690
|
-
onMouseMove: function (point, event) {
|
|
1691
|
-
if (point.fixedPosition && point.inDragMode) {
|
|
1692
|
-
var series = this,
|
|
1693
|
-
chart = series.chart,
|
|
1694
|
-
normalizedEvent = chart.pointer.normalize(event),
|
|
1695
|
-
diffX = point.fixedPosition.chartX - normalizedEvent.chartX,
|
|
1696
|
-
diffY = point.fixedPosition.chartY - normalizedEvent.chartY,
|
|
1697
|
-
newPlotX = void 0,
|
|
1698
|
-
newPlotY = void 0,
|
|
1699
|
-
graphLayoutsLookup = chart.graphLayoutsLookup;
|
|
1700
|
-
// At least 5px to apply change (avoids simple click):
|
|
1701
|
-
if (Math.abs(diffX) > 5 || Math.abs(diffY) > 5) {
|
|
1702
|
-
newPlotX = point.fixedPosition.plotX - diffX;
|
|
1703
|
-
newPlotY = point.fixedPosition.plotY - diffY;
|
|
1704
|
-
if (chart.isInsidePlot(newPlotX, newPlotY)) {
|
|
1705
|
-
point.plotX = newPlotX;
|
|
1706
|
-
point.plotY = newPlotY;
|
|
1707
|
-
point.hasDragged = true;
|
|
1708
|
-
this.redrawHalo(point);
|
|
1709
|
-
graphLayoutsLookup.forEach(function (layout) {
|
|
1710
|
-
layout.restartSimulation();
|
|
1711
|
-
});
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1714
|
-
}
|
|
1715
|
-
},
|
|
1716
|
-
/**
|
|
1717
|
-
* Mouse up action, finalizing drag&drop.
|
|
1718
|
-
*
|
|
1719
|
-
* @private
|
|
1720
|
-
* @param {Highcharts.Point} point The point that event occured.
|
|
1721
|
-
*/
|
|
1722
|
-
onMouseUp: function (point, event) {
|
|
1723
|
-
if (point.fixedPosition) {
|
|
1724
|
-
if (point.hasDragged) {
|
|
1725
|
-
if (this.layout.enableSimulation) {
|
|
1726
|
-
this.layout.start();
|
|
1727
|
-
}
|
|
1728
|
-
else {
|
|
1729
|
-
this.chart.redraw();
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
point.inDragMode = point.hasDragged = false;
|
|
1733
|
-
if (!this.options.fixedDraggable) {
|
|
1734
|
-
delete point.fixedPosition;
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
},
|
|
1738
|
-
// Draggable mode:
|
|
1739
|
-
/**
|
|
1740
|
-
* Redraw halo on mousemove during the drag&drop action.
|
|
1741
|
-
*
|
|
1742
|
-
* @private
|
|
1743
|
-
* @param {Highcharts.Point} point The point that should show halo.
|
|
1744
|
-
*/
|
|
1745
|
-
redrawHalo: function (point) {
|
|
1746
|
-
if (point && this.halo) {
|
|
1747
|
-
this.halo.attr({
|
|
1748
|
-
d: point.haloPath(this.options.states.hover.halo.size)
|
|
1749
|
-
});
|
|
1750
|
-
}
|
|
1751
|
-
}
|
|
1752
|
-
};
|
|
1753
|
-
/*
|
|
1754
|
-
* Draggable mode:
|
|
1755
|
-
*/
|
|
1756
|
-
addEvent(Chart, 'load', function () {
|
|
1757
|
-
var chart = this,
|
|
1758
|
-
mousedownUnbinder,
|
|
1759
|
-
mousemoveUnbinder,
|
|
1760
|
-
mouseupUnbinder;
|
|
1761
|
-
if (chart.container) {
|
|
1762
|
-
mousedownUnbinder = addEvent(chart.container, 'mousedown', function (event) {
|
|
1763
|
-
var point = chart.hoverPoint;
|
|
1764
|
-
if (point &&
|
|
1765
|
-
point.series &&
|
|
1766
|
-
point.series.hasDraggableNodes &&
|
|
1767
|
-
point.series.options.draggable) {
|
|
1768
|
-
point.series.onMouseDown(point, event);
|
|
1769
|
-
mousemoveUnbinder = addEvent(chart.container, 'mousemove', function (e) {
|
|
1770
|
-
return point &&
|
|
1771
|
-
point.series &&
|
|
1772
|
-
point.series.onMouseMove(point, e);
|
|
1773
|
-
});
|
|
1774
|
-
mouseupUnbinder = addEvent(chart.container.ownerDocument, 'mouseup', function (e) {
|
|
1775
|
-
mousemoveUnbinder();
|
|
1776
|
-
mouseupUnbinder();
|
|
1777
|
-
return point &&
|
|
1778
|
-
point.series &&
|
|
1779
|
-
point.series.onMouseUp(point, e);
|
|
1780
|
-
});
|
|
1781
|
-
}
|
|
1782
|
-
});
|
|
1783
|
-
}
|
|
1784
|
-
addEvent(chart, 'destroy', function () {
|
|
1785
|
-
mousedownUnbinder();
|
|
1786
|
-
});
|
|
1787
|
-
});
|
|
2892
|
+
* */
|
|
1788
2893
|
|
|
2894
|
+
return ReingoldFruchtermanLayout;
|
|
1789
2895
|
});
|
|
1790
|
-
_registerModule(_modules, 'Series/Networkgraph/
|
|
2896
|
+
_registerModule(_modules, 'Series/Networkgraph/NetworkgraphSeries.js', [_modules['Series/DragNodesComposition.js'], _modules['Series/GraphLayoutComposition.js'], _modules['Core/Globals.js'], _modules['Series/Networkgraph/NetworkgraphPoint.js'], _modules['Series/Networkgraph/NetworkgraphSeriesDefaults.js'], _modules['Series/NodesComposition.js'], _modules['Series/Networkgraph/ReingoldFruchtermanLayout.js'], _modules['Core/Series/SeriesRegistry.js'], _modules['Core/Utilities.js']], function (DragNodesComposition, GraphLayout, H, NetworkgraphPoint, NetworkgraphSeriesDefaults, NodesComposition, ReingoldFruchtermanLayout, SeriesRegistry, U) {
|
|
1791
2897
|
/* *
|
|
1792
2898
|
*
|
|
1793
2899
|
* Networkgraph series
|
|
@@ -1815,513 +2921,137 @@
|
|
|
1815
2921
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
1816
2922
|
};
|
|
1817
2923
|
})();
|
|
1818
|
-
var
|
|
2924
|
+
var noop = H.noop;
|
|
2925
|
+
var Series = SeriesRegistry.series,
|
|
2926
|
+
_a = SeriesRegistry.seriesTypes,
|
|
2927
|
+
columnProto = _a.column.prototype,
|
|
2928
|
+
lineProto = _a.line.prototype;
|
|
1819
2929
|
var addEvent = U.addEvent,
|
|
1820
|
-
css = U.css,
|
|
1821
2930
|
defined = U.defined,
|
|
1822
2931
|
extend = U.extend,
|
|
1823
2932
|
merge = U.merge,
|
|
1824
2933
|
pick = U.pick;
|
|
1825
|
-
var dragNodesMixin = H.dragNodesMixin;
|
|
1826
|
-
/**
|
|
1827
|
-
* Formatter callback function.
|
|
1828
|
-
*
|
|
1829
|
-
* @callback Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction
|
|
1830
|
-
*
|
|
1831
|
-
* @param {Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject|Highcharts.PointLabelObject} this
|
|
1832
|
-
* Data label context to format
|
|
1833
|
-
*
|
|
1834
|
-
* @return {string}
|
|
1835
|
-
* Formatted data label text
|
|
1836
|
-
*/
|
|
1837
|
-
/**
|
|
1838
|
-
* Context for the formatter function.
|
|
1839
|
-
*
|
|
1840
|
-
* @interface Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject
|
|
1841
|
-
* @extends Highcharts.PointLabelObject
|
|
1842
|
-
* @since 7.0.0
|
|
1843
|
-
*/ /**
|
|
1844
|
-
* The color of the node.
|
|
1845
|
-
* @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#color
|
|
1846
|
-
* @type {Highcharts.ColorString}
|
|
1847
|
-
* @since 7.0.0
|
|
1848
|
-
*/ /**
|
|
1849
|
-
* The point (node) object. The node name, if defined, is available through
|
|
1850
|
-
* `this.point.name`. Arrays: `this.point.linksFrom` and `this.point.linksTo`
|
|
1851
|
-
* contains all nodes connected to this point.
|
|
1852
|
-
* @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#point
|
|
1853
|
-
* @type {Highcharts.Point}
|
|
1854
|
-
* @since 7.0.0
|
|
1855
|
-
*/ /**
|
|
1856
|
-
* The ID of the node.
|
|
1857
|
-
* @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#key
|
|
1858
|
-
* @type {string}
|
|
1859
|
-
* @since 7.0.0
|
|
1860
|
-
*/
|
|
1861
|
-
''; // detach doclets above
|
|
1862
2934
|
/* *
|
|
1863
|
-
*
|
|
1864
|
-
* Class
|
|
1865
|
-
*
|
|
1866
|
-
* */
|
|
1867
|
-
/**
|
|
1868
|
-
* @private
|
|
1869
|
-
* @class
|
|
1870
|
-
* @name Highcharts.seriesTypes.networkgraph
|
|
1871
|
-
*
|
|
1872
|
-
* @extends Highcharts.Series
|
|
1873
|
-
*/
|
|
1874
|
-
var NetworkgraphSeries = /** @class */ (function (_super) {
|
|
1875
|
-
__extends(NetworkgraphSeries, _super);
|
|
1876
|
-
function NetworkgraphSeries() {
|
|
1877
|
-
/* *
|
|
1878
|
-
*
|
|
1879
|
-
* Static Properties
|
|
1880
|
-
*
|
|
1881
|
-
* */
|
|
1882
|
-
var _this = _super !== null && _super.apply(this,
|
|
1883
|
-
arguments) || this;
|
|
1884
|
-
/* *
|
|
1885
|
-
*
|
|
1886
|
-
* Properties
|
|
1887
|
-
*
|
|
1888
|
-
* */
|
|
1889
|
-
_this.data = void 0;
|
|
1890
|
-
_this.nodes = void 0;
|
|
1891
|
-
_this.options = void 0;
|
|
1892
|
-
_this.points = void 0;
|
|
1893
|
-
return _this;
|
|
1894
|
-
}
|
|
1895
|
-
|
|
1896
|
-
*
|
|
1897
|
-
*
|
|
1898
|
-
*
|
|
1899
|
-
*
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
*
|
|
1906
|
-
*
|
|
1907
|
-
*
|
|
1908
|
-
*
|
|
1909
|
-
* threshold, xAxis, yAxis, zoneAxis, dataSorting,
|
|
1910
|
-
* boostBlending
|
|
1911
|
-
* @requires modules/networkgraph
|
|
1912
|
-
* @optionparent plotOptions.networkgraph
|
|
1913
|
-
*/
|
|
1914
|
-
NetworkgraphSeries.defaultOptions = merge(Series.defaultOptions, {
|
|
1915
|
-
stickyTracking: false,
|
|
1916
|
-
/**
|
|
1917
|
-
* @ignore-option
|
|
1918
|
-
* @private
|
|
1919
|
-
*/
|
|
1920
|
-
inactiveOtherPoints: true,
|
|
1921
|
-
marker: {
|
|
1922
|
-
enabled: true,
|
|
1923
|
-
states: {
|
|
1924
|
-
/**
|
|
1925
|
-
* The opposite state of a hover for a single point node.
|
|
1926
|
-
* Applied to all not connected nodes to the hovered one.
|
|
1927
|
-
*
|
|
1928
|
-
* @declare Highcharts.PointStatesInactiveOptionsObject
|
|
1929
|
-
*/
|
|
1930
|
-
inactive: {
|
|
1931
|
-
/**
|
|
1932
|
-
* Opacity of inactive markers.
|
|
1933
|
-
*/
|
|
1934
|
-
opacity: 0.3,
|
|
1935
|
-
/**
|
|
1936
|
-
* Animation when not hovering over the node.
|
|
1937
|
-
*
|
|
1938
|
-
* @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
|
|
1939
|
-
*/
|
|
1940
|
-
animation: {
|
|
1941
|
-
/** @internal */
|
|
1942
|
-
duration: 50
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
},
|
|
1947
|
-
states: {
|
|
1948
|
-
/**
|
|
1949
|
-
* The opposite state of a hover for a single point link. Applied
|
|
1950
|
-
* to all links that are not comming from the hovered node.
|
|
1951
|
-
*
|
|
1952
|
-
* @declare Highcharts.SeriesStatesInactiveOptionsObject
|
|
1953
|
-
*/
|
|
1954
|
-
inactive: {
|
|
1955
|
-
/**
|
|
1956
|
-
* Opacity of inactive links.
|
|
1957
|
-
*/
|
|
1958
|
-
linkOpacity: 0.3,
|
|
1959
|
-
/**
|
|
1960
|
-
* Animation when not hovering over the node.
|
|
1961
|
-
*
|
|
1962
|
-
* @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
|
|
1963
|
-
*/
|
|
1964
|
-
animation: {
|
|
1965
|
-
/** @internal */
|
|
1966
|
-
duration: 50
|
|
1967
|
-
}
|
|
1968
|
-
}
|
|
1969
|
-
},
|
|
1970
|
-
/**
|
|
1971
|
-
* @sample highcharts/series-networkgraph/link-datalabels
|
|
1972
|
-
* Networkgraph with labels on links
|
|
1973
|
-
* @sample highcharts/series-networkgraph/textpath-datalabels
|
|
1974
|
-
* Networkgraph with labels around nodes
|
|
1975
|
-
* @sample highcharts/series-networkgraph/link-datalabels
|
|
1976
|
-
* Data labels moved into the nodes
|
|
1977
|
-
* @sample highcharts/series-networkgraph/link-datalabels
|
|
1978
|
-
* Data labels moved under the links
|
|
1979
|
-
*
|
|
1980
|
-
* @declare Highcharts.SeriesNetworkgraphDataLabelsOptionsObject
|
|
1981
|
-
*
|
|
1982
|
-
* @private
|
|
1983
|
-
*/
|
|
1984
|
-
dataLabels: {
|
|
1985
|
-
/**
|
|
1986
|
-
* The
|
|
1987
|
-
* [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
|
|
1988
|
-
* specifying what to show for _node_ in the networkgraph. In v7.0
|
|
1989
|
-
* defaults to `{key}`, since v7.1 defaults to `undefined` and
|
|
1990
|
-
* `formatter` is used instead.
|
|
1991
|
-
*
|
|
1992
|
-
* @type {string}
|
|
1993
|
-
* @since 7.0.0
|
|
1994
|
-
* @apioption plotOptions.networkgraph.dataLabels.format
|
|
1995
|
-
*/
|
|
1996
|
-
// eslint-disable-next-line valid-jsdoc
|
|
1997
|
-
/**
|
|
1998
|
-
* Callback JavaScript function to format the data label for a node.
|
|
1999
|
-
* Note that if a `format` is defined, the format takes precedence
|
|
2000
|
-
* and the formatter is ignored.
|
|
2001
|
-
*
|
|
2002
|
-
* @type {Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction}
|
|
2003
|
-
* @since 7.0.0
|
|
2004
|
-
*/
|
|
2005
|
-
formatter: function () {
|
|
2006
|
-
return this.key;
|
|
2007
|
-
},
|
|
2008
|
-
/**
|
|
2009
|
-
* The
|
|
2010
|
-
* [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
|
|
2011
|
-
* specifying what to show for _links_ in the networkgraph.
|
|
2012
|
-
* (Default: `undefined`)
|
|
2013
|
-
*
|
|
2014
|
-
* @type {string}
|
|
2015
|
-
* @since 7.1.0
|
|
2016
|
-
* @apioption plotOptions.networkgraph.dataLabels.linkFormat
|
|
2017
|
-
*/
|
|
2018
|
-
// eslint-disable-next-line valid-jsdoc
|
|
2019
|
-
/**
|
|
2020
|
-
* Callback to format data labels for _links_ in the sankey diagram.
|
|
2021
|
-
* The `linkFormat` option takes precedence over the
|
|
2022
|
-
* `linkFormatter`.
|
|
2023
|
-
*
|
|
2024
|
-
* @type {Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction}
|
|
2025
|
-
* @since 7.1.0
|
|
2026
|
-
*/
|
|
2027
|
-
linkFormatter: function () {
|
|
2028
|
-
return (this.point.fromNode.name +
|
|
2029
|
-
'<br>' +
|
|
2030
|
-
this.point.toNode.name);
|
|
2031
|
-
},
|
|
2032
|
-
/**
|
|
2033
|
-
* Options for a _link_ label text which should follow link
|
|
2034
|
-
* connection. Border and background are disabled for a label that
|
|
2035
|
-
* follows a path.
|
|
2036
|
-
*
|
|
2037
|
-
* **Note:** Only SVG-based renderer supports this option. Setting
|
|
2038
|
-
* `useHTML` to true will disable this option.
|
|
2039
|
-
*
|
|
2040
|
-
* @extends plotOptions.networkgraph.dataLabels.textPath
|
|
2041
|
-
* @since 7.1.0
|
|
2042
|
-
*/
|
|
2043
|
-
linkTextPath: {
|
|
2044
|
-
enabled: true
|
|
2045
|
-
},
|
|
2046
|
-
textPath: {
|
|
2047
|
-
enabled: false
|
|
2048
|
-
},
|
|
2049
|
-
style: {
|
|
2050
|
-
transition: 'opacity 2000ms'
|
|
2051
|
-
}
|
|
2052
|
-
},
|
|
2053
|
-
/**
|
|
2054
|
-
* Link style options
|
|
2055
|
-
* @private
|
|
2056
|
-
*/
|
|
2057
|
-
link: {
|
|
2058
|
-
/**
|
|
2059
|
-
* A name for the dash style to use for links.
|
|
2060
|
-
*
|
|
2061
|
-
* @type {string}
|
|
2062
|
-
* @apioption plotOptions.networkgraph.link.dashStyle
|
|
2063
|
-
*/
|
|
2064
|
-
/**
|
|
2065
|
-
* Color of the link between two nodes.
|
|
2066
|
-
*/
|
|
2067
|
-
color: 'rgba(100, 100, 100, 0.5)',
|
|
2068
|
-
/**
|
|
2069
|
-
* Width (px) of the link between two nodes.
|
|
2070
|
-
*/
|
|
2071
|
-
width: 1
|
|
2072
|
-
},
|
|
2073
|
-
/**
|
|
2074
|
-
* Flag to determine if nodes are draggable or not.
|
|
2075
|
-
* @private
|
|
2076
|
-
*/
|
|
2077
|
-
draggable: true,
|
|
2078
|
-
layoutAlgorithm: {
|
|
2079
|
-
/**
|
|
2080
|
-
* Repulsive force applied on a node. Passed are two arguments:
|
|
2081
|
-
* - `d` - which is current distance between two nodes
|
|
2082
|
-
* - `k` - which is desired distance between two nodes
|
|
2083
|
-
*
|
|
2084
|
-
* In `verlet` integration, defaults to:
|
|
2085
|
-
* `function (d, k) { return (k - d) / d * (k > d ? 1 : 0) }`
|
|
2086
|
-
*
|
|
2087
|
-
* @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration)
|
|
2088
|
-
*
|
|
2089
|
-
* @sample highcharts/series-networkgraph/forces/
|
|
2090
|
-
* Custom forces with Euler integration
|
|
2091
|
-
* @sample highcharts/series-networkgraph/cuboids/
|
|
2092
|
-
* Custom forces with Verlet integration
|
|
2093
|
-
*
|
|
2094
|
-
* @type {Function}
|
|
2095
|
-
* @default function (d, k) { return k * k / d; }
|
|
2096
|
-
* @apioption plotOptions.networkgraph.layoutAlgorithm.repulsiveForce
|
|
2097
|
-
*/
|
|
2098
|
-
/**
|
|
2099
|
-
* Attraction force applied on a node which is conected to another
|
|
2100
|
-
* node by a link. Passed are two arguments:
|
|
2101
|
-
* - `d` - which is current distance between two nodes
|
|
2102
|
-
* - `k` - which is desired distance between two nodes
|
|
2103
|
-
*
|
|
2104
|
-
* In `verlet` integration, defaults to:
|
|
2105
|
-
* `function (d, k) { return (k - d) / d; }`
|
|
2106
|
-
*
|
|
2107
|
-
* @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration)
|
|
2108
|
-
*
|
|
2109
|
-
* @sample highcharts/series-networkgraph/forces/
|
|
2110
|
-
* Custom forces with Euler integration
|
|
2111
|
-
* @sample highcharts/series-networkgraph/cuboids/
|
|
2112
|
-
* Custom forces with Verlet integration
|
|
2113
|
-
*
|
|
2114
|
-
* @type {Function}
|
|
2115
|
-
* @default function (d, k) { return k * k / d; }
|
|
2116
|
-
* @apioption plotOptions.networkgraph.layoutAlgorithm.attractiveForce
|
|
2117
|
-
*/
|
|
2118
|
-
/**
|
|
2119
|
-
* Ideal length (px) of the link between two nodes. When not
|
|
2120
|
-
* defined, length is calculated as:
|
|
2121
|
-
* `Math.pow(availableWidth * availableHeight / nodesLength, 0.4);`
|
|
2122
|
-
*
|
|
2123
|
-
* Note: Because of the algorithm specification, length of each link
|
|
2124
|
-
* might be not exactly as specified.
|
|
2125
|
-
*
|
|
2126
|
-
* @sample highcharts/series-networkgraph/styled-links/
|
|
2127
|
-
* Numerical values
|
|
2128
|
-
*
|
|
2129
|
-
* @type {number}
|
|
2130
|
-
* @apioption plotOptions.networkgraph.layoutAlgorithm.linkLength
|
|
2131
|
-
*/
|
|
2132
|
-
/**
|
|
2133
|
-
* Initial layout algorithm for positioning nodes. Can be one of
|
|
2134
|
-
* built-in options ("circle", "random") or a function where
|
|
2135
|
-
* positions should be set on each node (`this.nodes`) as
|
|
2136
|
-
* `node.plotX` and `node.plotY`
|
|
2137
|
-
*
|
|
2138
|
-
* @sample highcharts/series-networkgraph/initial-positions/
|
|
2139
|
-
* Initial positions with callback
|
|
2140
|
-
*
|
|
2141
|
-
* @type {"circle"|"random"|Function}
|
|
2142
|
-
*/
|
|
2143
|
-
initialPositions: 'circle',
|
|
2144
|
-
/**
|
|
2145
|
-
* When `initialPositions` are set to 'circle',
|
|
2146
|
-
* `initialPositionRadius` is a distance from the center of circle,
|
|
2147
|
-
* in which nodes are created.
|
|
2148
|
-
*
|
|
2149
|
-
* @type {number}
|
|
2150
|
-
* @default 1
|
|
2151
|
-
* @since 7.1.0
|
|
2152
|
-
*/
|
|
2153
|
-
initialPositionRadius: 1,
|
|
2154
|
-
/**
|
|
2155
|
-
* Experimental. Enables live simulation of the algorithm
|
|
2156
|
-
* implementation. All nodes are animated as the forces applies on
|
|
2157
|
-
* them.
|
|
2158
|
-
*
|
|
2159
|
-
* @sample highcharts/demo/network-graph/
|
|
2160
|
-
* Live simulation enabled
|
|
2161
|
-
*/
|
|
2162
|
-
enableSimulation: false,
|
|
2163
|
-
/**
|
|
2164
|
-
* Barnes-Hut approximation only.
|
|
2165
|
-
* Deteremines when distance between cell and node is small enough
|
|
2166
|
-
* to caculate forces. Value of `theta` is compared directly with
|
|
2167
|
-
* quotient `s / d`, where `s` is the size of the cell, and `d` is
|
|
2168
|
-
* distance between center of cell's mass and currently compared
|
|
2169
|
-
* node.
|
|
2170
|
-
*
|
|
2171
|
-
* @see [layoutAlgorithm.approximation](#series.networkgraph.layoutAlgorithm.approximation)
|
|
2172
|
-
*
|
|
2173
|
-
* @since 7.1.0
|
|
2174
|
-
*/
|
|
2175
|
-
theta: 0.5,
|
|
2176
|
-
/**
|
|
2177
|
-
* Verlet integration only.
|
|
2178
|
-
* Max speed that node can get in one iteration. In terms of
|
|
2179
|
-
* simulation, it's a maximum translation (in pixels) that node can
|
|
2180
|
-
* move (in both, x and y, dimensions). While `friction` is applied
|
|
2181
|
-
* on all nodes, max speed is applied only for nodes that move very
|
|
2182
|
-
* fast, for example small or disconnected ones.
|
|
2183
|
-
*
|
|
2184
|
-
* @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration)
|
|
2185
|
-
* @see [layoutAlgorithm.friction](#series.networkgraph.layoutAlgorithm.friction)
|
|
2186
|
-
*
|
|
2187
|
-
* @since 7.1.0
|
|
2188
|
-
*/
|
|
2189
|
-
maxSpeed: 10,
|
|
2190
|
-
/**
|
|
2191
|
-
* Approximation used to calculate repulsive forces affecting nodes.
|
|
2192
|
-
* By default, when calculateing net force, nodes are compared
|
|
2193
|
-
* against each other, which gives O(N^2) complexity. Using
|
|
2194
|
-
* Barnes-Hut approximation, we decrease this to O(N log N), but the
|
|
2195
|
-
* resulting graph will have different layout. Barnes-Hut
|
|
2196
|
-
* approximation divides space into rectangles via quad tree, where
|
|
2197
|
-
* forces exerted on nodes are calculated directly for nearby cells,
|
|
2198
|
-
* and for all others, cells are treated as a separate node with
|
|
2199
|
-
* center of mass.
|
|
2200
|
-
*
|
|
2201
|
-
* @see [layoutAlgorithm.theta](#series.networkgraph.layoutAlgorithm.theta)
|
|
2202
|
-
*
|
|
2203
|
-
* @sample highcharts/series-networkgraph/barnes-hut-approximation/
|
|
2204
|
-
* A graph with Barnes-Hut approximation
|
|
2205
|
-
*
|
|
2206
|
-
* @type {string}
|
|
2207
|
-
* @validvalue ["barnes-hut", "none"]
|
|
2208
|
-
* @since 7.1.0
|
|
2209
|
-
*/
|
|
2210
|
-
approximation: 'none',
|
|
2211
|
-
/**
|
|
2212
|
-
* Type of the algorithm used when positioning nodes.
|
|
2213
|
-
*
|
|
2214
|
-
* @type {string}
|
|
2215
|
-
* @validvalue ["reingold-fruchterman"]
|
|
2216
|
-
*/
|
|
2217
|
-
type: 'reingold-fruchterman',
|
|
2218
|
-
/**
|
|
2219
|
-
* Integration type. Available options are `'euler'` and `'verlet'`.
|
|
2220
|
-
* Integration determines how forces are applied on particles. In
|
|
2221
|
-
* Euler integration, force is applied direct as
|
|
2222
|
-
* `newPosition += velocity;`.
|
|
2223
|
-
* In Verlet integration, new position is based on a previous
|
|
2224
|
-
* posittion without velocity:
|
|
2225
|
-
* `newPosition += previousPosition - newPosition`.
|
|
2226
|
-
*
|
|
2227
|
-
* Note that different integrations give different results as forces
|
|
2228
|
-
* are different.
|
|
2229
|
-
*
|
|
2230
|
-
* In Highcharts v7.0.x only `'euler'` integration was supported.
|
|
2231
|
-
*
|
|
2232
|
-
* @sample highcharts/series-networkgraph/integration-comparison/
|
|
2233
|
-
* Comparison of Verlet and Euler integrations
|
|
2234
|
-
*
|
|
2235
|
-
* @type {string}
|
|
2236
|
-
* @validvalue ["euler", "verlet"]
|
|
2237
|
-
* @since 7.1.0
|
|
2238
|
-
*/
|
|
2239
|
-
integration: 'euler',
|
|
2240
|
-
/**
|
|
2241
|
-
* Max number of iterations before algorithm will stop. In general,
|
|
2242
|
-
* algorithm should find positions sooner, but when rendering huge
|
|
2243
|
-
* number of nodes, it is recommended to increase this value as
|
|
2244
|
-
* finding perfect graph positions can require more time.
|
|
2245
|
-
*/
|
|
2246
|
-
maxIterations: 1000,
|
|
2247
|
-
/**
|
|
2248
|
-
* Gravitational const used in the barycenter force of the
|
|
2249
|
-
* algorithm.
|
|
2250
|
-
*
|
|
2251
|
-
* @sample highcharts/series-networkgraph/forces/
|
|
2252
|
-
* Custom forces with Euler integration
|
|
2253
|
-
*/
|
|
2254
|
-
gravitationalConstant: 0.0625,
|
|
2255
|
-
/**
|
|
2256
|
-
* Friction applied on forces to prevent nodes rushing to fast to
|
|
2257
|
-
* the desired positions.
|
|
2258
|
-
*/
|
|
2259
|
-
friction: -0.981
|
|
2260
|
-
},
|
|
2261
|
-
showInLegend: false
|
|
2262
|
-
});
|
|
2263
|
-
return NetworkgraphSeries;
|
|
2264
|
-
}(Series));
|
|
2265
|
-
extend(NetworkgraphSeries.prototype, {
|
|
2935
|
+
*
|
|
2936
|
+
* Class
|
|
2937
|
+
*
|
|
2938
|
+
* */
|
|
2939
|
+
/**
|
|
2940
|
+
* @private
|
|
2941
|
+
* @class
|
|
2942
|
+
* @name Highcharts.seriesTypes.networkgraph
|
|
2943
|
+
*
|
|
2944
|
+
* @extends Highcharts.Series
|
|
2945
|
+
*/
|
|
2946
|
+
var NetworkgraphSeries = /** @class */ (function (_super) {
|
|
2947
|
+
__extends(NetworkgraphSeries, _super);
|
|
2948
|
+
function NetworkgraphSeries() {
|
|
2949
|
+
/* *
|
|
2950
|
+
*
|
|
2951
|
+
* Static Properties
|
|
2952
|
+
*
|
|
2953
|
+
* */
|
|
2954
|
+
var _this = _super !== null && _super.apply(this,
|
|
2955
|
+
arguments) || this;
|
|
2956
|
+
/* *
|
|
2957
|
+
*
|
|
2958
|
+
* Properties
|
|
2959
|
+
*
|
|
2960
|
+
* */
|
|
2961
|
+
_this.data = void 0;
|
|
2962
|
+
_this.nodes = void 0;
|
|
2963
|
+
_this.options = void 0;
|
|
2964
|
+
_this.points = void 0;
|
|
2965
|
+
return _this;
|
|
2966
|
+
}
|
|
2967
|
+
/* *
|
|
2968
|
+
*
|
|
2969
|
+
* Static Functions
|
|
2970
|
+
*
|
|
2971
|
+
* */
|
|
2972
|
+
NetworkgraphSeries.compose = function (ChartClass) {
|
|
2973
|
+
DragNodesComposition.compose(ChartClass);
|
|
2974
|
+
ReingoldFruchtermanLayout.compose(ChartClass);
|
|
2975
|
+
};
|
|
2976
|
+
/* *
|
|
2977
|
+
*
|
|
2978
|
+
* Functions
|
|
2979
|
+
*
|
|
2980
|
+
* */
|
|
2266
2981
|
/**
|
|
2267
|
-
*
|
|
2268
|
-
*
|
|
2982
|
+
* Defer the layout.
|
|
2983
|
+
* Each series first registers all nodes and links, then layout
|
|
2984
|
+
* calculates all nodes positions and calls `series.render()` in every
|
|
2985
|
+
* simulation step.
|
|
2986
|
+
*
|
|
2987
|
+
* Note:
|
|
2988
|
+
* Animation is done through `requestAnimationFrame` directly, without
|
|
2989
|
+
* `Highcharts.animate()` use.
|
|
2269
2990
|
* @private
|
|
2270
2991
|
*/
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2992
|
+
NetworkgraphSeries.prototype.deferLayout = function () {
|
|
2993
|
+
var layoutOptions = this.options.layoutAlgorithm,
|
|
2994
|
+
graphLayoutsStorage = this.chart.graphLayoutsStorage,
|
|
2995
|
+
graphLayoutsLookup = this.chart.graphLayoutsLookup,
|
|
2996
|
+
chartOptions = this.chart.options.chart,
|
|
2997
|
+
layout;
|
|
2998
|
+
if (!this.visible) {
|
|
2999
|
+
return;
|
|
3000
|
+
}
|
|
3001
|
+
if (!graphLayoutsStorage) {
|
|
3002
|
+
this.chart.graphLayoutsStorage = graphLayoutsStorage = {};
|
|
3003
|
+
this.chart.graphLayoutsLookup = graphLayoutsLookup = [];
|
|
3004
|
+
}
|
|
3005
|
+
layout = graphLayoutsStorage[layoutOptions.type];
|
|
3006
|
+
if (!layout) {
|
|
3007
|
+
layoutOptions.enableSimulation =
|
|
3008
|
+
!defined(chartOptions.forExport) ?
|
|
3009
|
+
layoutOptions.enableSimulation :
|
|
3010
|
+
!chartOptions.forExport;
|
|
3011
|
+
graphLayoutsStorage[layoutOptions.type] = layout =
|
|
3012
|
+
new GraphLayout.layouts[layoutOptions.type]();
|
|
3013
|
+
layout.init(layoutOptions);
|
|
3014
|
+
graphLayoutsLookup.splice(layout.index, 0, layout);
|
|
3015
|
+
}
|
|
3016
|
+
this.layout = layout;
|
|
3017
|
+
layout.setArea(0, 0, this.chart.plotWidth, this.chart.plotHeight);
|
|
3018
|
+
layout.addElementsToCollection([this], layout.series);
|
|
3019
|
+
layout.addElementsToCollection(this.nodes, layout.nodes);
|
|
3020
|
+
layout.addElementsToCollection(this.points, layout.links);
|
|
3021
|
+
};
|
|
2284
3022
|
/**
|
|
2285
|
-
* Create a single node that holds information on incoming and outgoing
|
|
2286
|
-
* links.
|
|
2287
3023
|
* @private
|
|
2288
3024
|
*/
|
|
2289
|
-
|
|
2290
|
-
destroy: function () {
|
|
3025
|
+
NetworkgraphSeries.prototype.destroy = function () {
|
|
2291
3026
|
if (this.layout) {
|
|
2292
3027
|
this.layout.removeElementFromCollection(this, this.layout.series);
|
|
2293
3028
|
}
|
|
2294
3029
|
NodesComposition.destroy.call(this);
|
|
2295
|
-
}
|
|
2296
|
-
/* eslint-disable no-invalid-this, valid-jsdoc */
|
|
3030
|
+
};
|
|
2297
3031
|
/**
|
|
2298
|
-
*
|
|
2299
|
-
*
|
|
3032
|
+
* Networkgraph has two separate collecions of nodes and lines, render
|
|
3033
|
+
* dataLabels for both sets:
|
|
2300
3034
|
* @private
|
|
2301
3035
|
*/
|
|
2302
|
-
|
|
2303
|
-
var
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
});
|
|
2316
|
-
});
|
|
2317
|
-
return this;
|
|
2318
|
-
},
|
|
3036
|
+
NetworkgraphSeries.prototype.drawDataLabels = function () {
|
|
3037
|
+
var textPath = this.options.dataLabels.textPath;
|
|
3038
|
+
// Render node labels:
|
|
3039
|
+
Series.prototype.drawDataLabels.apply(this, arguments);
|
|
3040
|
+
// Render link labels:
|
|
3041
|
+
this.points = this.data;
|
|
3042
|
+
this.options.dataLabels.textPath =
|
|
3043
|
+
this.options.dataLabels.linkTextPath;
|
|
3044
|
+
Series.prototype.drawDataLabels.apply(this, arguments);
|
|
3045
|
+
// Restore nodes
|
|
3046
|
+
this.points = this.nodes;
|
|
3047
|
+
this.options.dataLabels.textPath = textPath;
|
|
3048
|
+
};
|
|
2319
3049
|
/**
|
|
2320
3050
|
* Extend generatePoints by adding the nodes, which are Point objects
|
|
2321
3051
|
* but pushed to the this.nodes array.
|
|
2322
3052
|
* @private
|
|
2323
3053
|
*/
|
|
2324
|
-
generatePoints
|
|
3054
|
+
NetworkgraphSeries.prototype.generatePoints = function () {
|
|
2325
3055
|
var node,
|
|
2326
3056
|
i;
|
|
2327
3057
|
NodesComposition.generatePoints.apply(this, arguments);
|
|
@@ -2349,154 +3079,70 @@
|
|
|
2349
3079
|
link.formatPrefix = 'link';
|
|
2350
3080
|
});
|
|
2351
3081
|
this.indexateNodes();
|
|
2352
|
-
}
|
|
3082
|
+
};
|
|
2353
3083
|
/**
|
|
2354
3084
|
* In networkgraph, series.points refers to links,
|
|
2355
3085
|
* but series.nodes refers to actual points.
|
|
2356
3086
|
* @private
|
|
2357
3087
|
*/
|
|
2358
|
-
getPointsCollection
|
|
3088
|
+
NetworkgraphSeries.prototype.getPointsCollection = function () {
|
|
2359
3089
|
return this.nodes || [];
|
|
2360
|
-
}
|
|
3090
|
+
};
|
|
2361
3091
|
/**
|
|
2362
3092
|
* Set index for each node. Required for proper `node.update()`.
|
|
2363
3093
|
* Note that links are indexated out of the box in `generatePoints()`.
|
|
2364
3094
|
*
|
|
2365
3095
|
* @private
|
|
2366
3096
|
*/
|
|
2367
|
-
indexateNodes
|
|
3097
|
+
NetworkgraphSeries.prototype.indexateNodes = function () {
|
|
2368
3098
|
this.nodes.forEach(function (node, index) {
|
|
2369
3099
|
node.index = index;
|
|
2370
3100
|
});
|
|
2371
|
-
}
|
|
2372
|
-
/**
|
|
2373
|
-
* Extend the default marker attribs by using a non-rounded X position,
|
|
2374
|
-
* otherwise the nodes will jump from pixel to pixel which looks a bit
|
|
2375
|
-
* jaggy when approaching equilibrium.
|
|
2376
|
-
* @private
|
|
2377
|
-
*/
|
|
2378
|
-
markerAttribs: function (point, state) {
|
|
2379
|
-
var attribs = Series.prototype.markerAttribs.call(this,
|
|
2380
|
-
point,
|
|
2381
|
-
state);
|
|
2382
|
-
// series.render() is called before initial positions are set:
|
|
2383
|
-
if (!defined(point.plotY)) {
|
|
2384
|
-
attribs.y = 0;
|
|
2385
|
-
}
|
|
2386
|
-
attribs.x = (point.plotX || 0) - (attribs.width || 0) / 2;
|
|
2387
|
-
return attribs;
|
|
2388
|
-
},
|
|
3101
|
+
};
|
|
2389
3102
|
/**
|
|
2390
|
-
*
|
|
3103
|
+
* Extend init with base event, which should stop simulation during
|
|
3104
|
+
* update. After data is updated, `chart.render` resumes the simulation.
|
|
2391
3105
|
* @private
|
|
2392
3106
|
*/
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
3107
|
+
NetworkgraphSeries.prototype.init = function (chart, options) {
|
|
3108
|
+
var _this = this;
|
|
3109
|
+
_super.prototype.init.call(this, chart, options);
|
|
3110
|
+
addEvent(this, 'updatedData', function () {
|
|
3111
|
+
if (_this.layout) {
|
|
3112
|
+
_this.layout.stop();
|
|
3113
|
+
}
|
|
3114
|
+
});
|
|
3115
|
+
addEvent(this, 'afterUpdate', function () {
|
|
3116
|
+
_this.nodes.forEach(function (node) {
|
|
3117
|
+
if (node && node.series) {
|
|
3118
|
+
node.resolveColor();
|
|
3119
|
+
}
|
|
2406
3120
|
});
|
|
2407
3121
|
});
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
* Defer the layout.
|
|
2411
|
-
* Each series first registers all nodes and links, then layout
|
|
2412
|
-
* calculates all nodes positions and calls `series.render()` in every
|
|
2413
|
-
* simulation step.
|
|
2414
|
-
*
|
|
2415
|
-
* Note:
|
|
2416
|
-
* Animation is done through `requestAnimationFrame` directly, without
|
|
2417
|
-
* `Highcharts.animate()` use.
|
|
2418
|
-
* @private
|
|
2419
|
-
*/
|
|
2420
|
-
deferLayout: function () {
|
|
2421
|
-
var layoutOptions = this.options.layoutAlgorithm,
|
|
2422
|
-
graphLayoutsStorage = this.chart.graphLayoutsStorage,
|
|
2423
|
-
graphLayoutsLookup = this.chart.graphLayoutsLookup,
|
|
2424
|
-
chartOptions = this.chart.options.chart,
|
|
2425
|
-
layout;
|
|
2426
|
-
if (!this.visible) {
|
|
2427
|
-
return;
|
|
2428
|
-
}
|
|
2429
|
-
if (!graphLayoutsStorage) {
|
|
2430
|
-
this.chart.graphLayoutsStorage = graphLayoutsStorage = {};
|
|
2431
|
-
this.chart.graphLayoutsLookup = graphLayoutsLookup = [];
|
|
2432
|
-
}
|
|
2433
|
-
layout = graphLayoutsStorage[layoutOptions.type];
|
|
2434
|
-
if (!layout) {
|
|
2435
|
-
layoutOptions.enableSimulation =
|
|
2436
|
-
!defined(chartOptions.forExport) ?
|
|
2437
|
-
layoutOptions.enableSimulation :
|
|
2438
|
-
!chartOptions.forExport;
|
|
2439
|
-
graphLayoutsStorage[layoutOptions.type] = layout =
|
|
2440
|
-
new H.layouts[layoutOptions.type]();
|
|
2441
|
-
layout.init(layoutOptions);
|
|
2442
|
-
graphLayoutsLookup.splice(layout.index, 0, layout);
|
|
2443
|
-
}
|
|
2444
|
-
this.layout = layout;
|
|
2445
|
-
layout.setArea(0, 0, this.chart.plotWidth, this.chart.plotHeight);
|
|
2446
|
-
layout.addElementsToCollection([this], layout.series);
|
|
2447
|
-
layout.addElementsToCollection(this.nodes, layout.nodes);
|
|
2448
|
-
layout.addElementsToCollection(this.points, layout.links);
|
|
2449
|
-
},
|
|
3122
|
+
return this;
|
|
3123
|
+
};
|
|
2450
3124
|
/**
|
|
2451
|
-
* Extend the
|
|
2452
|
-
* the
|
|
3125
|
+
* Extend the default marker attribs by using a non-rounded X position,
|
|
3126
|
+
* otherwise the nodes will jump from pixel to pixel which looks a bit
|
|
3127
|
+
* jaggy when approaching equilibrium.
|
|
2453
3128
|
* @private
|
|
2454
3129
|
*/
|
|
2455
|
-
|
|
2456
|
-
var
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
series.redrawHalo(hoverPoint);
|
|
2472
|
-
}
|
|
2473
|
-
if (series.chart.hasRendered &&
|
|
2474
|
-
!series.options.dataLabels.allowOverlap) {
|
|
2475
|
-
series.nodes.concat(series.points).forEach(function (node) {
|
|
2476
|
-
if (node.dataLabel) {
|
|
2477
|
-
dataLabels.push(node.dataLabel);
|
|
2478
|
-
}
|
|
2479
|
-
});
|
|
2480
|
-
series.chart.hideOverlappingLabels(dataLabels);
|
|
2481
|
-
}
|
|
2482
|
-
},
|
|
2483
|
-
// Networkgraph has two separate collecions of nodes and lines, render
|
|
2484
|
-
// dataLabels for both sets:
|
|
2485
|
-
drawDataLabels: function () {
|
|
2486
|
-
var textPath = this.options.dataLabels.textPath;
|
|
2487
|
-
// Render node labels:
|
|
2488
|
-
Series.prototype.drawDataLabels.apply(this, arguments);
|
|
2489
|
-
// Render link labels:
|
|
2490
|
-
this.points = this.data;
|
|
2491
|
-
this.options.dataLabels.textPath =
|
|
2492
|
-
this.options.dataLabels.linkTextPath;
|
|
2493
|
-
Series.prototype.drawDataLabels.apply(this, arguments);
|
|
2494
|
-
// Restore nodes
|
|
2495
|
-
this.points = this.nodes;
|
|
2496
|
-
this.options.dataLabels.textPath = textPath;
|
|
2497
|
-
},
|
|
2498
|
-
// Return the presentational attributes.
|
|
2499
|
-
pointAttribs: function (point, state) {
|
|
3130
|
+
NetworkgraphSeries.prototype.markerAttribs = function (point, state) {
|
|
3131
|
+
var attribs = Series.prototype.markerAttribs.call(this,
|
|
3132
|
+
point,
|
|
3133
|
+
state);
|
|
3134
|
+
// series.render() is called before initial positions are set:
|
|
3135
|
+
if (!defined(point.plotY)) {
|
|
3136
|
+
attribs.y = 0;
|
|
3137
|
+
}
|
|
3138
|
+
attribs.x = (point.plotX || 0) - (attribs.width || 0) / 2;
|
|
3139
|
+
return attribs;
|
|
3140
|
+
};
|
|
3141
|
+
/**
|
|
3142
|
+
* Return the presentational attributes.
|
|
3143
|
+
* @private
|
|
3144
|
+
*/
|
|
3145
|
+
NetworkgraphSeries.prototype.pointAttribs = function (point, state) {
|
|
2500
3146
|
// By default, only `selected` state is passed on
|
|
2501
3147
|
var pointState = state || point && point.state || 'normal',
|
|
2502
3148
|
attribs = Series.prototype.pointAttribs.call(this,
|
|
@@ -2518,323 +3164,102 @@
|
|
|
2518
3164
|
}
|
|
2519
3165
|
}
|
|
2520
3166
|
return attribs;
|
|
2521
|
-
}
|
|
2522
|
-
// Draggable mode:
|
|
2523
|
-
/**
|
|
2524
|
-
* Redraw halo on mousemove during the drag&drop action.
|
|
2525
|
-
* @private
|
|
2526
|
-
* @param {Highcharts.Point} point The point that should show halo.
|
|
2527
|
-
*/
|
|
2528
|
-
redrawHalo: dragNodesMixin.redrawHalo,
|
|
2529
|
-
/**
|
|
2530
|
-
* Mouse down action, initializing drag&drop mode.
|
|
2531
|
-
* @private
|
|
2532
|
-
* @param {global.Event} event Browser event, before normalization.
|
|
2533
|
-
* @param {Highcharts.Point} point The point that event occured.
|
|
2534
|
-
*/
|
|
2535
|
-
onMouseDown: dragNodesMixin.onMouseDown,
|
|
2536
|
-
/**
|
|
2537
|
-
* Mouse move action during drag&drop.
|
|
2538
|
-
* @private
|
|
2539
|
-
* @param {global.Event} event Browser event, before normalization.
|
|
2540
|
-
* @param {Highcharts.Point} point The point that event occured.
|
|
2541
|
-
*/
|
|
2542
|
-
onMouseMove: dragNodesMixin.onMouseMove,
|
|
2543
|
-
/**
|
|
2544
|
-
* Mouse up action, finalizing drag&drop.
|
|
2545
|
-
* @private
|
|
2546
|
-
* @param {Highcharts.Point} point The point that event occured.
|
|
2547
|
-
*/
|
|
2548
|
-
onMouseUp: dragNodesMixin.onMouseUp,
|
|
2549
|
-
/**
|
|
2550
|
-
* When state should be passed down to all points, concat nodes and
|
|
2551
|
-
* links and apply this state to all of them.
|
|
2552
|
-
* @private
|
|
2553
|
-
*/
|
|
2554
|
-
setState: function (state, inherit) {
|
|
2555
|
-
if (inherit) {
|
|
2556
|
-
this.points = this.nodes.concat(this.data);
|
|
2557
|
-
Series.prototype.setState.apply(this, arguments);
|
|
2558
|
-
this.points = this.data;
|
|
2559
|
-
}
|
|
2560
|
-
else {
|
|
2561
|
-
Series.prototype.setState.apply(this, arguments);
|
|
2562
|
-
}
|
|
2563
|
-
// If simulation is done, re-render points with new states:
|
|
2564
|
-
if (!this.layout.simulation && !state) {
|
|
2565
|
-
this.render();
|
|
2566
|
-
}
|
|
2567
|
-
}
|
|
2568
|
-
});
|
|
2569
|
-
/* *
|
|
2570
|
-
*
|
|
2571
|
-
* Class
|
|
2572
|
-
*
|
|
2573
|
-
* */
|
|
2574
|
-
var NetworkgraphPoint = /** @class */ (function (_super) {
|
|
2575
|
-
__extends(NetworkgraphPoint, _super);
|
|
2576
|
-
function NetworkgraphPoint() {
|
|
2577
|
-
/* *
|
|
2578
|
-
*
|
|
2579
|
-
* Properties
|
|
2580
|
-
*
|
|
2581
|
-
* */
|
|
2582
|
-
var _this = _super !== null && _super.apply(this,
|
|
2583
|
-
arguments) || this;
|
|
2584
|
-
_this.degree = void 0;
|
|
2585
|
-
_this.linksFrom = void 0;
|
|
2586
|
-
_this.linksTo = void 0;
|
|
2587
|
-
_this.options = void 0;
|
|
2588
|
-
_this.radius = void 0;
|
|
2589
|
-
_this.series = void 0;
|
|
2590
|
-
_this.toNode = void 0;
|
|
2591
|
-
return _this;
|
|
2592
|
-
}
|
|
2593
|
-
return NetworkgraphPoint;
|
|
2594
|
-
}(Series.prototype.pointClass));
|
|
2595
|
-
extend(NetworkgraphPoint.prototype, {
|
|
2596
|
-
setState: NodesComposition.setNodeState,
|
|
2597
|
-
/**
|
|
2598
|
-
* Basic `point.init()` and additional styles applied when
|
|
2599
|
-
* `series.draggable` is enabled.
|
|
2600
|
-
* @private
|
|
2601
|
-
*/
|
|
2602
|
-
init: function () {
|
|
2603
|
-
Point.prototype.init.apply(this, arguments);
|
|
2604
|
-
if (this.series.options.draggable &&
|
|
2605
|
-
!this.series.chart.styledMode) {
|
|
2606
|
-
addEvent(this, 'mouseOver', function () {
|
|
2607
|
-
css(this.series.chart.container, { cursor: 'move' });
|
|
2608
|
-
});
|
|
2609
|
-
addEvent(this, 'mouseOut', function () {
|
|
2610
|
-
css(this.series.chart.container, { cursor: 'default' });
|
|
2611
|
-
});
|
|
2612
|
-
}
|
|
2613
|
-
return this;
|
|
2614
|
-
},
|
|
2615
|
-
/**
|
|
2616
|
-
* Return degree of a node. If node has no connections, it still has
|
|
2617
|
-
* deg=1.
|
|
2618
|
-
* @private
|
|
2619
|
-
*/
|
|
2620
|
-
getDegree: function () {
|
|
2621
|
-
var deg = this.isNode ?
|
|
2622
|
-
this.linksFrom.length + this.linksTo.length :
|
|
2623
|
-
0;
|
|
2624
|
-
return deg === 0 ? 1 : deg;
|
|
2625
|
-
},
|
|
2626
|
-
// Links:
|
|
2627
|
-
/**
|
|
2628
|
-
* Get presentational attributes of link connecting two nodes.
|
|
2629
|
-
* @private
|
|
2630
|
-
*/
|
|
2631
|
-
getLinkAttributes: function () {
|
|
2632
|
-
var linkOptions = this.series.options.link,
|
|
2633
|
-
pointOptions = this.options;
|
|
2634
|
-
return {
|
|
2635
|
-
'stroke-width': pick(pointOptions.width, linkOptions.width),
|
|
2636
|
-
stroke: (pointOptions.color || linkOptions.color),
|
|
2637
|
-
dashstyle: (pointOptions.dashStyle || linkOptions.dashStyle),
|
|
2638
|
-
opacity: pick(pointOptions.opacity, linkOptions.opacity, 1)
|
|
2639
|
-
};
|
|
2640
|
-
},
|
|
2641
|
-
/**
|
|
2642
|
-
* Render link and add it to the DOM.
|
|
2643
|
-
* @private
|
|
2644
|
-
*/
|
|
2645
|
-
renderLink: function () {
|
|
2646
|
-
var attribs;
|
|
2647
|
-
if (!this.graphic) {
|
|
2648
|
-
this.graphic = this.series.chart.renderer
|
|
2649
|
-
.path(this.getLinkPath())
|
|
2650
|
-
.addClass(this.getClassName(), true)
|
|
2651
|
-
.add(this.series.group);
|
|
2652
|
-
if (!this.series.chart.styledMode) {
|
|
2653
|
-
attribs = this.series.pointAttribs(this);
|
|
2654
|
-
this.graphic.attr(attribs);
|
|
2655
|
-
(this.dataLabels || []).forEach(function (label) {
|
|
2656
|
-
if (label) {
|
|
2657
|
-
label.attr({
|
|
2658
|
-
opacity: attribs.opacity
|
|
2659
|
-
});
|
|
2660
|
-
}
|
|
2661
|
-
});
|
|
2662
|
-
}
|
|
2663
|
-
}
|
|
2664
|
-
},
|
|
3167
|
+
};
|
|
2665
3168
|
/**
|
|
2666
|
-
*
|
|
3169
|
+
* Extend the render function to also render this.nodes together with
|
|
3170
|
+
* the points.
|
|
2667
3171
|
* @private
|
|
2668
3172
|
*/
|
|
2669
|
-
|
|
2670
|
-
var
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
opacity: attribs.opacity
|
|
2683
|
-
});
|
|
2684
|
-
}
|
|
2685
|
-
});
|
|
2686
|
-
}
|
|
2687
|
-
this.graphic.animate(this.shapeArgs);
|
|
2688
|
-
// Required for dataLabels
|
|
2689
|
-
var start = path[0];
|
|
2690
|
-
var end = path[1];
|
|
2691
|
-
if (start[0] === 'M' && end[0] === 'L') {
|
|
2692
|
-
this.plotX = (start[1] + end[1]) / 2;
|
|
2693
|
-
this.plotY = (start[2] + end[2]) / 2;
|
|
3173
|
+
NetworkgraphSeries.prototype.render = function () {
|
|
3174
|
+
var series = this,
|
|
3175
|
+
points = series.points,
|
|
3176
|
+
hoverPoint = series.chart.hoverPoint,
|
|
3177
|
+
dataLabels = [];
|
|
3178
|
+
// Render markers:
|
|
3179
|
+
series.points = series.nodes;
|
|
3180
|
+
lineProto.render.call(this);
|
|
3181
|
+
series.points = points;
|
|
3182
|
+
points.forEach(function (point) {
|
|
3183
|
+
if (point.fromNode && point.toNode) {
|
|
3184
|
+
point.renderLink();
|
|
3185
|
+
point.redrawLink();
|
|
2694
3186
|
}
|
|
2695
|
-
}
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
*/
|
|
2705
|
-
getMass: function () {
|
|
2706
|
-
var m1 = this.fromNode.mass,
|
|
2707
|
-
m2 = this.toNode.mass,
|
|
2708
|
-
sum = m1 + m2;
|
|
2709
|
-
return {
|
|
2710
|
-
fromNode: 1 - m1 / sum,
|
|
2711
|
-
toNode: 1 - m2 / sum
|
|
2712
|
-
};
|
|
2713
|
-
},
|
|
2714
|
-
/**
|
|
2715
|
-
* Get link path connecting two nodes.
|
|
2716
|
-
* @private
|
|
2717
|
-
* @return {Array<Highcharts.SVGPathArray>}
|
|
2718
|
-
* Path: `['M', x, y, 'L', x, y]`
|
|
2719
|
-
*/
|
|
2720
|
-
getLinkPath: function () {
|
|
2721
|
-
var left = this.fromNode,
|
|
2722
|
-
right = this.toNode;
|
|
2723
|
-
// Start always from left to the right node, to prevent rendering
|
|
2724
|
-
// labels upside down
|
|
2725
|
-
if (left.plotX > right.plotX) {
|
|
2726
|
-
left = this.toNode;
|
|
2727
|
-
right = this.fromNode;
|
|
2728
|
-
}
|
|
2729
|
-
return [
|
|
2730
|
-
['M', left.plotX || 0, left.plotY || 0],
|
|
2731
|
-
['L', right.plotX || 0, right.plotY || 0]
|
|
2732
|
-
];
|
|
2733
|
-
/*
|
|
2734
|
-
IDEA: different link shapes?
|
|
2735
|
-
return [
|
|
2736
|
-
'M',
|
|
2737
|
-
from.plotX,
|
|
2738
|
-
from.plotY,
|
|
2739
|
-
'Q',
|
|
2740
|
-
(to.plotX + from.plotX) / 2,
|
|
2741
|
-
(to.plotY + from.plotY) / 2 + 15,
|
|
2742
|
-
to.plotX,
|
|
2743
|
-
to.plotY
|
|
2744
|
-
];*/
|
|
2745
|
-
},
|
|
2746
|
-
isValid: function () {
|
|
2747
|
-
return !this.isNode || defined(this.id);
|
|
2748
|
-
},
|
|
2749
|
-
/**
|
|
2750
|
-
* Common method for removing points and nodes in networkgraph. To
|
|
2751
|
-
* remove `link`, use `series.data[index].remove()`. To remove `node`
|
|
2752
|
-
* with all connections, use `series.nodes[index].remove()`.
|
|
2753
|
-
* @private
|
|
2754
|
-
* @param {boolean} [redraw=true]
|
|
2755
|
-
* Whether to redraw the chart or wait for an explicit call. When
|
|
2756
|
-
* doing more operations on the chart, for example running
|
|
2757
|
-
* `point.remove()` in a loop, it is best practice to set
|
|
2758
|
-
* `redraw` to false and call `chart.redraw()` after.
|
|
2759
|
-
* @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=false]
|
|
2760
|
-
* Whether to apply animation, and optionally animation
|
|
2761
|
-
* configuration.
|
|
2762
|
-
*/
|
|
2763
|
-
remove: function (redraw, animation) {
|
|
2764
|
-
var point = this,
|
|
2765
|
-
series = point.series,
|
|
2766
|
-
nodesOptions = series.options.nodes || [],
|
|
2767
|
-
index,
|
|
2768
|
-
i = nodesOptions.length;
|
|
2769
|
-
// For nodes, remove all connected links:
|
|
2770
|
-
if (point.isNode) {
|
|
2771
|
-
// Temporary disable series.points array, because
|
|
2772
|
-
// Series.removePoint() modifies it
|
|
2773
|
-
series.points = [];
|
|
2774
|
-
// Remove link from all nodes collections:
|
|
2775
|
-
[]
|
|
2776
|
-
.concat(point.linksFrom)
|
|
2777
|
-
.concat(point.linksTo)
|
|
2778
|
-
.forEach(function (linkFromTo) {
|
|
2779
|
-
// Incoming links
|
|
2780
|
-
index = linkFromTo.fromNode.linksFrom.indexOf(linkFromTo);
|
|
2781
|
-
if (index > -1) {
|
|
2782
|
-
linkFromTo.fromNode.linksFrom.splice(index, 1);
|
|
2783
|
-
}
|
|
2784
|
-
// Outcoming links
|
|
2785
|
-
index = linkFromTo.toNode.linksTo.indexOf(linkFromTo);
|
|
2786
|
-
if (index > -1) {
|
|
2787
|
-
linkFromTo.toNode.linksTo.splice(index, 1);
|
|
3187
|
+
});
|
|
3188
|
+
if (hoverPoint && hoverPoint.series === series) {
|
|
3189
|
+
series.redrawHalo(hoverPoint);
|
|
3190
|
+
}
|
|
3191
|
+
if (series.chart.hasRendered &&
|
|
3192
|
+
!series.options.dataLabels.allowOverlap) {
|
|
3193
|
+
series.nodes.concat(series.points).forEach(function (node) {
|
|
3194
|
+
if (node.dataLabel) {
|
|
3195
|
+
dataLabels.push(node.dataLabel);
|
|
2788
3196
|
}
|
|
2789
|
-
// Remove link from data/points collections
|
|
2790
|
-
Series.prototype.removePoint.call(series, series.data.indexOf(linkFromTo), false, false);
|
|
2791
3197
|
});
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
point.destroy();
|
|
2806
|
-
}
|
|
2807
|
-
// Run redraw if requested
|
|
2808
|
-
series.isDirty = true;
|
|
2809
|
-
series.isDirtyData = true;
|
|
2810
|
-
if (redraw) {
|
|
2811
|
-
series.chart.redraw(redraw);
|
|
2812
|
-
}
|
|
3198
|
+
series.chart.hideOverlappingLabels(dataLabels);
|
|
3199
|
+
}
|
|
3200
|
+
};
|
|
3201
|
+
/**
|
|
3202
|
+
* When state should be passed down to all points, concat nodes and
|
|
3203
|
+
* links and apply this state to all of them.
|
|
3204
|
+
* @private
|
|
3205
|
+
*/
|
|
3206
|
+
NetworkgraphSeries.prototype.setState = function (state, inherit) {
|
|
3207
|
+
if (inherit) {
|
|
3208
|
+
this.points = this.nodes.concat(this.data);
|
|
3209
|
+
Series.prototype.setState.apply(this, arguments);
|
|
3210
|
+
this.points = this.data;
|
|
2813
3211
|
}
|
|
2814
3212
|
else {
|
|
2815
|
-
|
|
3213
|
+
Series.prototype.setState.apply(this, arguments);
|
|
2816
3214
|
}
|
|
2817
|
-
|
|
3215
|
+
// If simulation is done, re-render points with new states:
|
|
3216
|
+
if (!this.layout.simulation && !state) {
|
|
3217
|
+
this.render();
|
|
3218
|
+
}
|
|
3219
|
+
};
|
|
2818
3220
|
/**
|
|
2819
|
-
*
|
|
2820
|
-
* node. Then remove point from the layout.
|
|
3221
|
+
* Run pre-translation and register nodes&links to the deffered layout.
|
|
2821
3222
|
* @private
|
|
2822
3223
|
*/
|
|
2823
|
-
|
|
2824
|
-
if (this.
|
|
2825
|
-
this.
|
|
2826
|
-
// Removing multiple nodes at the same time
|
|
2827
|
-
// will try to remove link between nodes twice
|
|
2828
|
-
if (link.destroyElements) {
|
|
2829
|
-
link.destroyElements();
|
|
2830
|
-
}
|
|
2831
|
-
});
|
|
3224
|
+
NetworkgraphSeries.prototype.translate = function () {
|
|
3225
|
+
if (!this.processedXData) {
|
|
3226
|
+
this.processData();
|
|
2832
3227
|
}
|
|
2833
|
-
this.
|
|
2834
|
-
|
|
2835
|
-
|
|
3228
|
+
this.generatePoints();
|
|
3229
|
+
this.deferLayout();
|
|
3230
|
+
this.nodes.forEach(function (node) {
|
|
3231
|
+
// Draw the links from this node
|
|
3232
|
+
node.isInside = true;
|
|
3233
|
+
node.linksFrom.forEach(function (point) {
|
|
3234
|
+
point.shapeType = 'path';
|
|
3235
|
+
// Pass test in drawPoints
|
|
3236
|
+
point.y = 1;
|
|
3237
|
+
});
|
|
3238
|
+
});
|
|
3239
|
+
};
|
|
3240
|
+
NetworkgraphSeries.defaultOptions = merge(Series.defaultOptions, NetworkgraphSeriesDefaults);
|
|
3241
|
+
return NetworkgraphSeries;
|
|
3242
|
+
}(Series));
|
|
3243
|
+
extend(NetworkgraphSeries.prototype, {
|
|
3244
|
+
pointClass: NetworkgraphPoint,
|
|
3245
|
+
animate: void 0,
|
|
3246
|
+
directTouch: true,
|
|
3247
|
+
drawGraph: void 0,
|
|
3248
|
+
forces: ['barycenter', 'repulsive', 'attractive'],
|
|
3249
|
+
hasDraggableNodes: true,
|
|
3250
|
+
isCartesian: false,
|
|
3251
|
+
noSharedTooltip: true,
|
|
3252
|
+
pointArrayMap: ['from', 'to'],
|
|
3253
|
+
requireSorting: false,
|
|
3254
|
+
trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'],
|
|
3255
|
+
buildKDTree: noop,
|
|
3256
|
+
createNode: NodesComposition.createNode,
|
|
3257
|
+
drawTracker: columnProto.drawTracker,
|
|
3258
|
+
onMouseDown: DragNodesComposition.onMouseDown,
|
|
3259
|
+
onMouseMove: DragNodesComposition.onMouseMove,
|
|
3260
|
+
onMouseUp: DragNodesComposition.onMouseUp,
|
|
3261
|
+
redrawHalo: DragNodesComposition.redrawHalo
|
|
2836
3262
|
});
|
|
2837
|
-
NetworkgraphSeries.prototype.pointClass = NetworkgraphPoint;
|
|
2838
3263
|
SeriesRegistry.registerSeriesType('networkgraph', NetworkgraphSeries);
|
|
2839
3264
|
/* *
|
|
2840
3265
|
*
|
|
@@ -2843,156 +3268,52 @@
|
|
|
2843
3268
|
* */
|
|
2844
3269
|
/* *
|
|
2845
3270
|
*
|
|
2846
|
-
* API
|
|
3271
|
+
* API Declarations
|
|
2847
3272
|
*
|
|
2848
3273
|
* */
|
|
2849
3274
|
/**
|
|
2850
|
-
*
|
|
2851
|
-
* not specified, it is inherited from [chart.type](#chart.type).
|
|
2852
|
-
*
|
|
2853
|
-
* @extends series,plotOptions.networkgraph
|
|
2854
|
-
* @excluding boostThreshold, animation, animationLimit, connectEnds,
|
|
2855
|
-
* connectNulls, cropThreshold, dragDrop, getExtremesFromAll, label,
|
|
2856
|
-
* linecap, negativeColor, pointInterval, pointIntervalUnit,
|
|
2857
|
-
* pointPlacement, pointStart, softThreshold, stack, stacking,
|
|
2858
|
-
* step, threshold, xAxis, yAxis, zoneAxis, dataSorting,
|
|
2859
|
-
* boostBlending
|
|
2860
|
-
* @product highcharts
|
|
2861
|
-
* @requires modules/networkgraph
|
|
2862
|
-
* @apioption series.networkgraph
|
|
2863
|
-
*/
|
|
2864
|
-
/**
|
|
2865
|
-
* An array of data points for the series. For the `networkgraph` series type,
|
|
2866
|
-
* points can be given in the following way:
|
|
2867
|
-
*
|
|
2868
|
-
* An array of objects with named values. The following snippet shows only a
|
|
2869
|
-
* few settings, see the complete options set below. If the total number of
|
|
2870
|
-
* data points exceeds the series'
|
|
2871
|
-
* [turboThreshold](#series.area.turboThreshold), this option is not available.
|
|
2872
|
-
*
|
|
2873
|
-
* ```js
|
|
2874
|
-
* data: [{
|
|
2875
|
-
* from: 'Category1',
|
|
2876
|
-
* to: 'Category2'
|
|
2877
|
-
* }, {
|
|
2878
|
-
* from: 'Category1',
|
|
2879
|
-
* to: 'Category3'
|
|
2880
|
-
* }]
|
|
2881
|
-
* ```
|
|
2882
|
-
*
|
|
2883
|
-
* @type {Array<Object|Array|number>}
|
|
2884
|
-
* @extends series.line.data
|
|
2885
|
-
* @excluding drilldown,marker,x,y,draDrop
|
|
2886
|
-
* @sample {highcharts} highcharts/chart/reflow-true/
|
|
2887
|
-
* Numerical values
|
|
2888
|
-
* @sample {highcharts} highcharts/series/data-array-of-arrays/
|
|
2889
|
-
* Arrays of numeric x and y
|
|
2890
|
-
* @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
|
|
2891
|
-
* Arrays of datetime x and y
|
|
2892
|
-
* @sample {highcharts} highcharts/series/data-array-of-name-value/
|
|
2893
|
-
* Arrays of point.name and y
|
|
2894
|
-
* @sample {highcharts} highcharts/series/data-array-of-objects/
|
|
2895
|
-
* Config objects
|
|
2896
|
-
* @product highcharts
|
|
2897
|
-
* @apioption series.networkgraph.data
|
|
2898
|
-
*/
|
|
2899
|
-
/**
|
|
2900
|
-
* @type {Highcharts.SeriesNetworkgraphDataLabelsOptionsObject|Array<Highcharts.SeriesNetworkgraphDataLabelsOptionsObject>}
|
|
2901
|
-
* @product highcharts
|
|
2902
|
-
* @apioption series.networkgraph.data.dataLabels
|
|
2903
|
-
*/
|
|
2904
|
-
/**
|
|
2905
|
-
* The node that the link runs from.
|
|
2906
|
-
*
|
|
2907
|
-
* @type {string}
|
|
2908
|
-
* @product highcharts
|
|
2909
|
-
* @apioption series.networkgraph.data.from
|
|
2910
|
-
*/
|
|
2911
|
-
/**
|
|
2912
|
-
* The node that the link runs to.
|
|
2913
|
-
*
|
|
2914
|
-
* @type {string}
|
|
2915
|
-
* @product highcharts
|
|
2916
|
-
* @apioption series.networkgraph.data.to
|
|
2917
|
-
*/
|
|
2918
|
-
/**
|
|
2919
|
-
* A collection of options for the individual nodes. The nodes in a
|
|
2920
|
-
* networkgraph diagram are auto-generated instances of `Highcharts.Point`,
|
|
2921
|
-
* but options can be applied here and linked by the `id`.
|
|
2922
|
-
*
|
|
2923
|
-
* @sample highcharts/series-networkgraph/data-options/
|
|
2924
|
-
* Networkgraph diagram with node options
|
|
2925
|
-
*
|
|
2926
|
-
* @type {Array<*>}
|
|
2927
|
-
* @product highcharts
|
|
2928
|
-
* @apioption series.networkgraph.nodes
|
|
2929
|
-
*/
|
|
2930
|
-
/**
|
|
2931
|
-
* The id of the auto-generated node, refering to the `from` or `to` setting of
|
|
2932
|
-
* the link.
|
|
2933
|
-
*
|
|
2934
|
-
* @type {string}
|
|
2935
|
-
* @product highcharts
|
|
2936
|
-
* @apioption series.networkgraph.nodes.id
|
|
2937
|
-
*/
|
|
2938
|
-
/**
|
|
2939
|
-
* The color of the auto generated node.
|
|
2940
|
-
*
|
|
2941
|
-
* @type {Highcharts.ColorString}
|
|
2942
|
-
* @product highcharts
|
|
2943
|
-
* @apioption series.networkgraph.nodes.color
|
|
2944
|
-
*/
|
|
2945
|
-
/**
|
|
2946
|
-
* The color index of the auto generated node, especially for use in styled
|
|
2947
|
-
* mode.
|
|
2948
|
-
*
|
|
2949
|
-
* @type {number}
|
|
2950
|
-
* @product highcharts
|
|
2951
|
-
* @apioption series.networkgraph.nodes.colorIndex
|
|
2952
|
-
*/
|
|
2953
|
-
/**
|
|
2954
|
-
* The name to display for the node in data labels and tooltips. Use this when
|
|
2955
|
-
* the name is different from the `id`. Where the id must be unique for each
|
|
2956
|
-
* node, this is not necessary for the name.
|
|
2957
|
-
*
|
|
2958
|
-
* @sample highcharts/series-networkgraph/data-options/
|
|
2959
|
-
* Networkgraph diagram with node options
|
|
2960
|
-
*
|
|
2961
|
-
* @type {string}
|
|
2962
|
-
* @product highcharts
|
|
2963
|
-
* @apioption series.networkgraph.nodes.name
|
|
2964
|
-
*/
|
|
2965
|
-
/**
|
|
2966
|
-
* Mass of the node. By default, each node has mass equal to it's marker radius
|
|
2967
|
-
* . Mass is used to determine how two connected nodes should affect
|
|
2968
|
-
* each other:
|
|
3275
|
+
* Formatter callback function.
|
|
2969
3276
|
*
|
|
2970
|
-
*
|
|
2971
|
-
* nodes; if a big node has weights twice as the small one, then the small one
|
|
2972
|
-
* will move towards the big one twice faster than the big one to the small one
|
|
2973
|
-
* .
|
|
3277
|
+
* @callback Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction
|
|
2974
3278
|
*
|
|
2975
|
-
* @
|
|
2976
|
-
*
|
|
3279
|
+
* @param {Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject|Highcharts.PointLabelObject} this
|
|
3280
|
+
* Data label context to format
|
|
2977
3281
|
*
|
|
2978
|
-
* @
|
|
2979
|
-
*
|
|
2980
|
-
* @apioption series.networkgraph.nodes.mass
|
|
3282
|
+
* @return {string}
|
|
3283
|
+
* Formatted data label text
|
|
2981
3284
|
*/
|
|
2982
3285
|
/**
|
|
2983
|
-
*
|
|
2984
|
-
* the ones for [series.networkgraph.dataLabels](#series.networkgraph.dataLabels).
|
|
2985
|
-
*
|
|
2986
|
-
* @type {Highcharts.SeriesNetworkgraphDataLabelsOptionsObject|Array<Highcharts.SeriesNetworkgraphDataLabelsOptionsObject>}
|
|
3286
|
+
* Context for the formatter function.
|
|
2987
3287
|
*
|
|
2988
|
-
* @
|
|
2989
|
-
|
|
2990
|
-
|
|
3288
|
+
* @interface Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject
|
|
3289
|
+
* @extends Highcharts.PointLabelObject
|
|
3290
|
+
* @since 7.0.0
|
|
3291
|
+
*/ /**
|
|
3292
|
+
* The color of the node.
|
|
3293
|
+
* @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#color
|
|
3294
|
+
* @type {Highcharts.ColorString}
|
|
3295
|
+
* @since 7.0.0
|
|
3296
|
+
*/ /**
|
|
3297
|
+
* The point (node) object. The node name, if defined, is available through
|
|
3298
|
+
* `this.point.name`. Arrays: `this.point.linksFrom` and `this.point.linksTo`
|
|
3299
|
+
* contains all nodes connected to this point.
|
|
3300
|
+
* @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#point
|
|
3301
|
+
* @type {Highcharts.Point}
|
|
3302
|
+
* @since 7.0.0
|
|
3303
|
+
*/ /**
|
|
3304
|
+
* The ID of the node.
|
|
3305
|
+
* @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#key
|
|
3306
|
+
* @type {string}
|
|
3307
|
+
* @since 7.0.0
|
|
3308
|
+
*/
|
|
3309
|
+
''; // detach doclets above
|
|
2991
3310
|
|
|
2992
3311
|
return NetworkgraphSeries;
|
|
2993
3312
|
});
|
|
2994
|
-
_registerModule(_modules, 'masters/modules/networkgraph.src.js', [], function () {
|
|
3313
|
+
_registerModule(_modules, 'masters/modules/networkgraph.src.js', [_modules['Core/Globals.js'], _modules['Series/Networkgraph/NetworkgraphSeries.js']], function (Highcharts, NetworkgraphSeries) {
|
|
2995
3314
|
|
|
3315
|
+
var G = Highcharts;
|
|
3316
|
+
NetworkgraphSeries.compose(G.Chart);
|
|
2996
3317
|
|
|
2997
3318
|
});
|
|
2998
3319
|
}));
|