vue 数字软键盘 插件 封装 可拖动

1、效果图 

4341ddb9a2c64ad194c71f6d4d8ea940.gif

2、使用方式

<Keyboard v-if="show" @close="show = false" :inputDom="$refs.input" />

封装的数字键盘 Keyboard.vue 组件代码

<template>
  <div
    class="keyboard"
    ref="keyboard"
    :style="{ left: moveX + 'px', bottom: moveY + 'px' }"
  >
    <div class="drag" @mousedown="keyDown">
      <p></p>
      <div @click="$emit('close')" @mousedown.stop @mousemove.stop>
        <img src="./arrow.svg" alt="" />
      </div>
    </div>
    <div class="main">
      <div class="left">
        <div
          v-for="text in symbols"
          :key="text"
          @click="insertTxtAndSetcursor(text)"
        >
          {{ text }}
        </div>
      </div>
      <div class="right">
        <div class="left">
          <div
            class="item"
            v-for="i in 9"
            :key="i"
            @click="insertTxtAndSetcursor(i)"
          >
            {{ i }}
          </div>
        </div>
        <div class="right">
          <div class="item" @click="insertTxtAndSetcursor('', true)">
            <img src="./delete.svg" alt="" />
          </div>
          <div class="item" @click="insertTxtAndSetcursor(' ')">
            <img src="./blank.svg" alt="" />
          </div>
          <div class="item" @click="insertTxtAndSetcursor(0)">0</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script scoped>
export default {
  data() {
    return {
      symbols: ["+", "-", "=", ".", "/", "@"],
      flag: false,
      seto: null,
      downInfo: {},
      moveX: 0,
      moveY: 0,
    };
  },
  props: {
    inputDom: {
      type: Node,
      default: null,
    },
  },
  mounted() {
    document.addEventListener("mousemove", this.keyMove);
  },
  methods: {
    // 输入文本
    insertTxtAndSetcursor(text, del) {
      let element = this.inputDom; // 获取到指定标签
      let startPos = element.selectionStart; // 获取光标开始的位置
      let endPos = element.selectionEnd; // 获取光标结束的位置
      if (startPos === undefined || endPos === undefined) return; // 如果没有光标位置 不操作
      let oldTxt = element.value; // 获取输入框的文本内容
      let result = "";
      // 光标位置不能小于0
      const num = startPos - 1;
      if (del && num >= 0) {
        result = oldTxt.substring(0, startPos - 1) + oldTxt.substring(endPos); // 将文本插入
      } else {
        result =
          oldTxt.substring(0, startPos) + text + oldTxt.substring(endPos); // 将文本插入
      }
      element.value = result; // 将拼接好的文本设置为输入框的值
      element.focus(); // 重新聚焦输入框
      if (del && num >= 0) {
        element.selectionStart = startPos - 1 + (text + "").length; // 设置光标开始的位置
        element.selectionEnd = startPos - 1 + (text + "").length; // 设置光标结束的位置
      } else {
        element.selectionStart = startPos + (text + "").length; // 设置光标开始的位置
        element.selectionEnd = startPos + (text + "").length; // 设置光标结束的位置
      }
    },
    keyUp() {
      this.flag = false;
      document.removeEventListener("mouseup", this.keyUp);
      document.removeEventListener("mouseleave", this.keyUp);
    },
    keyDown(e) {
      this.downInfo.x = e.pageX;
      this.downInfo.y = e.pageY;
      this.downInfo.left = this.moveX;
      this.downInfo.bottom = this.moveY;
      this.seto = setTimeout(() => {
        this.flag = true;
        document.addEventListener("mouseup", this.keyUp);
        document.addEventListener("mouseleave", this.keyUp);
        clearTimeout(this.seto);
      }, 1000);
    },
    keyMove(e) {
      if (this.flag) {
        const maxh =
          (document.clientHeight ||
            document.documentElement.clientHeight ||
            document.body.clientHeight) - this.$refs.keyboard.clientHeight;
        const htj = this.downInfo.bottom + this.downInfo.y - e.pageY;
        const maxw =
          (document.clientWidth ||
            document.documentElement.clientWidth ||
            document.body.clientWidth) - this.$refs.keyboard.clientWidth;
        const wtj = this.downInfo.left - (this.downInfo.x - e.pageX);
        if (wtj <= maxw && wtj >= 0) {
          //确保键盘始终在屏幕可见范围内
          this.moveX = wtj;
        }
        if (htj <= maxh && htj >= 0) {
          //确保键盘始终在屏幕可见范围内
          this.moveY = htj;
        }
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.keyboard {
  width: 100vw;
  height: 245px;
  max-width: 353px;
  min-width: 285px;
  position: fixed;
  bottom: 0;
  left: 0;
  background-color: #d6d7db;
  > .drag {
    width: 100%;
    height: 15%;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    > p {
      width: 30%;
      height: 13%;
      border-radius: 5px;
      background-color: #fff;
    }
    > div {
      width: 18.3%;
      height: 100%;
      position: absolute;
      top: 50%;
      right: 0;
      transform: translateY(-50%);
      &::before {
        width: 1px;
        content: "";
        height: 60%;
        background-color: #fff;
        position: absolute;
        top: 50%;
        left: 0;
        transform: translateY(-50%);
      }
      > img {
        user-select: none;
        width: 45%;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    }
  }
  > .main {
    height: calc(100% - 15%);
    display: flex;
    justify-content: space-between;
    padding: 2%;
    > .left {
      flex: 15;
      margin-right: 2%;
      height: 100%;
      border-radius: 6px;
      background-color: #fff;
      overflow: auto;
      user-select: none;
      &::-webkit-scrollbar {
        display: none;
      }

      > div {
        font-size: 20px;
        height: 25%;
        display: flex;
        align-items: center;
        justify-content: center;
        &:active {
          background-color: #a1a8b8;
        }
      }
    }
    > .right {
      height: 100%;
      border-radius: 5px;
      flex: 77;
      display: flex;
      justify-content: space-between;
      user-select: none;
      > .left {
        height: 100%;
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
        align-content: space-between;
        width: 77%;
        > .item {
          background-color: #fff;
          height: 30.8%;
          width: 31.5%;
          display: flex;
          align-items: center;
          justify-content: center;
          border-radius: 5px;
          font-size: 18px;
          &:active {
            background-color: #adb4be;
          }
          &:nth-of-type(3n) {
            margin-right: 0;
          }
          &:nth-of-type(7),
          &:nth-of-type(8),
          &:nth-of-type(9) {
            margin-bottom: 0;
          }
        }
      }
      > .right {
        width: 21%;
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        > .item {
          border-radius: 5px;
          display: flex;
          align-items: center;
          justify-content: center;
          height: 30.8%;
          background-color: #adb4be;
          > img {
            width: 40%;
          }
          &:active {
            background-color: #7e8492;
          }
        }
      }
    }
  }
}
</style>

3、使用方式代码 

<template>
  <div id="app">
    <input ref="input" type="text" @focus="show = true" v-model="text" />
    <Keyboard v-if="show" @close="show = false" :inputDom="$refs.input" />
  </div>
</template>

<script scoped>
import Keyboard from "./Keyboard.vue";
export default {
  components: { Keyboard },
  data() {
    return { show: false, text: "" };
  },
};
</script>

<style lang="scss" scoped>
#app {
  width: 100vw;
  height: 100vh;
  background-color: #000;
  > input {
    height: 25px;
    display: block;
    margin: 0 auto;
  }
}
</style>

4、完结 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xl__qd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值