嘎嘎好用的虚拟键盘第二弹之中文输入法

发布于:2024-05-07 ⋅ 阅读:(28) ⋅ 点赞:(0)

之前还在为不用研究输入中文而暗自窃喜 这不新需求就来了(新需求不会迟到 它只是在路上飞一会儿)
找到了个博主分享的代码 是好使的 @前端-xyq 已经和原作者申请转载了 感谢~~

原作者地址:https://www.cnblogs.com/linjiangxian/p/16223681.html

抄的过程中发现 诶? 这不我之前用的那个虚拟键盘组件吗 这货还带中文呢
是的 他带 上一篇还有人问我能不能中文输入 我之前瞪两眼珠子 活拉就是没看见

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
原作者的方法就是能实现的 套了两层组件keyboard-input 和 simpleKeyboard
两个utils的js方法 core.js隐藏键盘 和 mixins.js 表单字段校验(这里用element-ui el-form的prop validate校验也行)

用的过程中发现有两个报错
1.点击关闭if (button == ‘{close}’) 会报

在这里插入图片描述
if里改成如下代码即可

	if (button == '{close}') {
        let arr = document.querySelectorAll('.hg-theme-default');
        arr.forEach((ele) => {
          ele.style.visibility = 'hidden';
        });
        return false;
      }

2.中英文切换时会报错
在这里插入图片描述
改成如下代码即可

        if (this.keyboard.options.layoutCandidates !== null) {
          this.displayDefault = {
            '{bksp}': 'backspace',
            '{lock}': 'caps',
            '{tab}': 'tab',
            '{shift}': 'shift',
            '{change}': '中文',
            '{space}': ' ',
            '{clear}': '清空',
            '{close}': '关闭',
          },
          this.keyboard.setOptions({
            layoutCandidates: null,
            display: this.displayDefault,
          });
        } else {
          this.displayDefault = {
            '{bksp}': 'backspace',
            '{lock}': 'caps',
            '{tab}': 'tab',
            '{shift}': 'shift',
            '{change}': '英文',
            '{space}': ' ',
            '{clear}': '清空',
            '{close}': '关闭',
          },
          this.keyboard.setOptions({
            layoutCandidates: layout.layoutCandidates,
            display: this.displayDefault,
          });
        }

我这里修改了simpleKeyboard内的部分代码 做了点样式调整

<template>
  <div :class="keyboardClass"></div>
</template>

<script>
import Keyboard from 'simple-keyboard';
import 'simple-keyboard/build/css/index.css';
import layout from 'simple-keyboard-layouts/build/layouts/chinese'; // 中文输入法

export default {
  name: 'SimpleKeyboard',
  props: {
    keyboardClass: {
      default: 'simple-keyboard',
      type: String,
    },
    input: {
      type: String,
      default: '',
    },
  },
  data: () => ({
    keyboard: null,
  }),
  mounted() {
    this.keyboard = new Keyboard(this.keyboardClass, {
      onChange: this.onChange,
      onKeyPress: this.onKeyPress,
      ...layout
    });
    this.setKeyboard()
  },
  methods: {
    setKeyboard() {
      this.keyboard.setOptions({
      layoutName: "shift",
      layoutCandidatesPageSize: 10,
      theme: "hg-theme-default hg-layout-default myTheme",
      layout: {
        // 默认布局
        default: [
          '` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
          '{tab} q w e r t y u i o p [ ] \\',
          "{lock} a s d f g h j k l ; '",
          '{shift} z x c v b n m , . / {clear}',
          '{change} {space} {close}',
        ],
        // 切换shift布局
        shift: [
          '~ ! @ # $ % ^ & * ( ) _ + {bksp}',
          '{tab} Q W E R T Y U I O P { } |',
          '{lock} A S D F G H J K L : "',
          '{shift} Z X C V B N M < > ? {clear}',
          '{change} {space} {close}',
        ],
      },
      buttonTheme: [
        {
          class: 'hg-red close',
          buttons: '{close}',
        },
        {
          class: 'hg-red change',
          buttons: '{change}',
        },
      ],
      display: {
        '{bksp}': 'backspace',
        '{lock}': 'caps',
        '{tab}': 'tab',
        '{shift}': 'shift',
        '{change}': '英文',
        '{space}': ' ',
        '{clear}': '清空',
        '{close}': '关闭',
      }
    });
    },

    onChange(input) {
      this.$emit('onChange', input);
    },
    
    // 点击键盘
    onKeyPress(button, $event) {
      console.log("onKeyPress -> $event", $event)
      if (button == '{close}') {
        let arr = document.querySelectorAll('.hg-theme-default');
        arr.forEach((ele) => {
          ele.style.visibility = 'hidden';
        });
        return false;
      } else if (button == '{change}') { // 切换中英输入法        
        if (this.keyboard.options.layoutCandidates !== null) {
          this.displayDefault = {
            '{bksp}': 'backspace',
            '{lock}': 'caps',
            '{tab}': 'tab',
            '{shift}': 'shift',
            '{change}': '中文',
            '{space}': ' ',
            '{clear}': '清空',
            '{close}': '关闭',
          },
          this.keyboard.setOptions({
            layoutCandidates: null,
            display: this.displayDefault,
          });
        } else {
          this.displayDefault = {
            '{bksp}': 'backspace',
            '{lock}': 'caps',
            '{tab}': 'tab',
            '{shift}': 'shift',
            '{change}': '英文',
            '{space}': ' ',
            '{clear}': '清空',
            '{close}': '关闭',
          },
          this.keyboard.setOptions({
            layoutCandidates: layout.layoutCandidates,
            display: this.displayDefault,
          });
        }
      } else if (button == '{clear}') {
        this.keyboard.clearInput();
      } else {
        let value = $event.target.offsetParent.parentElement.children[0].children[0].value;
        if (value) {
          this.keyboard.setInput(value);
        }        
      }
      this.$emit('onKeyPress', button);
      /**
       * If you want to handle the shift and caps lock buttons
       */
      if (button === '{shift}' || button === '{lock}') this.handleShift();
    },


    handleShift() {
      let currentLayout = this.keyboard.options.layoutName;
      let shiftToggle = currentLayout === "default" ? "shift" : "default";

      this.keyboard.setOptions({
        layoutName: shiftToggle
      });
    } 

  },
  watch: {
    input(input) {
      this.keyboard.setInput(input);
    },
  },
};
</script>

<style scoped>
  .hg-theme-default {
    width: 80%;
    padding: 15px;
    box-shadow: 0 4px 0 #b2b2b2, 0 7px 16px rgba(0,0,0,.3);
  }
  .hg-theme-default /deep/ .hg-button {
    height: 50px;    
  }
  .hg-theme-default /deep/ .hg-red {
    background: #a8001e!important;
    color: white;
  }
  .hg-theme-default /deep/ .hg-red {
    max-width: 200px;
  }
  .hg-theme-default /deep/ .close {
    max-width: 200px;
  }
  .hg-theme-default /deep/ .change {
    max-width: 200px;
  }

  .hg-theme-default /deep/ .hg-button{
    height: 50px;
    margin: 8px 10px;
    font-size: 23px;
    background-color: #fff;
    border-radius: 8px;
    cursor: pointer;
    -webkit-box-shadow: 0 4px 0 #b2b2b2, 0 5px 10px rgba(0,0,0,.7);
    box-shadow: 0 3px 0 #b2b2b2, 0 4px 6px rgba(0,0,0,.7);
  }

  .hg-theme-default /deep/ .hg-button:active {
    box-shadow: 0 4px 0 #717070, 0 5px 3px rgba(0,0,0,.9);
    background-color: #efefef;
  }

  .hg-theme-default /deep/ .hg-layout-default .hg-button.bksp {
    height: 50px;
    margin: 8px 10px;
    font-size: 23px;
    background-color: #fff;
    border-radius: 8px;
    cursor: pointer;
    -webkit-box-shadow: 0 4px 0 #b2b2b2, 0 5px 10px rgba(0,0,0,.7);
    box-shadow: 0 3px 0 #b2b2b2, 0 4px 6px rgba(0,0,0,.7);
    background: #a8001e;
    color: white;
  }

  .hg-theme-default /deep/ .hg-layout-default .hg-button.bksp:active {
    box-shadow: 0 4px 0 #717070, 0 5px 3px rgba(0,0,0,.9);
    background-color: #efefef;
    color: #000000;
  }

  .hg-theme-default /deep/ .hg-layout-default .hg-button.enter {
    height: 50px;
    margin: 5px 8px;
    font-size: 23px;
    background-color: #fff;
    border-radius: 8px;
    cursor: pointer;
    -webkit-box-shadow: 0 4px 0 #b2b2b2, 0 5px 10px rgba(0,0,0,.7);
    box-shadow: 0 3px 0 #b2b2b2, 0 4px 6px rgba(0,0,0,.7);
    background: #a8001e;
    color: white;
  }

  .hg-theme-default /deep/ .hg-layout-default .hg-button.enter:active {
    box-shadow: 0 4px 0 #717070, 0 5px 3px rgba(0,0,0,.9);
    background-color: #efefef;
    color: #000000;
  }
</style>

外层组件keyboard-input的css样式

<style scoped>
  .input-keyboard /deep/ .hg-theme-default {
    position: fixed;
    left: 50%;
    bottom: 230px;
    transform: translate(-50%);
    visibility: hidden;
    margin-top: 20px;
    z-index: 2000; 
  }

  .input-keyboard /deep/ .hg-candidate-box {
    position: static;
    transform: translateY(0);
    border-bottom: none;
    border-radius: none;
  }

  .input-keyboard /deep/.hg-rows {
    font-size: 25px;
  }
  
  .input-keyboard /deep/ .hg-candidate-box {
    font-size: 23px;
  } 
  .input-keyboard /deep/ li.hg-candidate-box-list-item {   
    height: 60px;
    width: 40px;
    padding: 0 6px;
  }
</style>


<style scoped>
  .input-keyboard /deep/ .el-input__inner {
    color: #000;
    border-color: #adadad;
    height: 45px;
  }
  .input-keyboard /deep/ .el-form-item.is-error .el-input__inner, .el-form-item.is-error .el-input__inner:focus, .el-form-item.is-error .el-textarea__inner, .el-form-item.is-error .el-textarea__inner:focus, .el-message-box__input input.invalid, .el-message-box__input input.invalid:focus {
    border-color: #a8001c;
  }
  .input-keyboard /deep/ .el-form-item__error {
    color: #a8001c;
    font-size: 17px;
    line-height: 1;
    padding-top: 2px;
    position: absolute;
    top: 100%;
    left: 0;
  }
  .input-keyboard /deep/ .el-form-item {
    margin-bottom: 50px;
  }
  .input-keyboard /deep/ .el-form-item__label {
    font-size: 25px;
    color: #000000;
  }
  .input-keyboard /deep/ .el-input.is-disabled .el-input__inner {
    font-size: 25px;
    height: 45px;
    background-color: #fff;
    border-color: #adadad;
    color: #000;
    cursor: not-allowed;
  }
  .input-keyboard /deep/ .el-textarea__inner {   
    font-size: 25px;
    color: #000000;   
  }
  .input-keyboard /deep/ .el-textarea.is-disabled .el-textarea__inner {
    font-size: 25px;
    height: 45px;
    background-color: #fff;
    border-color: #adadad;
    color: #000;
    cursor: not-allowed;
    font-family: Avenir,Helvetica,Arial,sans-serif;
  }
  .input-keyboard /deep/ .el-input.is-active .el-input__inner, .el-input__inner:focus {
    border-color: #a8001e;
    outline: 0;
  }
  .input-keyboard /deep/ .el-input.is-disabled .el-input__wrapper {
    background-color: #ffffff;
  } 
  .input-keyboard /deep/ .el-form-item.is-error .el-select-v2__wrapper, .el-form-item.is-error .el-select-v2__wrapper:focus, .el-form-item.is-error .el-textarea__inner, .el-form-item.is-error .el-textarea__inner:focus {
    box-shadow: 0 0 0 1px #a8001e inset;
  }
</style>

再次感谢作者@前端-xyq