BaseImageElement.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <template>
  2. <div
  3. class="base-element-image"
  4. :style="{
  5. top: elementInfo.top + 'px',
  6. left: elementInfo.left + 'px',
  7. width: elementInfo.width + 'px',
  8. height: elementInfo.height + 'px',
  9. transform: `rotate(${elementInfo.rotate}deg)`,
  10. }"
  11. >
  12. <div
  13. class="element-content"
  14. :style="{
  15. filter: shadowStyle ? `drop-shadow(${shadowStyle})` : '',
  16. transform: flip,
  17. }"
  18. >
  19. <ImageRectOutline
  20. v-if="clipShape.type === 'rect'"
  21. :width="elementInfo.width"
  22. :height="elementInfo.height"
  23. :radius="clipShape.radius"
  24. :outline="elementInfo.outline"
  25. />
  26. <ImageEllipseOutline
  27. v-else-if="clipShape.type === 'ellipse'"
  28. :width="elementInfo.width"
  29. :height="elementInfo.height"
  30. :outline="elementInfo.outline"
  31. />
  32. <ImagePolygonOutline
  33. v-else-if="clipShape.type === 'polygon'"
  34. :width="elementInfo.width"
  35. :height="elementInfo.height"
  36. :createPath="clipShape.createPath"
  37. :outline="elementInfo.outline"
  38. />
  39. <div class="image-content" :style="{ clipPath: clipShape.style }">
  40. <img
  41. :src="elementInfo.src"
  42. :draggable="false"
  43. :style="{
  44. top: imgPosition.top,
  45. left: imgPosition.left,
  46. width: imgPosition.width,
  47. height: imgPosition.height,
  48. filter: filter,
  49. }"
  50. alt=""
  51. />
  52. </div>
  53. </div>
  54. </div>
  55. </template>
  56. <script lang="ts">
  57. import { computed, defineComponent, PropType } from 'vue'
  58. import { PPTImageElement } from '@/types/slides'
  59. import { CLIPPATHS, ClipPathTypes } from '@/configs/imageClip'
  60. import ImageRectOutline from './ImageRectOutline.vue'
  61. import ImageEllipseOutline from './ImageEllipseOutline.vue'
  62. import ImagePolygonOutline from './ImagePolygonOutline.vue'
  63. import useElementShadow from '@/views/_common/_element/hooks/useElementShadow'
  64. export default defineComponent({
  65. name: 'base-element-image',
  66. components: {
  67. ImageRectOutline,
  68. ImageEllipseOutline,
  69. ImagePolygonOutline,
  70. },
  71. props: {
  72. elementInfo: {
  73. type: Object as PropType<PPTImageElement>,
  74. required: true,
  75. },
  76. },
  77. setup(props) {
  78. const imgPosition = computed(() => {
  79. if(!props.elementInfo || !props.elementInfo.clip) {
  80. return {
  81. top: '0',
  82. left: '0',
  83. width: '100%',
  84. height: '100%',
  85. }
  86. }
  87. const [start, end] = props.elementInfo.clip.range
  88. const widthScale = (end[0] - start[0]) / 100
  89. const heightScale = (end[1] - start[1]) / 100
  90. const left = start[0] / widthScale
  91. const top = start[1] / heightScale
  92. return {
  93. left: -left + '%',
  94. top: -top + '%',
  95. width: 100 / widthScale + '%',
  96. height: 100 / heightScale + '%',
  97. }
  98. })
  99. const clipShape = computed(() => {
  100. if(!props.elementInfo || !props.elementInfo.clip) return CLIPPATHS.rect
  101. const shape = props.elementInfo.clip.shape || ClipPathTypes.RECT
  102. return CLIPPATHS[shape]
  103. })
  104. const filter = computed(() => {
  105. if(!props.elementInfo.filters) return ''
  106. let filter = ''
  107. for(const key of Object.keys(props.elementInfo.filters)) {
  108. filter += `${key}(${props.elementInfo.filters[key]}) `
  109. }
  110. return filter
  111. })
  112. const flip = computed(() => {
  113. if(!props.elementInfo.flip) return ''
  114. const { x, y } = props.elementInfo.flip
  115. if(x && y) return `rotateX(${x}deg) rotateY(${y}deg)`
  116. else if(x) return `rotateX(${x}deg)`
  117. else if(y) return `rotateY(${y}deg)`
  118. return ''
  119. })
  120. const shadow = computed(() => props.elementInfo.shadow)
  121. const { shadowStyle } = useElementShadow(shadow)
  122. return {
  123. imgPosition,
  124. clipShape,
  125. filter,
  126. flip,
  127. shadowStyle,
  128. }
  129. },
  130. })
  131. </script>
  132. <style lang="scss" scoped>
  133. .base-element-image {
  134. position: absolute;
  135. }
  136. .element-content {
  137. width: 100%;
  138. height: 100%;
  139. position: relative;
  140. .image-content {
  141. width: 100%;
  142. height: 100%;
  143. overflow: hidden;
  144. position: relative;
  145. }
  146. img {
  147. position: absolute;
  148. }
  149. }
  150. </style>