BaseTextElement.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <template>
  2. <div
  3. class="base-element-text"
  4. :style="{
  5. top: elementInfo.top + 'px',
  6. left: elementInfo.left + 'px',
  7. width: elementInfo.width + 'px',
  8. height: elementInfo.height + 'px',
  9. }"
  10. >
  11. <div
  12. class="rotate-wrapper"
  13. :style="{ transform: `rotate(${elementInfo.rotate}deg)` }"
  14. >
  15. <div
  16. class="element-content"
  17. :style="{
  18. width: elementInfo.vertical ? 'auto' : elementInfo.width + 'px',
  19. height: elementInfo.vertical ? elementInfo.height + 'px' : elementInfo.height + 'px',
  20. backgroundColor: elementInfo.fill,
  21. opacity: elementInfo.opacity,
  22. textShadow: shadowStyle,
  23. lineHeight: elementInfo.lineHeight,
  24. letterSpacing: (elementInfo.wordSpace || 0) + 'px',
  25. color: elementInfo.defaultColor,
  26. fontFamily: elementInfo.defaultFontName,
  27. writingMode: elementInfo.vertical ? 'vertical-rl' : 'horizontal-tb',
  28. display: 'flex',
  29. alignItems: 'center',
  30. overflow: hidden,
  31. }"
  32. >
  33. <div class="shape-text" :style="elementInfo.style" :class="[elementInfo.align, { 'editable': editable || elementInfo.content }]">
  34. <ElementOutline
  35. :width="elementInfo.width"
  36. :height="elementInfo.height"
  37. :outline="elementInfo.outline"
  38. />
  39. <div
  40. class="text ProseMirror-static"
  41. :class="{ 'thumbnail': target === 'thumbnail' }"
  42. :style="{
  43. '--paragraphSpace': `${elementInfo.paragraphSpace === undefined ? 5 : elementInfo.paragraphSpace}px`,
  44. }"
  45. v-html="elementInfo.content"
  46. ></div>
  47. </div>
  48. </div>
  49. </div>
  50. </div>
  51. </template>
  52. <script lang="ts" setup>
  53. import { computed } from 'vue'
  54. import type { PPTTextElement } from '@/types/slides'
  55. import ElementOutline from '@/views/components/element/ElementOutline.vue'
  56. import useElementShadow from '@/views/components/element/hooks/useElementShadow'
  57. const props = defineProps<{
  58. elementInfo: PPTTextElement
  59. target?: string
  60. }>()
  61. const shadow = computed(() => props.elementInfo.shadow)
  62. const { shadowStyle } = useElementShadow(shadow)
  63. </script>
  64. <style lang="scss" scoped>
  65. .base-element-text {
  66. position: absolute;
  67. }
  68. .rotate-wrapper {
  69. width: 100%;
  70. height: 100%;
  71. }
  72. .element-content {
  73. position: relative;
  74. padding: 10px;
  75. line-height: 1.5;
  76. word-break: break-word;
  77. font-family: Kaiti, "Kaiti SC", "Kaiti TC", Roboto, "Noto Sans SC", "Noto Sans TC", "Noto Sans KR", "Noto Sans JP", "Roboto", Roboto, "Noto Sans SC", "Noto Sans TC", "Noto Sans KR", "Noto Sans JP";
  78. .text {
  79. position: relative;
  80. &.thumbnail {
  81. pointer-events: none;
  82. }
  83. }
  84. }
  85. .shape-text {
  86. width:100%;
  87. height:100%;
  88. position: absolute;
  89. top: 0;
  90. bottom: 0;
  91. left: 0;
  92. right: 0;
  93. display: flex;
  94. flex-direction: column;
  95. word-break: break-word;
  96. pointer-events: none;
  97. white-space: pre;
  98. &.editable {
  99. pointer-events: all;
  100. }
  101. &.top {
  102. justify-content: flex-start;
  103. }
  104. &.middle {
  105. justify-content: center;
  106. left: 50%;
  107. top: 50%;
  108. -webkit-transform: translate(-50%,-50%);
  109. transform: translate(-50%,-50%);
  110. }
  111. &.bottom {
  112. justify-content: flex-end;
  113. }
  114. }
  115. </style>