需求小能手——文字选中功能

前言

最近开发了一个很有意思的需求,鼠标选中文字,然后出现一个按钮,点击按钮完成对应的功能,跟浏览器选中文本搜索的功能类似。本身需求不复杂,但是结合其他条件就有点小麻烦,下面来看一下具体的实现过程。

浏览器选中文本

实现 选中功能效果描述就是左键选中文本,松开出现功能按钮,并且要获取到选中的文本。首先我们来实现功能按钮。 ## 功能按钮 功能按钮只有在选中文本后出现,我们可以通过css中的display属性获取v-if/show进行控制,重点是事件跟位置。 - 事件:选中文本会有松开动作,我们很容易想到用mouseup去触发。但是如果元素本身有click事件就会有问题,当鼠标松开时mouseup与click都会触发,我们是希望这两个事件互相不影响。思考了一会决定用鼠标按下松开间隔时间区分,点击一般要比选中的时间短。我们去掉click,绑定mousedown与mouseup,当鼠标按下时记录当前时间,松开时获取当前时间与之前的时间进行对比。

js 复制代码
handleMouseDown() {
// 当前时间
this.downTime = new Date().getTime()
},
handleMouseUp() {
const nowTime = new Date().getTime()
if (nowTime - this.downTime > 100) {
// mouseup逻辑
} else {
// click逻辑
}
},

判断条件的时长可以进行微调。

  • 位置:结合浏览器选中文本效果,当我们松开鼠标时,按钮就应该在鼠标附近出现,也就是说按钮的位置是相对于鼠标出现的位置,相对位置就很容易联想到absolute相对定位,所以我们将按钮position设置为absolute,接下来就是通过top、left确定按钮位置。top、left肯定是通过鼠标的位置获取的,如果我们的文本自身有div包裹,为了更加美观,我们可以获取div的宽高,然后用当前鼠标位置减去div宽、高,最后根据实际效果进行微调。通过以上分析,我们定义三个变量:
    buttonShow ------------ 控制按钮显示、隐藏
    buttonLeft/Top ------------ 控制按钮位置


getBoundingClientRect方法可以获取元素width、height、top等属性值,使用起来非常方便。我们通过style让button动态绑定这些属性。

js 复制代码
<el-button
v-show="buttonShow"
:style="{ position: 'absolute', top: buttonTop, left: buttonLeft }"
@click="handleSearch"
>搜索</el-button>

注意,这里我们用v-show去控制按钮的显示隐藏,一来按钮操作会相对频繁,二来方便我们接下来的优化。

需求优化

到此我们只要点击按钮触发功能逻辑,同时让按钮消失就算完成了该需求。但是目前触发按钮消失的方式很单一,我又研究了下浏览器的相关功能,发现以下两种也能触发按钮消失:

  1. 滚动条滚动。
  2. 鼠标移动一定距离,渐变消失。 所以为了这个需求用起来更加丝滑,我们也加上这两个功能。滚动条滚动这个非常简单,监听滚动事件,当滚动条滚动时buttonShow为false。
js 复制代码
window.addEventListener('scroll', () => {
if (this.buttonShow) {
this.buttonShow = false
}
})

重点是第二个鼠标移动一定距离渐变消失,首先我们来确认这个移动范围,该移动范围可以当作移动面积,具体的形状我们可以自定义,比如正方形、圆等。这里我们选择圆,当作范围,直接用圆的方程公式去做判断,js中通过Math.pow去表示平方。

注意坐标中的1一般情况下跟1px是对等的,都是物理像素。上面我们提到了消失是渐变消失,那么我们也给按钮消失加上渐变动画,这里我们使用vue中的Transition组件,这也是我们用v-show控制的原因。

js 复制代码
<Transition name="fade">
<el-button>...
</Transition>

注意css中的前缀跟name要匹配,最后我们通过window.getSelection().toString()拿到选中文本,执行业务逻辑。

总结

以上就是文字选中功能,重点是click与mouseup事件的区别,如果元素本身很简单,这个功能做起来会更加简便。

相关推荐
LiaCode13 小时前
别让 AI 把仓库写成“代码平行宇宙”:从 Deslop 看生成前查重
前端·后端·github
nice先生的狂想曲13 小时前
javascript高级程序设计(六)——2026.9.5
前端·javascript
光影少年13 小时前
如何做大型React+RN 项目架构设计、目录规范
前端·react native·react.js
一位正在转型AI全栈的前端工程师13 小时前
AI 全栈学习之旅 -Week 8:从单 Agent 到多 Agent 协作:LangGraph 实战与记忆持久化
前端·python
用户9210802628613 小时前
Promise 和 async/await:从用途到执行机制
前端
yyt36304584113 小时前
KLineChartQuant:GLSL 的精度问题及 RTC 解法
前端·vue.js·react.js·交互·图形渲染·webgl·数据可视化
HarmonLTS14 小时前
智盾 WAF v8.2 Ultra|下一代 Web 应用防火墙
前端
এ慕ོ冬℘゜14 小时前
前端实战:基于jQuery递归实现通用树形组织菜单(可直接复用)
前端·javascript·jquery
计算机魔术师14 小时前
英伟达据报洽谈向 Mira Murati 的 Thinking Machines Lab 投资 25 亿美元
前端
变与不变80614 小时前
js函数与封装详细解答
前端·javascript·vue.js