前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue <滑块拖动>

Vue <滑块拖动>

作者头像
网罗开发
发布2021-04-07 15:29:18
8620
发布2021-04-07 15:29:18
举报
文章被收录于专栏:网罗开发网罗开发

类似于滑块拖动很多组件都有,需求不复杂的可以直接用第三方组件的。但是如果碰到渐变拖动相信一大部分组件都没有,所以就要想办法自己封装了,其实原理还是很简单的。›

知识点:

  1. background: linear-gradient 背景渐变属性
  2. clip-path: polygon 背景裁切属性
  3. 移动端ontouchstart,ontouchmove,ontouchend和Pc 端onmousedown,onmousemove,onmouseup

组件使用:

代码语言:javascript
复制
<template>
  <div class="body">
    <slider :planNum.sync="plan" :color="['#D6FF7F','#00B3CC']"></slider>
    <slider :planNum.sync="plan1" :color="['#ED7B84','#9055FF']"></slider>
    <slider :planNum.sync="plan2" :color="['#2F80ED']"></slider>
    <slider :planNum.sync="plan3"></slider>
  </div>
</template>

<script>
import slider from '../common/slider'
export default {
  components: {
    slider
  },
  data() {
    return {
      plan: 75,
      plan1: 45,
      plan2: 100,
      plan3: 88
    }
  },
  methods: {
  }
}
</script>

<style lang="scss" scoped>
.body {
  display: inline-block;
  margin: 50px auto;
}
</style>

组件封装:slider.vue

代码语言:javascript
复制
<template>
  <div class="plan_box" ref="wrapper">
    <div
      class="plan"
      :style="`clip-path: polygon(0 0,${plan}% 0,${plan}% 100%,0 100%);background: linear-gradient(to left, ${this.gradient});`"
    ></div>
    <div class="slider" ref="slider">
      <span class="text">{{planNum}}%</span>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    planNum: Number, //进度数值
    color: { //背景颜色,['#e233ff'] 为单色 ,['#e233ff', '#ff6b00']为渐变色
      type: Array,
      default: function() {
        return ['#e233ff', '#ff6b00']
      }
    }
  },
  computed: {
    plan: {
      get() {
        return this.planNum
      },
      set(val) {
        this.$emit('update:planNum', Number(val))
      }
    },
    gradient() {
      if (this.color.length > 1) {
        return this.color.join(',')
      } else {
        return `${this.color[0]},${this.color[0]}`
      }
    }
  },
  data() {
    return {
      //   plan: 55
    }
  },
  mounted() {
    this.init(this.$refs.wrapper)
  },
  methods: {
    //pc端鼠标拖动
    mouseDown(el) {
      var _this = this
      var $el = el
      var slider = _this.$refs.slider
      var rect = $el.getBoundingClientRect()
      if (_this.plan) {
        let plan = _this.plan
        slider.style.left = (plan / 100) * rect.width + 'px'
      }
      slider.onmousedown = function(event) {
        event.preventDefault()
        document.onmousemove = function(e) {
          var sliderX = e.clientX - rect.left
          if (sliderX < 0) {
            sliderX = 0
          } else if (sliderX > rect.width) {
            sliderX = rect.width
          }
          //   console.log(sliderX)
          //滑块的位置
          slider.style.left = sliderX + 'px'
          //进度条的长度
          _this.plan = ((sliderX / rect.width) * 100).toFixed(0)
        }
        document.onmouseup = function() {
          document.onmousemove = null
          document.onmousedown = null
        }
      }
    },
    touchStart(el) {
      var _this = this
      var $el = el
      var slider = _this.$refs.slider
      var rect = $el.getBoundingClientRect()
      if (_this.plan) {
        let plan = _this.plan
        slider.style.left = (plan / 100) * rect.width + 'px'
      }
      slider.ontouchstart = function(event) {
        event.preventDefault()
        document.ontouchmove = function(e) {
          var oEvent = e.touches[0]
          var sliderX = oEvent.clientX - rect.left
          if (sliderX < 0) {
             sliderX = 0
          } else if (sliderX > rect.width) {
            sliderX = rect.width
          }
          // console.log(sliderX)
          //滑块的位置
          slider.style.left = sliderX + 'px'
          //进度条的长度
          _this.plan = ((sliderX / rect.width) * 100).toFixed(0)
        }
        document.ontouchend = function() {
          document.ontouchmove = null
          document.ontouchstart = null
        }
      }
    },
    init(el) {
      // 判断是否为移动设备
      if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
        this.touchStart(el)
      } else {
        this.mouseDown(el)
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.plan_box {
  margin: 50px 0;
  height: 11px;
  width: 300px;
  // border: 1px solid black;
  background: #f1f1f1;
  box-sizing: border-box;
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 5px;
  .plan {
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0;
    // background: black;

    border-radius: 5px;
  }
  .slider {
    cursor: grab;
    position: absolute;
    left: 0px;
    &::before {
      content: '';
      display: block;
      width: 20px;
      height: 20px;
      border-radius: 50%;
      background: white;
      box-shadow: 2px 2px 4px #919191;
      position: absolute;
      left: -10px;
      top: -10px;
    }
    .text {
      font-size: 12px;
      position: absolute;
      display: inline-block;
      padding: 5px;
      border-radius: 3px;
      background: white;
      top: -45px;
      left: -20px;
      box-shadow: 2px 2px 4px #d3d3d3;
    }
  }
}
</style>
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 网罗开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档