select.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. define(function(require, exports, module) {
  2. var kity = require('../core/kity');
  3. var utils = require('../core/utils');
  4. var Minder = require('../core/minder');
  5. var MinderNode = require('../core/node');
  6. var Command = require('../core/command');
  7. var Module = require('../core/module');
  8. var Renderer = require('../core/render');
  9. Module.register('Select', function() {
  10. var minder = this;
  11. var rc = minder.getRenderContainer();
  12. // 在实例上渲染框选矩形、计算框选范围的对象
  13. var marqueeActivator = (function() {
  14. // 记录选区的开始位置(mousedown的位置)
  15. var startPosition = null;
  16. // 选区的图形
  17. var marqueeShape = new kity.Path();
  18. // 标记是否已经启动框选状态
  19. // 并不是 mousedown 发生之后就启动框选状态,而是检测到移动了一定的距离(MARQUEE_MODE_THRESHOLD)之后
  20. var marqueeMode = false;
  21. var MARQUEE_MODE_THRESHOLD = 10;
  22. return {
  23. selectStart: function(e) {
  24. // 只接受左键
  25. if (e.originEvent.button || e.originEvent.altKey) return;
  26. // 清理不正确状态
  27. if (startPosition) {
  28. return this.selectEnd();
  29. }
  30. startPosition = e.getPosition(rc).round();
  31. },
  32. selectMove: function(e) {
  33. if (minder.getStatus() == 'textedit') {
  34. return;
  35. }
  36. if (!startPosition) return;
  37. var p1 = startPosition,
  38. p2 = e.getPosition(rc);
  39. // 检测是否要进入选区模式
  40. if (!marqueeMode) {
  41. // 距离没达到阈值,退出
  42. if (kity.Vector.fromPoints(p1, p2).length() < MARQUEE_MODE_THRESHOLD) {
  43. return;
  44. }
  45. // 已经达到阈值,记录下来并且重置选区形状
  46. marqueeMode = true;
  47. rc.addShape(marqueeShape);
  48. marqueeShape
  49. .fill(minder.getStyle('marquee-background'))
  50. .stroke(minder.getStyle('marquee-stroke')).setOpacity(0.8).getDrawer().clear();
  51. }
  52. var marquee = new kity.Box(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y),
  53. selectedNodes = [];
  54. // 使其犀利
  55. marquee.left = Math.round(marquee.left);
  56. marquee.top = Math.round(marquee.top);
  57. marquee.right = Math.round(marquee.right);
  58. marquee.bottom = Math.round(marquee.bottom);
  59. // 选区形状更新
  60. marqueeShape.getDrawer().pipe(function() {
  61. this.clear();
  62. this.moveTo(marquee.left, marquee.top);
  63. this.lineTo(marquee.right, marquee.top);
  64. this.lineTo(marquee.right, marquee.bottom);
  65. this.lineTo(marquee.left, marquee.bottom);
  66. this.close();
  67. });
  68. // 计算选中范围
  69. minder.getRoot().traverse(function(node) {
  70. var renderBox = node.getLayoutBox();
  71. if (!renderBox.intersect(marquee).isEmpty()) {
  72. selectedNodes.push(node);
  73. }
  74. });
  75. // 应用选中范围
  76. minder.select(selectedNodes, true);
  77. // 清除多余的东西
  78. window.getSelection().removeAllRanges();
  79. },
  80. selectEnd: function(e) {
  81. if (startPosition) {
  82. startPosition = null;
  83. }
  84. if (marqueeMode) {
  85. marqueeShape.fadeOut(200, 'ease', 0, function() {
  86. if (marqueeShape.remove) marqueeShape.remove();
  87. });
  88. marqueeMode = false;
  89. }
  90. }
  91. };
  92. })();
  93. var lastDownNode = null,
  94. lastDownPosition = null;
  95. return {
  96. 'init': function() {
  97. window.addEventListener('mouseup', function() {
  98. marqueeActivator.selectEnd();
  99. });
  100. },
  101. 'events': {
  102. 'mousedown': function(e) {
  103. var downNode = e.getTargetNode();
  104. // 没有点中节点:
  105. // 清除选中状态,并且标记选区开始位置
  106. if (!downNode) {
  107. this.removeAllSelectedNodes();
  108. marqueeActivator.selectStart(e);
  109. this.setStatus('normal');
  110. }
  111. // 点中了节点,并且按了 shift 键:
  112. // 被点中的节点切换选中状态
  113. else if (e.isShortcutKey('Ctrl')) {
  114. this.toggleSelect(downNode);
  115. }
  116. // 点中的节点没有被选择:
  117. // 单选点中的节点
  118. else if (!downNode.isSelected()) {
  119. this.select(downNode, true);
  120. }
  121. // 点中的节点被选中了,并且不是单选:
  122. // 完成整个点击之后需要使其变为单选。
  123. // 不能马上变为单选,因为可能是需要拖动选中的多个节点
  124. else if (!this.isSingleSelect()) {
  125. lastDownNode = downNode;
  126. lastDownPosition = e.getPosition();
  127. }
  128. },
  129. 'mousemove': marqueeActivator.selectMove,
  130. 'mouseup': function(e) {
  131. var upNode = e.getTargetNode();
  132. // 如果 mouseup 发生在 lastDownNode 外,是无需理会的
  133. if (upNode && upNode == lastDownNode) {
  134. var upPosition = e.getPosition();
  135. var movement = kity.Vector.fromPoints(lastDownPosition, upPosition);
  136. if (movement.length() < 1) this.select(lastDownNode, true);
  137. lastDownNode = null;
  138. }
  139. // 清理一下选择状态
  140. marqueeActivator.selectEnd(e);
  141. },
  142. //全选操作
  143. 'normal.keydown': function(e) {
  144. if (e.isShortcutKey('ctrl+a')) {
  145. var selectedNodes = [];
  146. this.getRoot().traverse(function(node) {
  147. selectedNodes.push(node);
  148. });
  149. this.select(selectedNodes, true);
  150. e.preventDefault();
  151. }
  152. }
  153. }
  154. };
  155. });
  156. });