index.vue 4.9 KB

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