Browse Source

add: 文本悬浮框完善定位

wzl 8 months ago
parent
commit
f9784564f1

File diff suppressed because it is too large
+ 5 - 0
packages/webview/src/components/Icon/SquiggleGray.vue


+ 15 - 1
packages/webview/src/components/Popups/Popup.vue

@@ -1,11 +1,25 @@
 <template>
-  <div class="popup">
+  <div class="popup" ref="popupRef">
     <slot />
   </div>
 </template>
 
 <script setup>
+import { ref, onMounted } from 'vue'
 
+const popupRef = ref()
+const width = ref(0)
+const height = ref(0)
+
+onMounted(() => {
+  width.value = popupRef.value.offsetWidth
+  height.value = popupRef.value.offsetHeight
+})
+
+defineExpose({
+  width,
+  height
+})
 </script>
 
 <style lang="scss">

+ 44 - 8
packages/webview/src/components/Popups/TextPopup.vue

@@ -1,19 +1,19 @@
 <template>
-  <Popup class="text-popup" v-if="showPopup && textPopup.length" :style="{ top: `${top}px`, left: `${left}px` }">
+  <Popup class="text-popup" :class="{ 'transform': isTranslateX }" ref="textPopupRef" v-if="showPopup && textPopup.length" :style="{ top: `${top}px`, left: `${left}px` }">
     <template v-for="(item, index) in textPopup" :key="`${item.dataElement}-${index}`">
       <CustomButton v-if="item.name === 'customButton'" :item="item" :data-element="item.dataElement" />
       <Button v-else-if="item.type === 'copy'" @click="handleTextPopup('copy')" :title="$t('documentEditor.copy')" :data-element="item.dataElement"><CopyText /></Button>
       <Button v-else-if="item.type === 'highlight'" @click="handleTextPopup('highlight')" :title="$t('header.highlight')" :data-element="item.dataElement"><HightlightGray /></Button>
       <Button v-else-if="item.type === 'underline'" @click="handleTextPopup('underline')" :title="$t('header.underline')" :data-element="item.dataElement"><UnderlineGray /></Button>
       <Button v-else-if="item.type === 'strikeout'" @click="handleTextPopup('strikeout')" :title="$t('header.strikeout')" :data-element="item.dataElement"><StrikeoutGray /></Button>
-      <Button v-else-if="item.type === 'squiggly'" @click="handleTextPopup('squiggly')" :title="$t('header.squiggly')" :data-element="item.dataElement"><Squiggle /></Button>
+      <Button v-else-if="item.type === 'squiggly'" @click="handleTextPopup('squiggly')" :title="$t('header.squiggly')" :data-element="item.dataElement"><SquiggleGray /></Button>
       <div v-else-if="['spacer', 'divider'].includes(item.type)" :class="item.type"></div>
     </template>
   </Popup>
 </template>
 
 <script setup>
-import { ref, onMounted, onUnmounted, computed } from 'vue'
+import { ref, onMounted, onUnmounted, computed, nextTick } from 'vue'
 import core from '@/core'
 import { useViewerStore } from '@/stores/modules/viewer'
 import { useDocumentStore } from '@/stores/modules/document'
@@ -26,6 +26,8 @@ const textPopup = computed(() => useViewer.getPopupItems('textPopup'))
 const showPopup = ref(false)
 const top = ref(0)
 const left = ref(0)
+const textPopupRef = ref(null)
+const isTranslateX = ref(true)
 
 let documentContainer
 
@@ -38,14 +40,44 @@ const handleTextPopup = (tool) => {
   core.handleTextPopup(data)
 }
 
-const updatePopupPosition = (data) => {
+const updatePopupPosition = async (data) => {
   const { show, rect } = data
 
   showPopup.value = show
+  await nextTick()
 
-  if (rect) {
-    top.value = rect.bottom
-    left.value = rect.left + (rect.right - rect.left) / 2
+  if (rect && showPopup.value) {
+    const popup = textPopupRef.value
+    if (!popup) return
+
+    // 计算弹窗的初始位置
+    let initialLeft = rect.left + (rect.right - rect.left) / 2
+    let initialTop = rect.bottom
+
+    const popupWidth = popup.width
+    const popupHeight = popup.height + 10
+
+    const windowWidth = window.innerWidth
+    const windowHeight = window.innerHeight
+
+    isTranslateX.value = true
+
+    // 检查水平位置
+    if (initialLeft - popupWidth / 2 < 0) {
+      initialLeft = 0
+      isTranslateX.value = false
+    } else if (initialLeft + popupWidth / 2 > windowWidth) {
+      initialLeft = windowWidth - popupWidth
+      isTranslateX.value = false
+    }
+
+    // 检查垂直位置
+    if (initialTop + popupHeight > windowHeight) {
+      initialTop = Math.max(0, rect.top - popupHeight)
+    }
+
+    top.value = initialTop
+    left.value = initialLeft
   }
 }
 core.addEvent('showTextPopup', updatePopupPosition)
@@ -66,7 +98,11 @@ onUnmounted(() => {
 
 <style lang="scss">
 .text-popup {
-  transform: translateX(-50%) translateY(5px);
+  transform: translateY(5px);
+
+  &.transform {
+    transform: translateX(-50%) translateY(5px);
+  }
 
   .button:last-child {
     margin-right: 0