【electron-vue】实现长按按钮+-输入框数字自增自减,上拖动增,下拖动减少。

需求

1、长按按钮+/长按按钮-,输入框数字自增/减少。

2、长按时,鼠标移出了按钮区域,不管原来click的是+,还是-,以鼠标竖直方向的差值绝对值为步长,只要mousemove方向往上,数字增加,方向往下,数字减少。

3、点击输入框可以直接修改输入框的数值。

4、可以输入正负整数。支持设置最大、小值,输入后自动调整数值到区间内。

5、hover按钮/输入框,边框为蓝色。

6、数值达到临界值无法再调整后,hover鼠标按钮样式为禁用状态

input 需求2不知道怎么实现,因此自行实现一个input-number组件。

 

期望

图为element input-number效果图

 

技术点

1、mousedown事件、mouseout事件、mouseup事件、setInterval

2、mousemove事件、父级组件调用子组件方法(refs的使用)

3、鼠标方向的判断

4、隐藏input"上下"箭头

交互效果:

5、mouseenter事件、mouseleave事件,border-color

6、cursor: not-allowed;

去掉按钮focus边框 outline: none;

 

最终效果

 

 

参考 vue中父组件调用子组件的方法

参考 vue组件:input数字输入框

参考 按下鼠标并拖到按钮外松开,如何触发click事件?

参考 用鼠标按下事件和鼠标松开事件实现长按事件

参考 VUE长按事件

参考 隐藏input type=number元素,右侧的上下箭头

 

代码参考

父类调用者 LandingPage.vue

<template>
    //省略....
    <input-number
          :value="1"
          :max-num="Number.MAX_VALUE"
          :min-num="0"
          ref="rightSide_inpunumber"
        ></input-number>
    //省略....
</template>

<script>
import InputNumber from "./Basic/InputNumber";

export default {
  name: "landing-page",
  components: { SystemInformation, InputNumber },
  data() {
    return {
      oldclientY: -1,
    };
  },
  methods: {
    pageMouseUp() {
      // console.log("pageMouseUp");
      this.$refs.rightSide_inpunumber.buttonMouseup();
    },
    pageMouseMove(e) {
      let offsetY = e.clientY - this.oldclientY;
      let flag = 0;
      if (offsetY > 0) {
        flag = 1;
      } else if (offsetY < 0) {
        flag = -1;
      }
      this.oldclientY = e.clientY;
      if (offsetY != 0 && this.$refs.rightSide_inpunumber.isClickButton) {
        offsetY = Math.abs(offsetY);
        this.$refs.rightSide_inpunumber.updateOffset(flag, offsetY);
      }
    },
  },
};

</script>

组件 InputNumber.vue

<template>
  <div class="inputNumber-wrapper">
    <input
      class="numboxInput"
      :style="inputStyle"
      type="number"
      :value="currentVal"
      @change="fixNumber"
      @mouseenter="inputMouseEnter"
      @mouseleave="inputMouseLeave"
    />
    <button
      id="reduceBtn"
      :class="reduceBtnClass"
      @mousedown="buttonMousedown(-1)"
      @mouseenter="inputMouseEnter"
      @mouseleave="inputMouseLeave"
      @mouseout="buttonMouseOut"
      @mouseup="buttonMouseup()"
    >-</button>
    <button
      id="addBtn"
      :class="addBtnClass"
      @mousedown="buttonMousedown(1)"
      @mouseenter="inputMouseEnter"
      @mouseleave="inputMouseLeave"
      @mouseout="buttonMouseOut"
      @mouseup="buttonMouseup()"
    >+</button>
  </div>
</template>

<script>
export default {
  name: "inputnumber",
  data() {
    return {
      addBtnClass: "btn",
      reduceBtnClass: "btn",
      inputStyle: {
        "border-color": "",
      },
      timeInterval: null,
      currentVal: this.value,
      isClickButton: false,
    };
  },
  components: {},
  props: {
    value: {
      type: Number,
      default: 10,
    },
    maxNum: {
      type: Number,
      default: Infinity,
    },
    minNum: {
      type: Number,
      default: -Infinity,
    },
    step: {
      type: Number,
      default: 1,
    },
  },
  watch: {
    currentVal(val) {
      this.$emit("input", val);
    },
  },
  methods: {
    /**
     * 交互效果 enter-变蓝
     */
    inputMouseEnter() {
      this.updateInputBorder(true);
      this.updateCursor();
    },
    /**
     * 交互效果 leave-恢复
     */
    inputMouseLeave() {
      this.updateInputBorder(false);
      this.updateCursor();
    },
    /**
     * 交互效果 input边框
     */
    updateInputBorder(isChanging) {
      if (isChanging) {
        this.inputStyle["border-color"] = "#409eff";
      } else {
        this.inputStyle["border-color"] = "";
      }
    },
    fixNumber($event) {
      let fix;
      if (typeof $event.target.value != "number") {
        fix = Number($event.target.value);
      } else {
        fix = $event.target.value;
      }
      this.updateVal(fix);
    },
    updateVal(val) {
      if (val > this.maxNum) val = this.maxNum;
      if (val < this.minNum) val = this.minNum;
      this.currentVal = val;
    },
    /**
     * flag : +/-
     * offset :一次加/减的值
     */
    updateOffset(flag, offset) {
      let isCanSet = false;
      if (flag > 0) {
        this.currentVal =
          this.currentVal < this.maxNum
            ? this.currentVal + offset
            : this.maxNum;
        this.updateVal(this.currentVal);
        this.updateCursor();
      } else if (flag < 0) {
        this.currentVal =
          this.currentVal > this.minNum
            ? this.currentVal - offset
            : this.minNum;
        this.updateVal(this.currentVal);
        this.updateCursor();
      }
    },
    updateCursor() {
      this.addBtnClass =
        this.currentVal < this.maxNum
          ? "btn"
          : "btn btn_is-disabled";
      this.reduceBtnClass =
        this.currentVal > this.minNum
          ? "btn"
          : "btn btn_is-disabled";
    },
    buttonClick(flag) {
      this.updateOffset(flag, this.step);
    },
    buttonMousedown(flag) {
      this.isClickButton = true;
      this.clearTimeInterval();
      if (flag > 0) {
        this.timeInterval = setInterval(() => {
          this.buttonClick(1);
        }, 100);
      } else if (flag < 0) {
        this.timeInterval = setInterval(() => {
          this.buttonClick(-1);
        }, 100);
      }
    },
    buttonMouseOut() {
      this.clearTimeInterval();
    },
    buttonMouseup() {
      this.isClickButton = false;
      this.clearTimeInterval();
    },
    clearTimeInterval() {
      if (this.timeInterval == null) return;
      clearInterval(this.timeInterval);
      this.timeInterval = null;
    },
  },
};
</script>

<style scoped>
/**去掉上下箭头 */
.inputNumber-wrapper {
  width: 180px;
  height: 40px;
  display: flex;
  position: relative;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input[type="number"] {
  -moz-appearance: textfield;
}

/**输入框 */
.numboxInput {
  text-align: center;
  background-color: #fff;
  background-image: none;
  border-radius: 4px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  color: #606266;
  display: inline-block;
  font-size: inherit;
  height: 40px;
  line-height: 40px;
  outline: none;
  padding: 0 15px;
  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
  width: 100%;
  padding-left: 15px;
  padding-right: 50px;
}
.numboxInput:hover {
  border-color: #c0c4cc;
}
.numboxInput_changing {
  border-color: #409eff;
}
.numboxInput:focus {
  border-color: #409eff;
}

/**按钮们 */
.btn {
  position: absolute;
  z-index: 1;
  width: 41px;
  height: auto;
  text-align: center;
  background: #f5f7fa;
  color: #606266;
  cursor: pointer;
  font-size: 13px;
  line-height: 19px;
  border: none;
  border-right: none;
  border-left: 1px solid #dcdfe6;
}
.btn:focus {
  outline: none;
}
.btn:hover {
  color: #409eff;
}
.btn_is-disabled {
  cursor: not-allowed;
}
#reduceBtn {
  right: 1px;
  bottom: 1px;
  top: auto;
  left: auto;
  border-radius: 0 0 4px 0;
}
#addBtn {
  top: 1px;
  right: 1px;
  border-radius: 0 4px 0 0;
  border-bottom: 1px solid #dcdfe6;
}
</style>

测试工程

https://github.com/LJLCarrien/evtest.git

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值