文本选择
- vx-hookhttps://www.npmjs.com/package/vx-hook vue 3.0 hook 库
- getSelection 文本选择
Uesage
代码语言:javascript复制<template>
<div id="app">
{{ state }}
<div ref='ele'> 测试文本 </div>
</div>
</template>
<script>
import { useTextSelection } from 'vx-hook'
export default {
name: 'App',
setup(){
const [ state, ele ] = useTextSelection()
return {
state,
ele
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Params
- initDom 文本选择事件绑定元素 ref
Result
- state
- text 被选中文本 string
- width 选中宽度 number | NaN
- height 选中高度 number | NaN
- top 选择框 顶部坐标 number | NaN
- bottom 选择框 底部坐标 number | NaN
- left 选择框 左侧坐标 number | NaN
- right 选择框 右侧坐标 number | NaN
- element 绑定元素
实现
代码语言:javascript复制import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
const initRect = {
top: NaN,
left: NaN,
bottom: NaN,
right: NaN,
height: NaN,
width: NaN,
}
const initState = {
text: '',
...initRect
}
function getInitState(){
return { ...initState }
}
// 获取选择文本及坐标
function getRectFromSelection(){
const selection = window.getSelection()
const text = selection.toString()
if(selection.rangeCount < 1){ return initRect }
const range = selection.getRangeAt(0);
const {
height,
width,
top,
left,
right,
bottom
} = range.getBoundingClientRect()
return {
text,
height,
width,
top,
left,
right,
bottom
}
}
const createOnMouseupHandler = state => () => {
if (!window.getSelection) return;
const data = getRectFromSelection()
if(data.text){
state.value = data
}
}
const createOnmousedownHandler = state => () => {
if (!window.getSelection) return;
if(state.value.text){
state.value = getInitState()
}
window.getSelection().removeAllRanges()
}
/**
* 文本选择
* @param { element } intiDom 绑定元素
* @returns { array }
* - state
* - text 被选中文本
* - width 选中宽度
* - height 选中高度
* - top 选择框 顶部坐标
* - bottom 选择框 底部坐标
* - left 选择框 左侧坐标
* - right 选择框 右侧坐标
* - element 绑定元素
*/
export default function useTextSelection(intiDom){
const element = ref(null)
const target = computed(() => intiDom&&intiDom.value ? intiDom : element.value )
const state = ref(getInitState())
const onMouseupHandler = createOnMouseupHandler(state)
const onMousedownHandler = createOnmousedownHandler(state)
watch(() => target.value, (ele, oldEle) =>{
if(oldEle){
oldEle.removeEventListener('mouseup', onMouseupHandler)
oldEle.removeEventListener('mousedown', onMousedownHandler)
}
if(ele){
ele.addEventListener('mouseup', onMouseupHandler)
ele.addEventListener('mousedown', onMousedownHandler)
}
})
onMounted(() => {
document.addEventListener('mousedown', onMousedownHandler)
})
onUnmounted(() =>{
document.removeEventListener('mousedown', onMousedownHandler)
})
return [ state, element ]
}