index.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <template>
  2. <div
  3. style="position: relative; user-select: none;"
  4. @mousedown="handleMouseDown"
  5. @mousemove="handleMouseMove"
  6. @mouseup="handleMouseUp"
  7. @mouseleave="handleMouseLeave"
  8. >
  9. <!-- 这里是需要进行框选的内容 -->
  10. <div :class="{ 'notSelect': isSelecting }">
  11. <slot />
  12. </div>
  13. <!-- 在鼠标框选移动时生成虚线框 -->
  14. <div
  15. v-if="isSelecting"
  16. :style="getSelectionBoxStyle"
  17. />
  18. </div>
  19. </template>
  20. <script>
  21. import { mapMutations, mapState } from 'vuex'
  22. let time = 0
  23. let newTime = 0
  24. export default {
  25. props: {
  26. offsetX: {
  27. type: Number,
  28. default: 340 + 50
  29. },
  30. offsetY: {
  31. type: Number,
  32. default: 73 + 50
  33. }
  34. },
  35. data () {
  36. return {
  37. isSelecting: false, // 是否正在进行框选
  38. isSelectDown: false, // 是否按下鼠标左键
  39. startX: 0, // 框选起始点的横坐标
  40. startY: 0, // 框选起始点的纵坐标
  41. endX: 0, // 框选结束点的横坐标
  42. endY: 0 // 框选结束点的纵坐标
  43. }
  44. },
  45. computed: {
  46. ...mapState('bigScreen', {
  47. shiftKeyDown: state => state.shiftKeyDown,
  48. scale: state => state.zoom / 100
  49. }),
  50. getSelectionBoxStyle () {
  51. // 计算虚线框的样式
  52. const left = Math.min(this.startX, this.endX) + 'px'
  53. const top = Math.min(this.startY, this.endY) + 'px'
  54. const width = Math.abs(this.endX - this.startX) + 'px'
  55. const height = Math.abs(this.endY - this.startY) + 'px'
  56. if (!this.isSelecting) {
  57. return {
  58. display: 'none'
  59. }
  60. }
  61. return {
  62. position: 'absolute',
  63. left,
  64. top,
  65. width,
  66. height,
  67. border: '1px dashed #007aff',
  68. background: '#2a2e3380'
  69. }
  70. }
  71. },
  72. methods: {
  73. ...mapMutations('bigScreen',
  74. [
  75. 'changeActiveCodes',
  76. 'changeActiveCode'
  77. ]
  78. ),
  79. handleMouseDown (event) {
  80. if (event.button === 0) {
  81. time = new Date()
  82. // 避免和shift + 点击多选组件冲突
  83. if (this.shiftKeyDown) {
  84. return
  85. }
  86. this.isSelectDown = true
  87. this.startX = (event.x - this.offsetX) / this.scale
  88. this.startY = (event.y - this.offsetY) / this.scale
  89. this.endX = (event.x - this.offsetX) / this.scale
  90. this.endY = (event.y - this.offsetY) / this.scale
  91. }
  92. },
  93. handleMouseMove (event) {
  94. if (!this.isSelectDown) {
  95. return
  96. }
  97. newTime = new Date()
  98. if (newTime - time > 300) {
  99. this.isSelecting = true
  100. }
  101. if (this.isSelecting) {
  102. this.endX = (event.x - this.offsetX) / this.scale
  103. this.endY = (event.y - this.offsetY) / this.scale
  104. }
  105. },
  106. handleMouseUp (event) {
  107. this.isSelectDown = false
  108. // 按下鼠标和抬起鼠标时间间隔小表示单击,否则表示框选结束
  109. // 避免和shift + 点击多选组件冲突
  110. // 避免和右键点击冲突
  111. if (
  112. newTime - time < 300 &&
  113. !this.shiftKeyDown &&
  114. event.button !== 2
  115. ) {
  116. // 按下鼠标和抬起鼠标时间间隔小表示单击,否则表示框选结束
  117. // this.changeActiveCodes([])
  118. // this.changeActiveCode('')
  119. }
  120. // 鼠标按下,并开始选择
  121. if (event.button === 0 && this.isSelecting) {
  122. this.isSelecting = false
  123. if (newTime - time < 300) {
  124. newTime = 0
  125. time = 0
  126. return
  127. }
  128. newTime = 0
  129. time = 0
  130. // 在这里可以根据起始点和结束点的坐标计算选中的区域,进行相应的操作
  131. this.$emit('selectArea', {
  132. startX: Math.min(this.startX, this.endX),
  133. startY: Math.min(this.startY, this.endY),
  134. endX: Math.max(this.startX, this.endX),
  135. endY: Math.max(this.startY, this.endY)
  136. })
  137. // 重置起始点和结束点的坐标
  138. this.startX = 0
  139. this.startY = 0
  140. this.endX = 0
  141. this.endY = 0
  142. } else if (!this.shiftKeyDown && !this.isSelecting) {
  143. // 重置起始点和结束点的坐标
  144. this.startX = 0
  145. this.startY = 0
  146. this.endX = 0
  147. this.endY = 0
  148. this.$emit('selectArea', {
  149. startX: Math.min(this.startX, this.endX),
  150. startY: Math.min(this.startY, this.endY),
  151. endX: Math.max(this.startX, this.endX),
  152. endY: Math.max(this.startY, this.endY)
  153. })
  154. this.changeActiveCodes([])
  155. }
  156. },
  157. handleMouseLeave () {
  158. this.isSelecting = false
  159. this.isSelectDown = false
  160. this.startX = 0
  161. this.startY = 0
  162. this.endX = 0
  163. this.endY = 0
  164. }
  165. }
  166. }
  167. </script>
  168. <style scoped>
  169. .notSelect {
  170. user-select: none;
  171. pointer-events: none;
  172. }
  173. </style>