forceLayout.js 6.4 KB

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