navigator.directive.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /**
  2. * @fileOverview
  3. *
  4. * 左下角的导航器
  5. *
  6. * @author: zhangbobell
  7. * @email : zhangbobell@163.com
  8. *
  9. * @copyright: Baidu FEX, 2015 */
  10. angular.module('kityminderEditor')
  11. .directive('navigator', ['memory', 'config', function(memory, config) {
  12. return {
  13. restrict: 'A',
  14. templateUrl: 'ui/directive/navigator/navigator.html',
  15. scope: {
  16. minder: '='
  17. },
  18. link: function(scope) {
  19. minder.setDefaultOptions({zoom: config.get('zoom')});
  20. scope.isNavOpen = !memory.get('navigator-hidden');
  21. scope.getZoomRadio = function(value) {
  22. var zoomStack = minder.getOption('zoom');
  23. var minValue = zoomStack[0];
  24. var maxValue = zoomStack[zoomStack.length - 1];
  25. var valueRange = maxValue - minValue;
  26. return (1 - (value - minValue) / valueRange);
  27. };
  28. scope.getHeight = function(value) {
  29. var totalHeight = $('.zoom-pan').height();
  30. return scope.getZoomRadio(value) * totalHeight;
  31. };
  32. // 初始的缩放倍数
  33. scope.zoom = 100;
  34. // 发生缩放事件时
  35. minder.on('zoom', function(e) {
  36. scope.zoom = e.zoom;
  37. });
  38. scope.toggleNavOpen = function() {
  39. scope.isNavOpen = !scope.isNavOpen;
  40. memory.set('navigator-hidden', !scope.isNavOpen);
  41. if (scope.isNavOpen) {
  42. bind();
  43. updateContentView();
  44. updateVisibleView();
  45. } else{
  46. unbind();
  47. }
  48. };
  49. setTimeout(function() {
  50. if (scope.isNavOpen) {
  51. bind();
  52. updateContentView();
  53. updateVisibleView();
  54. } else{
  55. unbind();
  56. }
  57. }, 0);
  58. function bind() {
  59. minder.on('layout layoutallfinish', updateContentView);
  60. minder.on('viewchange', updateVisibleView);
  61. }
  62. function unbind() {
  63. minder.off('layout layoutallfinish', updateContentView);
  64. minder.off('viewchange', updateVisibleView);
  65. }
  66. /** 以下部分是缩略图导航器 *
  67. * */
  68. var $previewNavigator = $('.nav-previewer');
  69. // 画布,渲染缩略图
  70. var paper = new kity.Paper($previewNavigator[0]);
  71. // 用两个路径来挥之节点和连线的缩略图
  72. var nodeThumb = paper.put(new kity.Path());
  73. var connectionThumb = paper.put(new kity.Path());
  74. // 表示可视区域的矩形
  75. var visibleRect = paper.put(new kity.Rect(100, 100).stroke('red', '1%'));
  76. var contentView = new kity.Box(), visibleView = new kity.Box();
  77. /**
  78. * 增加一个对天盘图情况缩略图的处理,
  79. * @Editor: Naixor line 104~129
  80. * @Date: 2015.11.3
  81. */
  82. var pathHandler = getPathHandler(minder.getTheme());
  83. // 主题切换事件
  84. minder.on('themechange', function(e) {
  85. pathHandler = getPathHandler(e.theme);
  86. });
  87. function getPathHandler(theme) {
  88. switch (theme) {
  89. case "tianpan":
  90. case "tianpan-compact":
  91. return function(nodePathData, x, y, width, height) {
  92. var r = width >> 1;
  93. nodePathData.push('M', x, y + r,
  94. 'a', r, r, 0, 1, 1, 0, 0.01,
  95. 'z');
  96. }
  97. default: {
  98. return function(nodePathData, x, y, width, height) {
  99. nodePathData.push('M', x, y,
  100. 'h', width, 'v', height,
  101. 'h', -width, 'z');
  102. }
  103. }
  104. }
  105. }
  106. navigate();
  107. function navigate() {
  108. function moveView(center, duration) {
  109. var box = visibleView;
  110. center.x = -center.x;
  111. center.y = -center.y;
  112. var viewMatrix = minder.getPaper().getViewPortMatrix();
  113. box = viewMatrix.transformBox(box);
  114. var targetPosition = center.offset(box.width / 2, box.height / 2);
  115. minder.getViewDragger().moveTo(targetPosition, duration);
  116. }
  117. var dragging = false;
  118. paper.on('mousedown', function(e) {
  119. dragging = true;
  120. moveView(e.getPosition('top'), 200);
  121. $previewNavigator.addClass('grab');
  122. });
  123. paper.on('mousemove', function(e) {
  124. if (dragging) {
  125. moveView(e.getPosition('top'));
  126. }
  127. });
  128. $(window).on('mouseup', function() {
  129. dragging = false;
  130. $previewNavigator.removeClass('grab');
  131. });
  132. }
  133. function updateContentView() {
  134. var view = minder.getRenderContainer().getBoundaryBox();
  135. contentView = view;
  136. var padding = 30;
  137. paper.setViewBox(
  138. view.x - padding - 0.5,
  139. view.y - padding - 0.5,
  140. view.width + padding * 2 + 1,
  141. view.height + padding * 2 + 1);
  142. var nodePathData = [];
  143. var connectionThumbData = [];
  144. minder.getRoot().traverse(function(node) {
  145. var box = node.getLayoutBox();
  146. pathHandler(nodePathData, box.x, box.y, box.width, box.height);
  147. if (node.getConnection() && node.parent && node.parent.isExpanded()) {
  148. connectionThumbData.push(node.getConnection().getPathData());
  149. }
  150. });
  151. paper.setStyle('background', minder.getStyle('background'));
  152. if (nodePathData.length) {
  153. nodeThumb
  154. .fill(minder.getStyle('root-background'))
  155. .setPathData(nodePathData);
  156. } else {
  157. nodeThumb.setPathData(null);
  158. }
  159. if (connectionThumbData.length) {
  160. connectionThumb
  161. .stroke(minder.getStyle('connect-color'), '0.5%')
  162. .setPathData(connectionThumbData);
  163. } else {
  164. connectionThumb.setPathData(null);
  165. }
  166. updateVisibleView();
  167. }
  168. function updateVisibleView() {
  169. visibleView = minder.getViewDragger().getView();
  170. visibleRect.setBox(visibleView.intersect(contentView));
  171. }
  172. }
  173. }
  174. }]);