小程序自定义进度条

2,898 阅读2分钟

小程序video虽然有自己的进度条,可是样式不好自定义,大多情况下会选择用slider组件来实现进度条功能,但slider组件同样存在样式不好自定义的问题,这里介绍一个使用movable-area + movable-view实现进度条的方法。

  1. 首先是wxml

<movable-area  catchtouchmove="voidMethod" catchtap="tap"
class="progress-box" style="width:{{width}}px;height:10px">
<view class="bg-box">
  <view style="width:{{value}}%" class="inner"></view>
</view>
  <movable-view class="progress-dot" wx:if="{{showDot}}" x="{{value*width/100}}" bindtouchmove="touchmove" bindtouchend="touchend"  direction="horizontal" bindchange="getCgh">
    <view class="dot"></view>
  </movable-view>
</movable-area>

movable-area的catchtouchmove绑定一个空函数,内部的滑动不会影响到外部,设置宽度为容器宽度,高度10像素的区域。内部bg-box的区域为了已播放部分深色显示。

movable-view则是内部滑块区域,里面的view是滑块的可见部分(为什么要把可拖动范围设置大点:因为滑块太小要手指刚好触到可见滑块才能滑动,被领导要求了),通过wxss定义好样式

.progress-box{
  position: absolute;
  /* background: #232; */
}

.progress-dot{
  background: #ffffff00;
  width: 70px;
  height:40px;
   display: flex;
   justify-content: center;
   align-items: center;
   top: -15px;
   z-index: 10;
  left: -30px;
   
  
}
.dot{
  background: #ffffff;
  width: 8px;
  height:8px;
  border-radius: 100px;
}
.bg-box{
  position: absolute;
  width: 100%;
  height: 2px;
  top: 4px;
  background-color: #ffffff22;
}
.bg-box .inner{
  background:linear-gradient(to bottom,#ffffff,#666);
  height: 100%;
}

.dot才是滑块的真正可见部分,完成后的滑块大概这个样子

image.png

滑块的if属性是为了控制视频暂停时才显示滑块,视频播放时不显示滑块。

然后是关键的js部分。这里进度条是作为组件使用的,所以播放进度和是否暂停需要由父组件传入

  properties: {
    value:{
      type:Number,
      value:0,
      observer:function observe(){
        var newVal = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
        
        
      }
    },
    showDot:{
      type:Boolean,
      value:false
    }
  },

定义下data

data: {
    width: wx.getSystemInfoSync().windowWidth,
    currX:0,
    touch:false,
    timer:0
  },

这里需要注意一点,bindchange触发频率太高,没有状态,所以并不适合在bindchange中来控制视频进度,这里只在bindchange中记录进度条位置

//这是bindchange触发的函数
getCgh(e){
       
      let {x}=e.detail
      let {width}=this.data
      let pecent=x/width*100
      this.data.currX=pecent
      
    },

真正实现视频进度拖动的是touchmove

tap(e){//点击区域的某处直接跳到那个进度
      let {x}=e.detail
      let {width}=this.data
      let pecent=x/width*100
      this.data.currX=pecent
      this.triggerEvent('change',{value:pecent})

    },
    voidMethod(){
  
    },
  touchmove(e){
      this.triggerEvent('changing',{value: this.data.currX})
      // console.log(this.data.currX)
    },
    touchend(e){
      this.triggerEvent('change',{value: this.data.currX})


    },

先看下父组件如何调用的

<progress value="{{progress}}" bindchanging="showTime" showDot="{{isstop}}"  bindchange="changeProgress" ></progress>

value就是视频当前进度,showDot是视频是否播放, bindchanging就是拖动进度条,bindchange是拖动结束。 这里showTime是在拖动进度条过程中显示时长的函数,等拖动结束再触发视频的进度改变。

在进度条组件json中配置一下,然后在父组件的usingComponents中配置一下,就可以在父组件使用了

{
  "component": true,
  "usingComponents": {}
}