vue 拖拽进度条滑动组件 横向竖向滑动插件 - 愿你走过半生,归来任是少年。 - CSDN博客

[](http://creativecommons.org/licenses/by-sa/4.0/)版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/kingrome2017/article/details/95857640

dom.js

//是否有指定class存在
export function hasClass(el, className) {
    let reg = new RegExp('(^|\\s)' + className + '(\\s|$)')
    return reg.test(el.className)
  }
  //如果存在什么都不做,否则就设置添加
  export function addClass(el, className) {
    if (hasClass(el, className)) {
      return
    }
  
    let newClass = el.className.split(' ')
    newClass.push(className)
    el.className = newClass.join(' ')
  }
  
  export function getData(el, name, val) {
    const prefix = 'data-'
    if (val) {
      return el.setAttribute(prefix + name, val)
    }
    return el.getAttribute(prefix + name)
  }
  
  let elementStyle = document.createElement('div').style
  
  let vendor = (() => {
    let transformNames = {
      webkit: 'webkitTransform',
      Moz: 'MozTransform',
      O: 'OTransform',
      ms: 'msTransform',
      standard: 'transform'  //以上前缀都不满足,就用这个
    }
  
    for (let key in transformNames) {
      if (elementStyle[transformNames[key]] !== undefined) {
        return key
      }
    }
  
    return false
  })()
  
  export function prefixStyle(style) {
    if (vendor === false) {
      return false
    }
  
    if (vendor === 'standard') {
      return style
    }
  
    return vendor + style.charAt(0).toUpperCase() + style.substr(1)
  }
  

在这里插入图片描述

竖向拖拽滑动进度条插件

<template>
  <div class="hello">
    <div class="progress-bar" ref="progressBar" @click="progressClick">
      <div class="bar-inner">
        <!-- 背景 -->
        <div class="progress" ref="progress"></div>
        <!-- 小圆点 -->
        <div
          class="progress-btn-wrapper"
          ref="progressBtn"
          @touchstart.prevent="progressTouchStart"
          @touchmove.prevent="progressTouchMove"
          @touchend="progressTouchEnd"
        >
          <div class="progress-btn"></div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { prefixStyle } from "./dom";
const progressBtnWidth = 16;
const transform = prefixStyle("transform");
export default {
  name: "HelloWorld",
  data() {
    return {
      msg: ""
    };
  },
  created() {
    this.touch = {}; //创建一个touch对象
  },
  methods: {
    progressTouchStart(e) {
      //创建一个标志,意思它已经初始化完
      this.touch.initiated = true;
      //记录滚动条的位置
      if (this.touch.bottom > 0) {
        this.touch.startY = e.touches[0].pageY + this.touch.bottom;
      } else {
        this.touch.startY = e.touches[0].pageY;
      }
    },
    progressTouchMove(e) {
      //如果初始化完则什么都不做
      if (!this.touch.initiated) {
        return;
      }
      const deltaY = this.touch.startY - e.touches[0].pageY; //计算差值
      //max 的0  意思不能小于0 、、、、min,不能超过整个滚动条的宽度
      const offsetWidth = Math.min(
        this.$refs.progressBar.clientHeight,
        Math.max(0, deltaY)
      );
      //保存当前滚动条的位置
      this.touch.bottom = offsetWidth;
      this._offset(offsetWidth);
    },
    progressTouchEnd() {
      this.touch.initiated = false;
      //滚动完后要给父组件派发一个事件
      this._triggerPercent();
    },
    //点击改变歌曲播放进度
    progressClick(e) {
      const rect = this.$refs.progressBar.getBoundingClientRect(); //是一个获取距离的方法
      const offsetWidth = Math.min(
        rect.height,
        Math.max(0, rect.bottom - e.pageY)
      );
      this._offset(offsetWidth);
      // 这里当我们点击 progressBtn 的时候,e.offsetX 获取不对
      // this._offset(e.offsetX)
      this._triggerPercent();
    },
    _triggerPercent() {
      const barHeight = this.$refs.progressBar.clientHeight - progressBtnWidth;
      const percent = this.$refs.progress.clientHeight / barHeight;
      this.$emit("percentChange", percent);
    },
    //偏移方法
    _offset(offsetWidth) {
      this.$refs.progress.style.height = `${offsetWidth}px`; //获取进度条的位置,距离左右的距离
      this.$refs.progressBtn.style[
        transform
      ] = `translate3d(0,${-offsetWidth}px,0)`; //小球的偏移
    }
  },
  watch: {
    //它是不断改变的 监听父组件传入的值
    percent(newPercent) {
      //大于0 而且不是在拖动的状态下,拖动的时候不要改变
      if (newPercent >= 0 && !this.touch.initiated) {
        const barWidth = this.$refs.progressBar.clientHeight - progressBtnWidth; //进度条的总度 内容-按钮的宽度
        const offsetWidth = newPercent * barWidth; //应该偏移的宽度
        this._offset(offsetWidth);
      }
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.progress-bar {
  width: 10px;
  height: 200px;
  margin: 0 auto;
}

.bar-inner {
  position: relative;
  /* bottom: 13px; */
  width: 10px;
  height: 200px;
  background: green;
}

.progress {
  position: absolute;
  width: 100%;
  bottom: 0;
  background: #ffcd32;
}

.progress-btn-wrapper {
  position: absolute;
  /* left: -8px;
  top: -13px; */
  left: -10px;
  bottom: -13px;
  width: 30px;
  height: 30px;
}

.progress-btn {
  position: relative;
  top: 7px;
  left: 7px;
  box-sizing: border-box;
  width: 16px;
  height: 16px;
  border: 3px solid #333;
  border-radius: 50%;
  background: #ffcd32;
}
</style>

横向拖拽滑动进度条插件

<template>
  <div class="progress-bar" ref="progressBar" @click="progressClick">
    <div class="bar-inner">
      <!-- 背景 -->
      <div class="progress" ref="progress"></div>
      <!-- 小圆点 -->
      <div class="progress-btn-wrapper" ref="progressBtn"
           @touchstart.prevent="progressTouchStart"
           @touchmove.prevent="progressTouchMove"
           @touchend="progressTouchEnd"
      >
        <div class="progress-btn"></div>
      </div>
    </div>
  </div>
</template>

<script type="text/ecmascript-6">
  import {prefixStyle} from 'common/js/dom'

  const progressBtnWidth = 16
  const transform = prefixStyle('transform')

  export default {
    props: {
      percent: {
        type: Number,
        default: 0
      }
    },
    created() {
      this.touch = {}  //创建一个touch对象
    },
    methods: {
      progressTouchStart(e) {
        //创建一个标志,意思它已经初始化完
        this.touch.initiated = true
        //手指的位置
        this.touch.startX = e.touches[0].pageX
        //当前滚动,滚动条的位置
        this.touch.left = this.$refs.progress.clientWidth
      },
      progressTouchMove(e) {
        //如果初始化完则什么都不做
        if (!this.touch.initiated) {
          return
        }
        const deltaX = e.touches[0].pageX - this.touch.startX //计算差值 
        //max 的0  意思不能小于0 、、、、min,不能超过整个滚动条的宽度
        const offsetWidth = Math.min(this.$refs.progressBar.clientWidth - progressBtnWidth, Math.max(0, this.touch.left + deltaX)) 
        this._offset(offsetWidth)
      },
      progressTouchEnd() {
        this.touch.initiated = false
        //滚动完后要给父组件派发一个事件
        this._triggerPercent()
      },
      //点击改变歌曲播放进度
      progressClick(e) {
        const rect = this.$refs.progressBar.getBoundingClientRect() //是一个获取距离的方法
        const offsetWidth = e.pageX - rect.left
        this._offset(offsetWidth)
        // 这里当我们点击 progressBtn 的时候,e.offsetX 获取不对
        // this._offset(e.offsetX)
        this._triggerPercent()
      },
      _triggerPercent() {
        const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth
        const percent = this.$refs.progress.clientWidth / barWidth
        this.$emit('percentChange', percent)
      },
      //偏移方法
      _offset(offsetWidth) {
        this.$refs.progress.style.width = `${offsetWidth}px`  //获取进度条的位置,距离左右的距离
        this.$refs.progressBtn.style[transform] = `translate3d(${offsetWidth}px,0,0)`  //小球的偏移
      }
    },
    watch: {
      //它是不断改变的
      percent(newPercent) {
        //大于0 而且不是在拖动的状态下,拖动的时候不要改变
        if (newPercent >= 0 && !this.touch.initiated) {
          const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth  //进度条的总宽度 内容-按钮的宽度
          const offsetWidth = newPercent * barWidth //应该偏移的宽度
          this._offset(offsetWidth)
        }
      }
    }
  }
</script>

<style scoped lang="stylus" rel="stylesheet/stylus">
  @import "~common/stylus/variable"

  .progress-bar
    height: 30px
    .bar-inner
      position: relative
      top: 13px
      height: 4px
      background: rgba(0, 0, 0, 0.3)
      .progress
        position: absolute
        height: 100%
        background: $color-theme
      .progress-btn-wrapper
        position: absolute
        left: -8px
        top: -13px
        width: 30px
        height: 30px
        .progress-btn
          position: relative
          top: 7px
          left: 7px
          box-sizing: border-box
          width: 16px
          height: 16px
          border: 3px solid $color-text
          border-radius: 50%
          background: $color-theme
</style>

Original url: Access
Created at: 2019-09-24 21:42:14
Category: default
Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论