Vue 自定义指令实现文本溢出省略与鼠标交互滚动效果

225 阅读1分钟

最终效果

  • ✨内容溢出显示省略号
  • ✨鼠标进入时,滚动显示剩余内容
  • ✨鼠标移出时,恢复到开头位置
  • ✨支持响应式更新内容

20250218103551_rec_.gif

开始造轮子

自定义指令

新建文件 src/directives/textEllipsis.ts

import { gsap } from 'gsap';
import { ObjectDirective } from 'vue';

/**
 * 自定义指令:v-text-ellipsis
 * @description 给元素添加文本溢出显示省略号,鼠标移入时内容滚动的效果
 */
const textEllipsis: ObjectDirective<HTMLElement, never> = {
    beforeMount(el) {
        // 设置溢出省略
        el.style.overflow = 'hidden';
        el.style.textOverflow = 'ellipsis';
        el.style.textWrap = 'nowrap';

        // 动画实例
        let scrollAnimation: gsap.core.Tween | undefined;

        // 鼠标移入效果
        el.addEventListener('mouseenter', () => {
            // 停止当前动画
            scrollAnimation?.kill();

            // 隐藏内容溢出的省略号
            el.style.textOverflow = 'unset';

            const SCROLL_SPEED = 60;
            const maxScrollWidth = el.scrollWidth;
            const duration = maxScrollWidth / SCROLL_SPEED;

            // 滚动显示更多内容
            scrollAnimation = gsap.to(el, { scrollLeft: maxScrollWidth, duration: duration });
        });

        // 鼠标移出效果
        el.addEventListener('mouseleave', () => {
            // 停止当前动画
            scrollAnimation?.kill();

            // 把内容滚动到开始的位置
            scrollAnimation = gsap.to(el, {
                scrollLeft: 0,
                duration: 0.15,
                onComplete() {
                    // 动画结束重新显示省略号
                    el.style.textOverflow = 'ellipsis';
                },
            });
        });
    },
};

export default textEllipsis;

注册指令

src/main.ts 中添加

import textEllipsis from './directives/textEllipsis';

app.directive('text-ellipsis', textEllipsis);

扩展 Vue 的类型定义

src/types/vue-shim.d.ts 中添加

import "vue";
import textEllipsis from "../directives/textEllipsis";

declare module "@vue/runtime-core" {
    export interface ComponentCustomProperties {
        /**
         * 自定义指令:v-text-ellipsis
         * @description 给元素添加文本溢出显示省略号,鼠标移入时内容滚动的效果
         */
        vTextEllipsis: typeof textEllipsis;
    }
}

使用自定义指令

<p v-text-ellipsis>{{ textContent }}</p>

最终效果