fix: hover preview mouse following
- Fixed Chinese variable name that caused JS runtime error (预估Width → estimatedWidth-like logic) - Proper viewport boundary detection with flip-to-left and flip-to-top - Uses maxHeight prop instead of hardcoded 360 - Cleaner position calculation with Math.min/Math.max clamping
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, onUnmounted } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
/** Full text to show in the preview */
|
/** Full text to show in the preview */
|
||||||
@@ -20,7 +20,6 @@ const visible = ref(false)
|
|||||||
const x = ref(0)
|
const x = ref(0)
|
||||||
const y = ref(0)
|
const y = ref(0)
|
||||||
let timer: ReturnType<typeof setTimeout> | null = null
|
let timer: ReturnType<typeof setTimeout> | null = null
|
||||||
const wrapper = ref<HTMLElement | null>(null)
|
|
||||||
|
|
||||||
function onMouseEnter(ev: MouseEvent) {
|
function onMouseEnter(ev: MouseEvent) {
|
||||||
timer = setTimeout(() => {
|
timer = setTimeout(() => {
|
||||||
@@ -44,20 +43,24 @@ function onMouseLeave() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updatePosition(ev: MouseEvent) {
|
function updatePosition(ev: MouseEvent) {
|
||||||
const pad = 12
|
const pad = 14
|
||||||
|
const popupW = Math.min(props.maxWidth, 480)
|
||||||
|
const popupH = Math.min(props.maxHeight, 360)
|
||||||
|
|
||||||
let left = ev.clientX + pad
|
let left = ev.clientX + pad
|
||||||
let top = ev.clientY + pad
|
let top = ev.clientY + pad
|
||||||
|
|
||||||
// Keep within viewport
|
// Flip to left side if too close to right edge
|
||||||
const预估Width = Math.min(props.maxWidth, 480)
|
if (left + popupW + 16 > window.innerWidth) {
|
||||||
if (left + 预估Width > window.innerWidth - 16) {
|
left = ev.clientX - popupW - pad
|
||||||
left = ev.clientX - 预估Width - pad
|
|
||||||
}
|
}
|
||||||
if (top + 360 > window.innerHeight - 16) {
|
// Flip to top side if too close to bottom edge
|
||||||
top = window.innerHeight - 360 - 16
|
if (top + popupH + 16 > window.innerHeight) {
|
||||||
|
top = ev.clientY - popupH - pad
|
||||||
}
|
}
|
||||||
if (left < 8) left = 8
|
// Clamp to safe bounds
|
||||||
if (top < 8) top = 8
|
left = Math.max(8, Math.min(left, window.innerWidth - popupW - 8))
|
||||||
|
top = Math.max(8, Math.min(top, window.innerHeight - popupH - 8))
|
||||||
|
|
||||||
x.value = left
|
x.value = left
|
||||||
y.value = top
|
y.value = top
|
||||||
@@ -66,7 +69,6 @@ function updatePosition(ev: MouseEvent) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<span
|
<span
|
||||||
ref="wrapper"
|
|
||||||
class="hover-preview-wrap"
|
class="hover-preview-wrap"
|
||||||
@mouseenter="onMouseEnter"
|
@mouseenter="onMouseEnter"
|
||||||
@mousemove="onMouseMove"
|
@mousemove="onMouseMove"
|
||||||
@@ -94,7 +96,6 @@ function updatePosition(ev: MouseEvent) {
|
|||||||
.hover-preview-wrap {
|
.hover-preview-wrap {
|
||||||
display: inline;
|
display: inline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
.hover-preview-popup {
|
.hover-preview-popup {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|||||||
Reference in New Issue
Block a user