vue 拖拽进度条滑动组件(一) 竖向滑动插件

progress.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)
  }
  

竖向滑动子组件代码myprogress.vue:

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

<script>
import { prefixStyle } from "./progress";
const progressBtnWidth = 16;
const transform = prefixStyle("transform");
export default {
  name: "HelloWorld",
  props:['heightRatio'],
  data() {
    return { };
  },
  created() {
    this.touch = {}; //创建一个touch对象
  },
  methods: {
    progressTouchStart(e) {
      //创建一个标志,意思它已经初始化完
      this.touch.initiated = true;
      //记录滚动条的位置
      if (this.touch.top > 0) {
        this.touch.startY = e.touches[0].pageY - this.touch.top;
      } else {
        this.touch.startY = e.touches[0].pageY;
      }
    },
    progressTouchMove(e) {
      //如果初始化完则什么都不做
      if (!this.touch.initiated) {
        return;
      }
      const deltaY = e.touches[0].pageY - this.touch.startY; //计算差值
      //max 的0  意思不能小于0 、、、、min,不能超过整个滚动条的宽度
      const offsetWidth = Math.min(
        this.$refs.progressBar.clientHeight,
        Math.max(0, deltaY)
      );
      //保存当前滚动条的位置
      this.touch.top = offsetWidth;
      // console.log('ddd',this.touch.top) 
      this._offset(offsetWidth);
      //滚动完后要给父组件派发一个事件
      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: {
    //它是不断改变的 监听父组件传入的值
    heightRatio(val){
      this.touch.top = this.heightRatio*this.$refs.progressBar.clientHeight;
      this._offset(this.heightRatio*this.$refs.progressBar.clientHeight)
    },
  }
};
</script>

<style lang='less' scoped>
.progress-bar {
  width: 10px;
  height: 330px;
  margin: 0 auto;
  .bar-inner {
    position: relative;
    /* bottom: 13px; */
    width: 10px;
    height: 330px;
    background: #dce0dc;
    border-radius: 10px;
    .progress {
      position: absolute;
      width: 100%;
      top: 0;
      background: #ffcd32;
      border-radius: 10px;
    }
    .progress-btn-wrapper {
      position: absolute;
      left: -10px;
      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>
    <div class="my-progress">
      <div class="content fl" ref="content">
        <div v-for="(item,index) in 30">{
   
   {index}}-我是内容我是内容我是内容我是内容我是</div>
      </div>
      <my-progress class="fl" @percentChange="percentChange" :heightRatio="nowScroll"></my-progress>
      
    </div>
  </div>
</template>

<script>
import MyProgress from "../components/progress/myprogress";

export default {
  data() {
    return {
      nowScroll:0
    };
  },

  components: {
    MyProgress
  },

  mounted() {
    window.addEventListener('scroll', this.handleScroll,true)
  },
  watch: {},

  methods: {
    handleScroll() {
      let scrollTop = this.$refs.content.scrollTop;
      let scrollHeight = this.$refs.content.scrollHeight; //内容总高度
      let clientHeight = this.$refs.content.clientHeight; //可见高度
      this.nowScroll = scrollTop/(scrollHeight-clientHeight);
    },
    percentChange(val) {
      console.log('djksjdk',val);
      let scrollHeight = this.$refs.content.scrollHeight; //内容总高度
      let clientHeight = this.$refs.content.clientHeight;
      var scrollH = val*(scrollHeight-clientHeight);
      this.$refs.content.scrollTop = scrollH;  
    }
  },

  computed: {}
}

</script>
<style lang='less' scoped>
.fl {
  float: left;
}
.fr {
  float: right;
}
.my-progress {
  height: 600px;
  margin: 3%;
  padding: 3%;
  box-sizing: border-box;
  overflow: hidden;
  .content {
    width: calc(~'100% - 10px');
    max-height: 330px;
    overflow: scroll;
  }
}
</style>

猜你喜欢

转载自blog.csdn.net/yuan_jlj/article/details/111450327