MultiSelectOperate.vue 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. <template>
  2. <div
  3. class="multi-select-operate"
  4. :style="{
  5. left: range.minX * canvasScale + 'px',
  6. top: range.minY * canvasScale + 'px',
  7. }"
  8. >
  9. <BorderLine v-for="line in borderLines" :key="line.type" :type="line.type" :style="line.style" />
  10. <template v-if="!disableResize">
  11. <ResizeHandler
  12. v-for="point in resizeHandlers"
  13. :key="point.direction"
  14. :type="point.direction"
  15. :style="point.style"
  16. @mousedown.stop="scaleMultiElement($event, range, point.direction)"
  17. />
  18. </template>
  19. </div>
  20. </template>
  21. <script lang="ts" setup>
  22. import { computed, ref, watchEffect } from 'vue'
  23. import { storeToRefs } from 'pinia'
  24. import { useMainStore } from '@/store'
  25. import type { PPTElement } from '@/types/slides'
  26. import { getElementListRange } from '@/utils/element'
  27. import type { OperateResizeHandlers, MultiSelectRange } from '@/types/edit'
  28. import useCommonOperate from '../hooks/useCommonOperate'
  29. import ResizeHandler from './ResizeHandler.vue'
  30. import BorderLine from './BorderLine.vue'
  31. const props = defineProps<{
  32. elementList: PPTElement[]
  33. scaleMultiElement: (e: MouseEvent, range: MultiSelectRange, command: OperateResizeHandlers) => void
  34. }>()
  35. const { activeElementIdList, canvasScale } = storeToRefs(useMainStore())
  36. const localActiveElementList = computed(() => props.elementList.filter(el => activeElementIdList.value.includes(el.id)))
  37. const range = ref({
  38. minX: 0,
  39. maxX: 0,
  40. minY: 0,
  41. maxY: 0,
  42. })
  43. // 根据多选元素整体在画布中的范围,计算边框线和缩放点的位置信息
  44. const width = computed(() => (range.value.maxX - range.value.minX) * canvasScale.value)
  45. const height = computed(() => (range.value.maxY - range.value.minY) * canvasScale.value)
  46. const { resizeHandlers, borderLines } = useCommonOperate(width, height)
  47. // 计算多选元素整体在画布中的范围
  48. const setRange = () => {
  49. const { minX, maxX, minY, maxY } = getElementListRange(localActiveElementList.value)
  50. range.value = { minX, maxX, minY, maxY }
  51. }
  52. watchEffect(setRange)
  53. // 禁用多选状态下缩放:仅未旋转的图片和形状可以在多选状态下缩放
  54. const disableResize = computed(() => {
  55. return localActiveElementList.value.some(item => {
  56. if (
  57. (item.type === 'image' || item.type === 'shape') &&
  58. !item.rotate
  59. ) return false
  60. return true
  61. })
  62. })
  63. </script>
  64. <style lang="scss" scoped>
  65. .multi-select-operate {
  66. position: absolute;
  67. top: 0;
  68. left: 0;
  69. z-index: 101;
  70. }
  71. </style>