| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| import { forceLayout } from './forceHelper'; |
| import { simpleLayout } from './simpleLayoutHelper'; |
| import { circularLayout } from './circularLayoutHelper'; |
| import { linearMap } from '../../util/number'; |
| import * as vec2 from 'zrender/src/core/vector'; |
| import * as zrUtil from 'zrender/src/core/util'; |
| export default function (ecModel) { |
| ecModel.eachSeriesByType('graph', function (graphSeries) { |
| var coordSys = graphSeries.coordinateSystem; |
| |
| if (coordSys && coordSys.type !== 'view') { |
| return; |
| } |
| |
| if (graphSeries.get('layout') === 'force') { |
| var preservedPoints = graphSeries.preservedPoints || {}; |
| var graph = graphSeries.getGraph(); |
| var nodeData = graph.data; |
| var edgeData = graph.edgeData; |
| var forceModel = graphSeries.getModel('force'); |
| var initLayout = forceModel.get('initLayout'); |
| |
| if (graphSeries.preservedPoints) { |
| nodeData.each(function (idx) { |
| var id = nodeData.getId(idx); |
| nodeData.setItemLayout(idx, preservedPoints[id] || [NaN, NaN]); |
| }); |
| } else if (!initLayout || initLayout === 'none') { |
| simpleLayout(graphSeries); |
| } else if (initLayout === 'circular') { |
| circularLayout(graphSeries, 'value'); |
| } |
| |
| var nodeDataExtent = nodeData.getDataExtent('value'); |
| var edgeDataExtent = edgeData.getDataExtent('value'); // var edgeDataExtent = edgeData.getDataExtent('value'); |
| |
| var repulsion = forceModel.get('repulsion'); |
| var edgeLength = forceModel.get('edgeLength'); |
| |
| if (!zrUtil.isArray(repulsion)) { |
| repulsion = [repulsion, repulsion]; |
| } |
| |
| if (!zrUtil.isArray(edgeLength)) { |
| edgeLength = [edgeLength, edgeLength]; |
| } // Larger value has smaller length |
| |
| |
| edgeLength = [edgeLength[1], edgeLength[0]]; |
| var nodes = nodeData.mapArray('value', function (value, idx) { |
| var point = nodeData.getItemLayout(idx); |
| var rep = linearMap(value, nodeDataExtent, repulsion); |
| |
| if (isNaN(rep)) { |
| rep = (repulsion[0] + repulsion[1]) / 2; |
| } |
| |
| return { |
| w: rep, |
| rep: rep, |
| fixed: nodeData.getItemModel(idx).get('fixed'), |
| p: !point || isNaN(point[0]) || isNaN(point[1]) ? null : point |
| }; |
| }); |
| var edges = edgeData.mapArray('value', function (value, idx) { |
| var edge = graph.getEdgeByIndex(idx); |
| var d = linearMap(value, edgeDataExtent, edgeLength); |
| |
| if (isNaN(d)) { |
| d = (edgeLength[0] + edgeLength[1]) / 2; |
| } |
| |
| return { |
| n1: nodes[edge.node1.dataIndex], |
| n2: nodes[edge.node2.dataIndex], |
| d: d, |
| curveness: edge.getModel().get('lineStyle.curveness') || 0 |
| }; |
| }); |
| var coordSys = graphSeries.coordinateSystem; |
| var rect = coordSys.getBoundingRect(); |
| var forceInstance = forceLayout(nodes, edges, { |
| rect: rect, |
| gravity: forceModel.get('gravity') |
| }); |
| var oldStep = forceInstance.step; |
| |
| forceInstance.step = function (cb) { |
| for (var i = 0, l = nodes.length; i < l; i++) { |
| if (nodes[i].fixed) { |
| // Write back to layout instance |
| vec2.copy(nodes[i].p, graph.getNodeByIndex(i).getLayout()); |
| } |
| } |
| |
| oldStep(function (nodes, edges, stopped) { |
| for (var i = 0, l = nodes.length; i < l; i++) { |
| if (!nodes[i].fixed) { |
| graph.getNodeByIndex(i).setLayout(nodes[i].p); |
| } |
| |
| preservedPoints[nodeData.getId(i)] = nodes[i].p; |
| } |
| |
| for (var i = 0, l = edges.length; i < l; i++) { |
| var e = edges[i]; |
| var edge = graph.getEdgeByIndex(i); |
| var p1 = e.n1.p; |
| var p2 = e.n2.p; |
| var points = edge.getLayout(); |
| points = points ? points.slice() : []; |
| points[0] = points[0] || []; |
| points[1] = points[1] || []; |
| vec2.copy(points[0], p1); |
| vec2.copy(points[1], p2); |
| |
| if (+e.curveness) { |
| points[2] = [(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * e.curveness, (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * e.curveness]; |
| } |
| |
| edge.setLayout(points); |
| } // Update layout |
| |
| |
| cb && cb(stopped); |
| }); |
| }; |
| |
| graphSeries.forceLayout = forceInstance; |
| graphSeries.preservedPoints = preservedPoints; // Step to get the layout |
| |
| forceInstance.step(); |
| } else { |
| // Remove prev injected forceLayout instance |
| graphSeries.forceLayout = null; |
| } |
| }); |
| } |