【react + setSelectionRange】虛擬數字鍵盤(純潔版)


先上dj(效果)! 先上dj(效果)!

 

 

 技術:react --ref  --父子組件通信  光標事件 字符串方法 

兼容:基於Mozilla的瀏覽器不支持setSelectionRange

注意事項:瀏覽器默認行為  冒泡 (整個鍵盤區域有一個click顯示鍵盤,單個數字鍵另外事件,點擊某個位置時(隱藏鍵盤) 阻止一下冒泡  避免出現冒泡至最外層,導致無法關閉)

光標事件:

//Selection對象表示用戶選擇的文本范圍或插入符號的當前位置。
  要獲取用於檢查或修改的Selection對象,請使用window.getSelection()
// selectionSatrt記錄鼠標點擊的開始位置,selectionEnd記錄結束位置
 主要思路:點擊輸入框彈出虛擬鍵盤,點擊鍵盤某個數字,拿到該值的描述,對input框進行賦值;復雜場景,當點擊了1245,想在2和4之間插一個3,這個時候,鼠標按下時
   記錄下光標的位置(這里需要注意的是瀏覽器默認行為是fouce,本人這里使用的是click事件,為了實現非阻塞,需要在瀏覽器默認行為foucs之后執行,這里用到了setTimeout 0 ),
   對input框的賦值操作---實質是對字符串進行插入或者刪除的動作,點擊鍵盤刪除,需要更新光標的位置,再進行字符串的操作。
其他就是一些 比較常規的交互處理了 如點擊鍵盤區域外關閉鍵盤 點擊時高亮 等...
場景:針對不同人群的使用習慣 是否使用虛擬數字鍵盤(例:鼠標點擊輸入框彈出數字鍵盤)
參數說明:
 integer:是否只顯示整型 (小鍵盤不帶小數點.) true fasle  默認false 顯示小數點
 方法說明:
 1.showCheckBoard 展示鍵盤 --- 接收兩個參數 e Id(input框的Id 用於給form表單賦值)例 this.onBoardRefChild.showCheckBoard(e,Id) 必須接收子組件參數event 
 2.setCaret 獲取實時光標動態--- 例 this.onBoardRefChild.setCaret(dom) setCaret 必須接收子組件參數 input dom結構 (例:document.getElementById("xxx"))
 3.setValue 顯示值設置---設置最新修改的值(插入的小鍵盤數字或者刪除后)
 注意: 
   1.該組件需要和input框一起使用,作為input的同級元素存在 外層需要有一個共同的父元素包裹 
     父級元素設置相對定位 relative (便於小鍵盤的彈出定位) 
     包裹的區域為可視區域  區域外點擊會關閉小鍵盤
   2.input 必須設置一個id 例如 <Input id="inputNode" /> 用於方法函數進行元素查找和光標定位   form表單中的input id為 getFieldDecorator 設置的名字
*/
 //添加點擊事件 點擊鍵盤外的區域 關閉鍵盤
componentDidMount() {
        document.addEventListener('click', this.hideKeyBoard);
    }
 
//隱藏鍵盤
    hideKeyBoard = () => {
        this.setState({
            showkey: false,
            Id: "",
        })
    }
    //展示鍵盤 
    showCheckBoard = (e) => {
        this.stopPropagation(e);
        this.setState({
            showkey: true,
        })
    }
    //阻止冒泡事件
    stopPropagation(e) {
        if (e && e.nativeEvent) {
            e.nativeEvent.stopImmediatePropagation();
        }
    }
    //獲取實時光標動態
    setCaret = (dom) => {
        this.setState({
            dom,
        })
        // console.log("document.getElementById(InputId)",dom)
        // let obj =  document.getElementById("tagsInputs")
        if (dom.createTextRange && dom.createTextRange) {
            dom.caretPos = document.selection.createRange().duplicate();
        }
    }
    //插入 / 刪除 內容
    insertAtCaret = (textObj, textFeildValue,) => {
        //  console.log("textObj",textObj)
        if (document.all) {
            if (textObj.createTextRange && textObj.caretPos) {
                var caretPos = textObj.caretPos;
                caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == '   ' ? textFeildValue + '   ' : textFeildValue;
            } else {
                textObj.value = textFeildValue;
            }
        } else {
            //Selection對象表示用戶選擇的文本范圍或插入符號的當前位置。要獲取用於檢查或修改的Selection對象,請使用window.getSelection()
            // selectionSatrt記錄鼠標點擊的開始位置,selectionEnd記錄結束位置
            if (textObj.setSelectionRange) {
                var rangeStart = textObj.selectionStart;
                var rangeEnd = textObj.selectionEnd;
                var newLocation = textObj.selectionStart + textFeildValue.length
                var tempStr1 = textObj.value.substring(0, rangeStart);
                var tempStr2 = textObj.value.substring(rangeEnd);
                textObj.value = tempStr1 + (textFeildValue != "c" ? textFeildValue : "") + tempStr2; //將左邊、插入值、右邊拼接在一起
                textObj.focus()
                if (textFeildValue == "c") {//刪除退格操作  slice
                    this.setState({
                        InputValue: ((tempStr1).slice(0, rangeEnd - 1)) + tempStr2
                    }, () => {
                        this.props.setValue(this.state.InputValue, textObj.id)
                    })
                    //在瀏覽器默認行為foucs之后執行,實現非阻塞 
                    setTimeout(() => {
                        textObj.setSelectionRange(rangeStart - 1, rangeStart - 1);
                        // textObj.selectionStart = (rangeStart-1)<0?0:rangeStart-1// 更新光標位置,將之前算的新位置給輸入框光標
                    }, 0)
                } else {
                    textObj.setSelectionRange(newLocation, newLocation);
                    this.setState({
                        InputValue: tempStr1 + textFeildValue + tempStr2
                    }, () => {
                        this.props.setValue(this.state.InputValue, textObj.id)
                    })
                }
            } else {
                console.log("This version of Mozilla based browser does not support setSelectionRange / 此版本的基於Mozilla的瀏覽器不支持setSelectionRange");
            }
        }
    }
    //點擊特定內容(鍵盤)
    handleClick = (e, item) => {
        //點擊ok關閉鍵盤
        if(item.id=="ok"){
            this.hideKeyBoard()
            //阻止冒泡到最外層顯示鍵盤的按鈕事件handleCheckBoard
            e.stopPropagation()
        }else{
             this.insertAtCaret(this.state.dom, item.id,)
        }
    }
    //點擊內容(鍵盤)
    handleCheckBoard = (e) => {
        this.showCheckBoard(e)
    }
    //高亮點擊內容
    handleItemMousedown = (item) => {
        var x = document.querySelectorAll(".number-item");
        x[item.seq].style.background = '#bfbfbf';
    }
    //還原點擊內容
    handleItemMouseUp = (item) => {
        var x = document.querySelectorAll(".number-item");
        x[item.seq].style.background = '#7d7876';
    }
  render() {
        const numberArr = [{
            descriptsSPCode: "07",
            descripts: "7",
            id: "7",
            descriptsEN: "seven",
            seq: "0"
        }, {
            descriptsSPCode: "08",
            descripts: "8",
            id: "8",
            descriptsEN: "eight",
            seq: "1"
        }, {
            descriptsSPCode: "09",
            descripts: "9",
            id: "9",
            descriptsEN: "nine",
            seq: "2"
        }, {
            descriptsSPCode: "04",
            descripts: "4",
            id: "4",
            descriptsEN: "four",
            seq: "3"
        }, {
            descriptsSPCode: "05",
            descripts: "5",
            id: "5",
            descriptsEN: "five",
            seq: "4"
        }, {
            descriptsSPCode: "06",
            descripts: "6",
            id: "6",
            descriptsEN: "six",
            seq: "5"
        },
        {
            descriptsSPCode: "01",
            descripts: "1",
            id: "1",
            descriptsEN: "one",
            seq: "6"
        }, {
            descriptsSPCode: "02",
            descripts: "2",
            id: "2",
            descriptsEN: "two",
            seq: "7"
        }, {
            descriptsSPCode: "03",
            descripts: "3",
            id: "3",
            descriptsEN: "three",
            seq: "8"
        }, {
            descriptsSPCode: "0",
            descripts: "0",
            id: "0",
            descriptsEN: "ten",
            seq: "9"
        }, {
            descriptsSPCode: "01",
            descripts: ".",
            id: ".",
            descriptsEN: "spot",
            seq: "10"
        }, {
            descriptsSPCode: "ok",
            descripts: "ok",
            id: "ok",
            descriptsEN: "good",
            seq: "11"
        },
        {
            descriptsSPCode: "c",
            descripts: "←",
            id: "c",
            descriptsEN: "reset",
            seq: "12"
        },
        ]
        let numberBlock = numberArr && numberArr.map((item, i) => {
            return (
                <button
                    className="number-item"
                    style={{
                        WebkitUserSelect: "none",
                        userSelect: "none",
                        width: item.descripts == "0" && this.props.integer && this.props.integer ? "228px" : item.descripts == "0" ? "144px" : "60px",
                        height: item.id == "c" ? "203px" : "60px",
                        display: this.props.integer && this.props.integer && item.seq == "10" ? "none" : "inline-block",
                        textAlign: item.descripts == "0" && !this.props.integer ? "left" : "center",
                        paddingLeft: item.descripts == "0" && !this.props.integer ? "22px" : "0",
                        paddingRight: "0",
                        border: "0",
                        lineHeight: item.id == "c" ? "203px" : "60px",
                        borderRadius: item.id == "c" ? "0 6px 6px 0" : "4px",
                        position: item.id == "c" ? "absolute" : "static",
                        top: item.id == "c" ? "0px" : "0",
                        right: item.id == "c" ? "-8px" : "0",
                        background: "#7d7876",
                        color: "#ffffff",
                        cursor: "pointer",
                        margin: item.descriptsSPCode == "ok" ? "6px 4px" : "6px 12px",
                        fontSize: "30px",
                    }}
                    onClick={(e) => this.handleClick(e, item)}
                    onMouseDown={() => this.handleItemMousedown(item)}
                    onMouseUp={() => this.handleItemMouseUp(item)}
                >
                    {item.descripts}
                </button>
            )
        })
        return (
            <div>
                <div id="tags" onClick={(e) => this.handleCheckBoard(e,)} style={{
                    display: this.state.showkey ? "block" : "none", position: "absolute", zIndex: "1",
                    width: "320px", background: "rgba(0, 0, 0, 0.65)", borderRadius: "6px", textAlign: 'left'
                }}>
                    {numberBlock}
                </div>
            </div>
        );
    }

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM