forceLayout.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. var _forceHelper = require("./forceHelper");
  20. var forceLayout = _forceHelper.forceLayout;
  21. var _simpleLayoutHelper = require("./simpleLayoutHelper");
  22. var simpleLayout = _simpleLayoutHelper.simpleLayout;
  23. var _circularLayoutHelper = require("./circularLayoutHelper");
  24. var circularLayout = _circularLayoutHelper.circularLayout;
  25. var _number = require("../../util/number");
  26. var linearMap = _number.linearMap;
  27. var vec2 = require("zrender/lib/core/vector");
  28. var zrUtil = require("zrender/lib/core/util");
  29. var _multipleGraphEdgeHelper = require("../helper/multipleGraphEdgeHelper");
  30. var getCurvenessForEdge = _multipleGraphEdgeHelper.getCurvenessForEdge;
  31. /*
  32. * Licensed to the Apache Software Foundation (ASF) under one
  33. * or more contributor license agreements. See the NOTICE file
  34. * distributed with this work for additional information
  35. * regarding copyright ownership. The ASF licenses this file
  36. * to you under the Apache License, Version 2.0 (the
  37. * "License"); you may not use this file except in compliance
  38. * with the License. You may obtain a copy of the License at
  39. *
  40. * http://www.apache.org/licenses/LICENSE-2.0
  41. *
  42. * Unless required by applicable law or agreed to in writing,
  43. * software distributed under the License is distributed on an
  44. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  45. * KIND, either express or implied. See the License for the
  46. * specific language governing permissions and limitations
  47. * under the License.
  48. */
  49. function _default(ecModel) {
  50. ecModel.eachSeriesByType('graph', function (graphSeries) {
  51. var coordSys = graphSeries.coordinateSystem;
  52. if (coordSys && coordSys.type !== 'view') {
  53. return;
  54. }
  55. if (graphSeries.get('layout') === 'force') {
  56. var preservedPoints = graphSeries.preservedPoints || {};
  57. var graph = graphSeries.getGraph();
  58. var nodeData = graph.data;
  59. var edgeData = graph.edgeData;
  60. var forceModel = graphSeries.getModel('force');
  61. var initLayout = forceModel.get('initLayout');
  62. if (graphSeries.preservedPoints) {
  63. nodeData.each(function (idx) {
  64. var id = nodeData.getId(idx);
  65. nodeData.setItemLayout(idx, preservedPoints[id] || [NaN, NaN]);
  66. });
  67. } else if (!initLayout || initLayout === 'none') {
  68. simpleLayout(graphSeries);
  69. } else if (initLayout === 'circular') {
  70. circularLayout(graphSeries, 'value');
  71. }
  72. var nodeDataExtent = nodeData.getDataExtent('value');
  73. var edgeDataExtent = edgeData.getDataExtent('value'); // var edgeDataExtent = edgeData.getDataExtent('value');
  74. var repulsion = forceModel.get('repulsion');
  75. var edgeLength = forceModel.get('edgeLength');
  76. if (!zrUtil.isArray(repulsion)) {
  77. repulsion = [repulsion, repulsion];
  78. }
  79. if (!zrUtil.isArray(edgeLength)) {
  80. edgeLength = [edgeLength, edgeLength];
  81. } // Larger value has smaller length
  82. edgeLength = [edgeLength[1], edgeLength[0]];
  83. var nodes = nodeData.mapArray('value', function (value, idx) {
  84. var point = nodeData.getItemLayout(idx);
  85. var rep = linearMap(value, nodeDataExtent, repulsion);
  86. if (isNaN(rep)) {
  87. rep = (repulsion[0] + repulsion[1]) / 2;
  88. }
  89. return {
  90. w: rep,
  91. rep: rep,
  92. fixed: nodeData.getItemModel(idx).get('fixed'),
  93. p: !point || isNaN(point[0]) || isNaN(point[1]) ? null : point
  94. };
  95. });
  96. var edges = edgeData.mapArray('value', function (value, idx) {
  97. var edge = graph.getEdgeByIndex(idx);
  98. var d = linearMap(value, edgeDataExtent, edgeLength);
  99. if (isNaN(d)) {
  100. d = (edgeLength[0] + edgeLength[1]) / 2;
  101. }
  102. var edgeModel = edge.getModel();
  103. var curveness = zrUtil.retrieve3(edgeModel.get('lineStyle.curveness'), -getCurvenessForEdge(edge, graphSeries, idx, true), 0);
  104. return {
  105. n1: nodes[edge.node1.dataIndex],
  106. n2: nodes[edge.node2.dataIndex],
  107. d: d,
  108. curveness: curveness,
  109. ignoreForceLayout: edgeModel.get('ignoreForceLayout')
  110. };
  111. });
  112. var coordSys = graphSeries.coordinateSystem;
  113. var rect = coordSys.getBoundingRect();
  114. var forceInstance = forceLayout(nodes, edges, {
  115. rect: rect,
  116. gravity: forceModel.get('gravity'),
  117. friction: forceModel.get('friction')
  118. });
  119. var oldStep = forceInstance.step;
  120. forceInstance.step = function (cb) {
  121. for (var i = 0, l = nodes.length; i < l; i++) {
  122. if (nodes[i].fixed) {
  123. // Write back to layout instance
  124. vec2.copy(nodes[i].p, graph.getNodeByIndex(i).getLayout());
  125. }
  126. }
  127. oldStep(function (nodes, edges, stopped) {
  128. for (var i = 0, l = nodes.length; i < l; i++) {
  129. if (!nodes[i].fixed) {
  130. graph.getNodeByIndex(i).setLayout(nodes[i].p);
  131. }
  132. preservedPoints[nodeData.getId(i)] = nodes[i].p;
  133. }
  134. for (var i = 0, l = edges.length; i < l; i++) {
  135. var e = edges[i];
  136. var edge = graph.getEdgeByIndex(i);
  137. var p1 = e.n1.p;
  138. var p2 = e.n2.p;
  139. var points = edge.getLayout();
  140. points = points ? points.slice() : [];
  141. points[0] = points[0] || [];
  142. points[1] = points[1] || [];
  143. vec2.copy(points[0], p1);
  144. vec2.copy(points[1], p2);
  145. if (+e.curveness) {
  146. points[2] = [(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * e.curveness, (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * e.curveness];
  147. }
  148. edge.setLayout(points);
  149. } // Update layout
  150. cb && cb(stopped);
  151. });
  152. };
  153. graphSeries.forceLayout = forceInstance;
  154. graphSeries.preservedPoints = preservedPoints; // Step to get the layout
  155. forceInstance.step();
  156. } else {
  157. // Remove prev injected forceLayout instance
  158. graphSeries.forceLayout = null;
  159. }
  160. });
  161. }
  162. module.exports = _default;