Vue实现双向滑动输入条

本文实例为大家分享了Vue实现双向滑动输入条的具体代码,供大家参考,具体内容如下

效果图如下:

组件支持传入最小值(min)最大值(max)的范围,并可设置初始最小值(initialMin)和初始最大值(initialMax)

拖动滑块调整最大最小值,并可点击输入条位置,切换数值

①创建滑动输入条组件Slider.vue

<template>
  <div class="m-slider" ref="slider">
    <div class="u-slider-rail" @click="onClickPoint"></div>
    <div class="u-slider-track" @click="onClickPoint" :style="`left: ${left}px; right: auto; width: ${right - left}px;`"></div>
    <div class="u-slider-handle" ref="left" @mousedown="onLeftMouseDown" :style="`left: ${left}px; right: auto; transform: translateX(-50%);`"></div>
    <div class="u-slider-handle" ref="right" @mousedown="onRightMouseDown" :style="`left: ${right}px; right: auto; transform: translateX(-50%);`"></div>
  </div>
</template>
<script>
export default {
  name: 'Slider',
  props: {
    min: { // 滑动输入条最小值
      type: Number,
      default: 0
    },
    max: { // 滑动输入条最大值
      type: Number,
      default: 100
    },
    initialMin: { // 滑动输入条初始最小值,默认在最左侧
      type: Number,
      default: 0
    },
    initialMax: { // 滑动输入条初始最大值,默认在最右侧
      type: Number,
      default: 100
    }
  },
  data () {
    return {
      left: '', // 左滑块距离滑动条左端的距离
      right: '', // 右滑动距离滑动条左端的距离
      width: '' // 滑动输入条在页面中的宽度
    }
  },
  mounted () {
    this.width = this.$refs.slider.clientWidth
    this.left = this.initialMin * this.width / this.max
    this.right = this.initialMax * this.width / this.max
  },
  computed: {
    low () {
      return Math.round(this.left / this.width * this.max)
    },
    high () {
      return Math.round(this.right / this.width * this.max)
    }
  },
  watch: {
    low (to, from) {
      this.$emit('lowChange', to) // 左滑块对应数字回调
    },
    high (to, from) {
      this.$emit('highChange', to) // 右滑块对应数字回调
    }
  },
  methods: {
    onClickPoint (e) { // 点击滑动条,移动滑块
      var offsetLeft = this.$refs.slider.offsetLeft // 滑动条左端距离屏幕左侧的距离
      var moveX = e.clientX - offsetLeft
      if (moveX <= this.left) {
        this.left = moveX
      } else if (this.moveX >= this.right) {
        this.right = this.moveX
      } else {
        if ((moveX - this.left) < (this.right - moveX)) {
          this.left = moveX
        } else {
          this.right = moveX
        }
      }
    },
    onLeftMouseDown (e) { // 在滚动条上拖动左滑块
      // 滑块水平方向上距离屏幕左端的距离,减去滑块距离滑动条最左端的距离:e.clientX - this.$refs.left.offsetLeft
      var offsetLeft = this.$refs.slider.offsetLeft // 滑动条左端距离屏幕左侧的距离
      document.onmousemove = (e) => {
        var moveX = e.clientX - offsetLeft
        if (moveX < 0) {
          this.left = 0
        } else if (moveX >= this.right) {
          this.left = this.right
        } else {
          this.left = moveX
        }
      }
      document.onmouseup = (e) => {
        document.onmousemove = null
        document.onmouseup = null
      }
    },
    onRightMouseDown (e) { // 在滚动条上拖动右滑块
      /// 滑块水平方向上距离屏幕左端的距离,减去滑块距离滑动条最左端的距离:e.clientX - this.$refs.left.offsetLeft
      var offsetLeft = this.$refs.slider.offsetLeft // 滑动条左端距离屏幕左侧的距离
      console.log('offsetLeft:', offsetLeft)
      document.onmousemove = (e) => {
        var moveX = e.clientX - offsetLeft
        if (moveX > this.width) {
          this.right = this.width
        } else if (moveX <= this.left) {
          this.right = this.left
        } else {
          this.right = moveX
        }
      }
      document.onmouseup = (e) => {
        document.onmousemove = null
        document.onmouseup = null
      }
    }
  }
}
</script>
<style lang="less" scoped>
.m-slider {
  height: 4px;
  position: relative;
  cursor: pointer;
  touch-action: none;
  &:hover {
    .u-slider-rail { // 灰色未选择滑动条背景色
      background: #E3E3E3;
    }
    .u-slider-track { // 蓝色已选择滑动条背景色
      background: #1890ff;
    }
  }
  .u-slider-rail { // 灰色未选择滑动条背景色
    position: absolute;
    z-index: 99;
    height: 4px;
    width: 100%;
    background: #f5f5f5;
    border-radius: 2px;
    transition: background .3s;
  }
  .u-slider-track { // 蓝色已选择滑动条背景色
    background: #91d5ff;
    border-radius: 4px;
    position: absolute;
    z-index: 99;
    height: 4px;
    cursor: pointer;
    transition: background .3s;
  }
  .u-slider-handle { // 滑块
    position: absolute;
    z-index: 999;
    width: 14px;
    height: 14px;
    margin-top: -7px;
    box-shadow: 0;
    background: #fff;
    border: 2px solid #91d5ff;
    border-radius: 50%;
    cursor: pointer;
    transition: border-color .3s,box-shadow .6s,transform .3s cubic-bezier(.18,.89,.32,1.28);
    &:hover {
      border-color: #1890ff;
    }
  }
}
</style>

②在要使用的页面引入

<div class="m-num">
    <p class="u-num">{{ low }}</p>
    <p class="u-num">{{ high }}</p>
</div>
<div class="slider">
    <Slider
        :min="0"
        :max="100"
        :initialMin="low"
        :initialMax="high"
        @lowChange="lowChange"
        @highChange="highChange"
    />
</div>
import Slider from '@/components/Slider'
components: {
    Slider
}
data () {
    return {
        low: 20,
        high: 80
    }
}
lowChange (val) {
      this.low = val
      console.log('lowChange:', val)
},
highChange (val) {
      this.high = val
      console.log('highChange:', val)
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vue开发拖拽进度条滑动组件

    分享一个最近写的进度条滑动组件,以前都是用jq写,学会了vue,尝试着拿vue来写觉得非常简单,代码复用性很强! 效果图如下: 调用组件如下: <slider :min=0 :max=100 v-model = "per"></slider> <template> <div class="slider" ref="slider"> <div class="process"

  • vue实现滑动验证条

    本文实例为大家分享了vue实现滑动验证条的具体代码,供大家参考,具体内容如下 效果 代码 VerifySlider.vue <template>   <div     ref="dragDiv"     class="drag"   >     <div ref="drag_bg" class="drag_bg" />     <div ref="drag_text"

  • Vue实现双向滑动输入条

    本文实例为大家分享了Vue实现双向滑动输入条的具体代码,供大家参考,具体内容如下 效果图如下: 组件支持传入最小值(min)最大值(max)的范围,并可设置初始最小值(initialMin)和初始最大值(initialMax) 拖动滑块调整最大最小值,并可点击输入条位置,切换数值 ①创建滑动输入条组件Slider.vue <template>   <div class="m-slider" ref="slider">     <div

  • iOS实现双向滑动条效果

    最近做项目,碰到一种双向滑动条,自己实现了一下,随便写一下思路,方便以后开发,避免重复写代码,以后粘贴就行了.封装了一下,代码如下: #import <UIKit/UIKit.h> typedef NSString* (^HLDoubleSlideViewSwitchStrBock)(CGFloat count); @interface HLDoubleSlideView : UIView @property(nonatomic,assign)CGFloat maxValue; @proper

  • Vue 的双向绑定原理与用法揭秘

    本文实例讲述了Vue 的双向绑定原理与用法.分享给大家供大家参考,具体如下: Vue 中需要输入什么内容的时候,自然会想到使用 <input v-model="xxx" /> 的方式来实现双向绑定.下面是一个最简单的示例 <div id="app"> <h2>What's your name:</h2> <input v-model="name" /> <div>Hello

  • Android自定义双向滑动控件

    本文实例为大家分享了Android自定义双向滑动控件的具体代码,供大家参考,具体内容如下 先看一下效果图 1.SeekBarPressure工具类 public class SeekBarPressure extends View {     private static final String TAG = "SeekBarPressure";     private static final int CLICK_ON_LOW = 1;      //点击在前滑块上     priv

  • vue loadmore 组件滑动加载更多源码解析

    上一篇讲到在项目中使用上拉加载更多组件,但是由于实际项目开发中由于需求变更或者说在webview中上拉加载有些机型在上拉时候会把webview也一起上拉导致上拉加载不灵敏等问题,我们有时候也会换成滑动到底部自动加载的功能. 既然都是加载更多,很多代码思想势必相似,主要区别在于上拉和滑动到底部这个操作上,所以,我们需要注意: 上拉加载是point指针touch触摸事件,现在因为是滑动加载,需要添加scroll事件去监听然后执行相应回调 上拉加载主要计算触摸滚动距离,滑动加载主要计算containe

  • Vue.js双向绑定实现原理详解

    Vue.js最核心的功能有两个,一是响应式的数据绑定系统,二是组件系统.本文仅探究几乎所有Vue的开篇介绍都会提到的hello world双向绑定是怎样实现的.先讲涉及的知识点,再参考源码,用尽可能少的代码实现那个hello world开篇示例. 参考文章:http://www.jb51.net/article/100819.htm 一.访问器属性 访问器属性是对象中的一种特殊属性,它不能直接在对象中设置,而必须通过defineProperty()方法单独定义. var obj = { }; /

  • 深入理解vue.js双向绑定的实现原理

    前言 大家都知道Vue.js最核心的功能有两个,一是响应式的数据绑定系统,二是组件系统.本文仅探究几乎所有Vue的开篇介绍都会提到的hello world双向绑定是怎样实现的.先讲涉及的知识点,再参考源码,用尽可能少的代码实现那个hello world开篇示例. 一.访问器属性 访问器属性是对象中的一种特殊属性,它不能直接在对象中设置,而必须通过defineProperty()方法单独定义. var obj = { }; // 为obj定义一个名为hello的访问器属性 Object.defin

  • Vue实现双向绑定的方法

    本文能帮你做什么? 1.了解vue的双向数据绑定原理以及核心代码模块 2.缓解好奇心的同时了解如何实现双向绑定 为了便于说明原理与实现,本文相关代码主要摘自vue源码, 并进行了简化改造,相对较简陋,并未考虑到数组的处理.数据的循环依赖等,也难免存在一些问题,欢迎大家指正.不过这些并不会影响大家的阅读和理解,相信看完本文后对大家在阅读vue源码的时候会更有帮助< 本文所有相关代码均在github上面可找到 https://github.com/DMQ/mvvm 相信大家对mvvm双向绑定应该都不

  • 轻松理解vue的双向数据绑定问题

    Vue介绍 Vue是当前很火的一款MVVM的轻量级框架,它是以数据驱动和组件化的思想构建的.因为它提供了简洁易于理解的api,使得我们很容易上手. Vue与MVVM 如果你之前已经习惯了用jQuery操作DOM,学习Vue.js时请先抛开手动操作DOM的思维,因为Vue.js是数据驱动的,你无需手动操作DOM.Vue以数据为驱动,将自身的Dom元素与数据进行绑定,一旦创建绑定,Dom和数据保持同步. 双向绑定 主流双向数据绑定实现原理 脏值检测 : 这是AngularJS实现双向数据绑定的方式.

随机推荐