• 【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",
                             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",
                         "320px", background: "rgba(0, 0, 0, 0.65)", borderRadius: "6px", textAlign: 'left'
                    }}>
                        {numberBlock}
                    </div>
                </div>
            );
        }
    

      

  • 相关阅读:
    Kafka笔记—可靠性、幂等性和事务
    简易 bokeh 图像散景效果算法实现
    unisound_asr 云知声 语音识别 python版接口
    分享用于学习C++音频处理的代码示例
    集 降噪 美颜 虚化 增强 为一体的极速图像润色算法 附Demo程序
    快速双边滤波 附完整C代码
    pixel art之 hqx 算法
    这一路走来,冷暖自知 (附算法demos)
    票据OCR前预处理 (附Demo)
    学习图像算法阶段性总结 (附一键修图Demo) 2016.04.19更新demo
  • 原文地址:https://www.cnblogs.com/522040-m/p/13164193.html
Copyright © 2020-2023  润新知