useTextSelection vue 文本选择hook

2020-05-09 16:33:19 浏览数 (1)

文本选择

  • 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 ]
    
}

0 人点赞