前言
最近开发了一个很有意思的需求,鼠标选中文字,然后出现一个按钮,点击按钮完成对应的功能,跟浏览器选中文本搜索的功能类似。本身需求不复杂,但是结合其他条件就有点小麻烦,下面来看一下具体的实现过程。
浏览器选中文本
实现 选中功能效果描述就是左键选中文本,松开出现功能按钮,并且要获取到选中的文本。首先我们来实现功能按钮。 ## 功能按钮 功能按钮只有在选中文本后出现,我们可以通过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去控制按钮的显示隐藏,一来按钮操作会相对频繁,二来方便我们接下来的优化。
需求优化
到此我们只要点击按钮触发功能逻辑,同时让按钮消失就算完成了该需求。但是目前触发按钮消失的方式很单一,我又研究了下浏览器的相关功能,发现以下两种也能触发按钮消失:
- 滚动条滚动。
- 鼠标移动一定距离,渐变消失。 所以为了这个需求用起来更加丝滑,我们也加上这两个功能。滚动条滚动这个非常简单,监听滚动事件,当滚动条滚动时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事件的区别,如果元素本身很简单,这个功能做起来会更加简便。