index.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. let left = Math.min(this.startX, this.endX) + 'px'
  54. let top = Math.min(this.startY, this.endY) + 'px'
  55. const left1 = Math.min(this.startX, this.endX) + 50 * this.scale + 'px'
  56. const top1 = Math.min(this.startY, this.endY) + 50 * this.scale + 'px'
  57. const width = Math.abs(this.endX - this.startX) + 'px'
  58. const height = Math.abs(this.endY - this.startY) + 'px'
  59. if (!this.isSelecting) {
  60. return {
  61. display: 'none'
  62. }
  63. }
  64. return {
  65. position: 'absolute',
  66. left,
  67. top,
  68. width,
  69. height,
  70. border: '1px dashed #007aff',
  71. background: '#2a2e3380'
  72. }
  73. }
  74. },
  75. methods: {
  76. ...mapMutations('bigScreen',
  77. [
  78. 'changeActiveCodes',
  79. 'changeActiveCode'
  80. ]
  81. ),
  82. handleMouseDown (event) {
  83. // 点击在底部背景上
  84. if (event.button === 0) {
  85. time = new Date()
  86. // 避免和shift + 点击多选组件冲突
  87. if (this.shiftKeyDown) {
  88. return
  89. }
  90. this.isSelectDown = true
  91. // 点击在底部背景上
  92. if (typeof event.target.className === 'string' && event.target.className.indexOf('mouse-select-wrap') !== -1) {
  93. this.startX = event.offsetX
  94. this.endX = event.offsetX
  95. this.startY = event.offsetY
  96. this.endY = event.offsetY
  97. } else if (typeof event.target.className === 'string' && event.target.className.indexOf('design-drag-wrap') !== -1) {
  98. this.startX = event.offsetX + 50
  99. this.endX = event.offsetX + 50
  100. this.startY = event.offsetY + 50
  101. this.endY = event.offsetY + 50
  102. }
  103. // this.startX = (event.x - this.offsetX + 50) / this.scale
  104. // this.startY = (event.y - this.offsetY + 50) / this.scale
  105. // this.endX = (event.x - this.offsetX + 50) / this.scale
  106. // this.endY = (event.y - this.offsetY + 50) / this.scale
  107. }
  108. },
  109. handleMouseMove (event) {
  110. if (!this.isSelectDown) {
  111. return
  112. }
  113. newTime = new Date()
  114. // if (newTime - time > 300) {
  115. this.isSelecting = true
  116. // }
  117. if (this.isSelecting) {
  118. if (typeof event.target.className === 'string' && event.target.className.indexOf('mouse-select-wrap') !== -1) {
  119. this.endX = event.offsetX
  120. this.endY = event.offsetY
  121. } else if (typeof event.target.className === 'string' && event.target.className.indexOf('design-drag-wrap') !== -1) {
  122. this.startX = event.offsetX + 50
  123. this.endY = event.offsetY + 50
  124. }
  125. }
  126. },
  127. handleMouseUp (event) {
  128. this.isSelectDown = false
  129. // 按下鼠标和抬起鼠标时间间隔小表示单击,否则表示框选结束
  130. // 避免和shift + 点击多选组件冲突
  131. // 避免和右键点击冲突
  132. if (
  133. newTime - time < 300 &&
  134. !this.shiftKeyDown &&
  135. event.button !== 2
  136. ) {
  137. // 按下鼠标和抬起鼠标时间间隔小表示单击,否则表示框选结束
  138. // this.changeActiveCodes([])
  139. // this.changeActiveCode('')
  140. }
  141. // 鼠标按下,并开始选择
  142. if (event.button === 0 && this.isSelecting) {
  143. this.isSelecting = false
  144. if (newTime - time < 300) {
  145. newTime = 0
  146. time = 0
  147. return
  148. }
  149. newTime = 0
  150. time = 0
  151. // 在这里可以根据起始点和结束点的坐标计算选中的区域,进行相应的操作
  152. this.$emit('selectArea', {
  153. startX: Math.min(this.startX, this.endX),
  154. startY: Math.min(this.startY, this.endY),
  155. endX: Math.max(this.startX, this.endX),
  156. endY: Math.max(this.startY, this.endY)
  157. })
  158. // 重置起始点和结束点的坐标
  159. this.startX = 0
  160. this.startY = 0
  161. this.endX = 0
  162. this.endY = 0
  163. } else if (!this.shiftKeyDown && !this.isSelecting) {
  164. // 重置起始点和结束点的坐标
  165. this.startX = 0
  166. this.startY = 0
  167. this.endX = 0
  168. this.endY = 0
  169. // this.$emit('selectArea', {
  170. // startX: Math.min(this.startX, this.endX),
  171. // startY: Math.min(this.startY, this.endY),
  172. // endX: Math.max(this.startX, this.endX),
  173. // endY: Math.max(this.startY, this.endY)
  174. // })
  175. // this.changeActiveCodes([])
  176. }
  177. },
  178. handleMouseLeave () {
  179. this.isSelecting = false
  180. this.isSelectDown = false
  181. this.startX = 0
  182. this.startY = 0
  183. this.endX = 0
  184. this.endY = 0
  185. }
  186. }
  187. }
  188. </script>
  189. <style scoped lang="scss">
  190. .mouse-select-wrap{
  191. width: 200%;
  192. height: 200%;
  193. margin: -50px;
  194. padding: 50px;
  195. }
  196. .notSelect {
  197. user-select: none;
  198. pointer-events: none;
  199. }
  200. </style>