VUE 实现划词 问AI 翻译等功能

实现原理: 通过监听鼠标 mouseup mousedown等事件 定位选中的词语 然后计算浮窗位置

javascript 复制代码
    handleMouseUp(e) {
      // 排除拖动图标、no-word-select类的元素
      if (e.target.closest('.drag-icon') || e.target.closest(".no-word-select")) return;

      let selectedText = '';
      let positionData = null; // 存储定位所需的数据(Range或鼠标坐标+元素)
      const target = e.target;
      const targetTag = target.tagName;

      // 处理textarea/input的选中文本
      if (targetTag === 'TEXTAREA' || (targetTag === 'INPUT' && target.type === 'text')) {
        const el = target;
        const start = el.selectionStart;
        const end = el.selectionEnd;
        if (start < end) {
          selectedText = el.value.substring(start, end).trim();
          // 存储鼠标坐标和元素本身(用于输入框定位)
          positionData = {
            type: 'input',
            clientX: e.clientX,
            clientY: e.clientY,
            element: el
          };
        }
      } else {
        // 普通元素的选中文本
        const selection = window.getSelection();
        selectedText = selection.toString().trim();
        if (selectedText) {
          positionData = {
            type: 'normal',
            range: selection.getRangeAt(0)
          };
        }
      }

      // 赋值选中文本
      this.selectedText = selectedText;

      // 有选中文本且有定位数据时,显示浮窗并计算位置
      if (this.selectedText && positionData) {
        this.calculatePosition(positionData);
        this.visible = true;
      } else {
        // 无选中文本时隐藏浮窗
        this.visible = false;
        this.explainVisible = false;
      }
    },
    // 计算浮窗位置
    calculatePosition(positionData) {
      const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
      const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
      const floatWidth = 240;
      const floatHeight = 34;

      if (positionData.type === 'input') {
        // 输入框的定位逻辑:基于鼠标松开的坐标
        const { clientX, clientY, element } = positionData;
        // 浮窗位置:鼠标位置下方8px,水平居中于鼠标位置
        this.top = clientY + scrollTop + 8;
        this.left = clientX + scrollLeft - floatWidth / 2;

        // 额外处理:防止浮窗超出输入框的右侧/左侧
        const elRect = element.getBoundingClientRect();
        const elRight = elRect.right + scrollLeft;
        const elLeft = elRect.left + scrollLeft;
        // 浮窗右边界超出输入框右边界时,左移
        if (this.left + floatWidth > elRight) {
          this.left = elRight - floatWidth - 8;
        }
        // 浮窗左边界超出输入框左边界时,右移
        if (this.left < elLeft) {
          this.left = elLeft + 8;
        }
      } else {
        // 普通元素的定位逻辑:基于Range的坐标
        const rect = positionData.range.getBoundingClientRect();
        this.top = rect.bottom + scrollTop + 8;
        this.left = rect.left + scrollLeft + (rect.width - floatWidth) / 2;
      }

      // 全局边界处理:防止浮窗超出屏幕
      const screenWidth = document.documentElement.clientWidth;
      const screenHeight = document.documentElement.clientHeight;

      if (this.left + floatWidth > screenWidth) this.left = screenWidth - floatWidth - 8;
      if (this.left < 0) this.left = 8;
      if (this.top + floatHeight > screenHeight) this.top = this.top - floatHeight - 16; // 向上偏移
    },

获取到所选词语后,调用相应的大模型,我这边用的是Dify的API,另外一个文章有写实现方法

相关推荐
无巧不成书02181 小时前
Windows PowerShell执行策略详解:从npm报错到完美解决
前端·windows·npm·powershell执行策略·执行策略·npm.ps1·脚本报错
Z兽兽8 小时前
React@18+Vite项目配置env文件
前端·react.js·前端框架
SuniaWang8 小时前
《Spring AI + 大模型全栈实战》学习手册系列 · 专题六:《Vue3 前端开发实战:打造企业级 RAG 问答界面》
java·前端·人工智能·spring boot·后端·spring·架构
A_nanda9 小时前
根据AI提示排查vue前端项目
前端·javascript·vue.js
happymaker06269 小时前
web前端学习日记——DAY05(定位、浮动、视频音频播放)
前端·学习·音视频
~无忧花开~9 小时前
React状态管理完全指南
开发语言·前端·javascript·react.js·前端框架
LegendNoTitle10 小时前
计算机三级等级考试 网络技术 选择题考点详细梳理
服务器·前端·经验分享·笔记·php
@大迁世界10 小时前
1.什么是 ReactJS?
前端·javascript·react.js·前端框架·ecmascript
BJ-Giser10 小时前
Cesium 基于EZ-Tree的植被效果
前端·可视化·cesium
王码码203511 小时前
Flutter for OpenHarmony:Flutter 三方库 algoliasearch 毫秒级云端搜索体验(云原生搜索引擎)
android·前端·git·flutter·搜索引擎·云原生·harmonyos