自定义时间滑块

1、前几个月产品给了同事个需求,模仿海康威视的摄像头监控模块;同事搞了三周搞不出来;没办法最后只有我亲自出马;废话不说了,
效果如下:
1、滑块个数不限制;
2、鼠标落下产生滑块;可以自由拖拽控制位置和长度;
3、滑块位置限制由前后滑块或时间条的极值确定(0:00 - 24:00)
(ps:因为好几个月了最近为了面试提高身价才勉为其难写的;服务器没开所以效果大概如下图;想看具体效果自己开个vue-element-admin 复制粘贴上去)
在入图片描述
在这里插入图片描述

父组件一周七天:
代码如下:

	<template>
  <el-container style="position: relative" id="container">
    <el-button icon="el-icon-delete" style="border-radius: 1px;margin-left: 65px" @click="reset()">重 置</el-button>


    <div style="width: 680px;height: 385px;position:absolute;top: 50px;-moz-user-select:none;" @mouseleave="close()">

      <div v-for="(item,index) in node" :key="index">
        <slider :node = "item"  :ref="item.ref" @mouseover.native="show(item)" @click.native = "mousedown(item)"></slider>

        <el-popover placement="left-end" width="300"  trigger="manual" v-model="item.showPopover">

          <span style="margin-right: 136px">复制到...</span>
          <el-checkbox  v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
          <div style="margin: 15px 0;width: 100%;border-bottom: 1px solid whitesmoke"></div>

          <el-checkbox-group v-model="checkList" @change="handleCheckedCitiesChange">
            <el-checkbox v-for="city in weekDay" :disabled="city == clickItem" :label="city" :key="city">{{city}}</el-checkbox>
          </el-checkbox-group>

          <div style="width: 100%;text-align: right">
            <el-button type="text" @click="copy(item)">确 定</el-button>
            <el-button type="text" style="margin-right: 50px;" @click="item.showPopover = false">取 消</el-button>
          </div>

          <el-button slot="reference"
                     type="text"
                     icon="el-icon-document-copy"
                     @mouseover.native="show(item)"
                     @click="changeCheck(item)"
                     v-show="item.showIcon"
                     style="display: inline-block;
                            cursor: pointer;
                            color: #0c8f7d;font-size: 17px;
                            position: absolute;
                            margin-left: 640px;
                            margin-top: -40px;">
          </el-button>
        </el-popover>


      </div>

    </div>

    <el-button style="position: absolute;top: 450px;left: 5px;
    border-radius: 1px;background: rgb(19, 168, 168);color: white" @click="preservation">应 用</el-button>

  </el-container>


</template>

<script>
import slider from '../components/slider'

import {mapActions, mapState} from "vuex";

const weekOptions = ['星期一', '星期二', '星期三', '星期四','星期五','星期六','星期日']

export default {
  props: {
    useDatas: {
      type: Object,
      default: {}
    },
  },


  data(){
    return {
      visible:false,

      checkList: [],

      checkAll: false,

      clickItem:'',

      weekDay : weekOptions,

      node:[],

      initParams:{}

    }
  },

  methods:{
    ...mapActions(['getAppID']),

    async getTime(){
      const vm = this
      let query = {cameraId:vm.cameraID,appId:vm.appID}
      let res = await this.$api.getAdvancedSettingFn(query)
      if (res.status != '200') return this.$message.error('请求数据失败')
      vm.initParams = res.data



      this.node[0].timeData = this.initParams.mondayList
      this.node[1].timeData = this.initParams.tuesdayList
      this.node[2].timeData = this.initParams.wednesdayList
      this.node[3].timeData = this.initParams.thursdayList
      this.node[4].timeData = this.initParams.fridayList
      this.node[5].timeData = this.initParams.saturdayList
      this.node[6].timeData = this.initParams.sundayList

      setTimeout(()=>{
        this.node.forEach(item=> {
          vm.$refs[item.ref][0].initSlider()
        })
      })
      console.log(res.data)
    },


    preservation(){
      const vm = this
      let deploymentTimeList = []

      this.node.forEach(item => {
        let timeArr = this.$refs[item.ref][0].getTimeArr()
        deploymentTimeList.push({
          timeArr:timeArr,
          week:item.week
        })
      })
   if(((vm.useDatas.testTimeUnit=='s'||vm.useDatas.testTimeUnit=='m')&&vm.useDatas.testTime<=60)||((vm.useDatas.testTimeUnit=='h')&&vm.useDatas.testTime<=24)){
        let isOpen = this.useDatas.isOpen1?'1':'0'
      if (this.useDatas.testTime == "0"||this.useDatas.testTime == "") return this.$message.error('时间间隔不为空或零')
    //  if (this.useDatas.testTime == "") return this.$message.error('时间间隔不为空或零')

      let query = {
        cameraId : this.cameraID,
        appId:this.useDatas.appId,
        testTime:this.useDatas.testTime,
        testTimeUnit:this.useDatas.testTimeUnit,
        isOpen:isOpen,
        deploymentTimeList: deploymentTimeList
      }

      this.$api.setAdvancedSettingFn(query).then(res=>{
        if (res.status!== "200") return 
        this.$message.success('应用成功')
      })
   }
   else{
         vm.$message.error('秒数和分钟不能超过60,小时不能超过24')   
              }
    mousedown(item){

      this.node.forEach(item1 => {

        if (item != item1) {
          this.$refs[item1.ref][0].closeTime()
        }

      })
    },

    //重置
    reset(){
      this.node.forEach(item=>{
        item.timeData.length=0
        this.$refs[item.ref][0].initSlider()
      })
    },


    //复制
    copy(item){


      let timeData = this.$refs[item.ref][0].getTimeArr()


      this.node.forEach(item1 => {
        if(this.checkList.indexOf(item1.weekday)!=-1&&item1!==item){
          item1.timeData.length = 0
          item1.timeData = timeData
          this.$refs[item1.ref][0].initSlider()
        }
        item1.showPopover = false
      })


    },

    // 选择框
    changeCheck(item){
      this.checkList = []
      this.checkList.push(item.weekday)
      this.checkAll = false
      this.clickItem = item.weekday

      this.node.forEach(item1=>item1 == item ? item1.showPopover = !item1.showPopover : item1.showPopover = false)

    },


    handleCheckAllChange(val) {
      let array = []
      array.push(this.clickItem)
      this.checkList = val ? weekOptions : array;
    },
    handleCheckedCitiesChange(value) {
      let checkedCount = value.length;
      this.checkAll = checkedCount === this.weekDay.length;
    },



    show(data){
      this.node.forEach(item => item.showIcon = item === data)
    },

    close(){
      this.node.forEach(item => item.showIcon = false)
    },

  },

  computed: {
    ...mapState(['cameraID','appID','settingObj']),
  },

  watch:{
    appID: {
      handler:function (val){
        if (val) {
          this.getTime()
        }
      },
      immediate: true
    },
    "useDatas.appId": {
      handler: function(newVal, oldVal) {
        if(newVal!=''){
          console.log('newVal',newVal,this.appID);
          var vm=this
          vm.pointArr = [];
          vm.showDatas=[];
          vm.oIndex = -1;
          vm.crossDatas=[];
          vm.initCrossDatas=[];
          vm.useDatas.areaList=[]
          vm.flag=true
        }

      },
      deep: true,
      immediate: true
    },
  },

  components:{
    slider
  },
  beforeCreate() {

  },
  created() {
    console.log(this.useDatas)
    console.log(this.settingObj)

    for (let i=1;i<=7;i++){
      this.node.push({
        grandfather: 'grandfather' + i,
        father: 'father' + i,
        timeTip: 'timeTip' + i,
        leftToolTip: 'leftToolTip' + i,
        rightToolTip: 'rightToolTip' + i,
        centerTip: 'centerTip' + i,
        showIcon:false,
        showPopover:false,
        ref:'ref'+i
      })
    }
    this.node[0].weekday = '星期一'
    this.node[0].week = 'Monday'

    this.node[1].weekday = '星期二'
    this.node[1].week = 'Tuesday'

    this.node[2].weekday = '星期三'
    this.node[2].week = 'Wednesday'

    this.node[3].weekday = '星期四'
    this.node[3].week = 'Thursday'

    this.node[4].weekday = '星期五'
    this.node[4].week = 'Friday'


    this.node[5].weekday = '星期六'
    this.node[5].week = 'Saturday'

    this.node[6].weekday = '星期日'
    this.node[6].week = 'Sunday'

  },
  mounted() {
    this.getTime()
  }
}
</script>

<style lang="less">
  .el-container{
  -webkit-user-select: none!important;
  -moz-user-select: none!important;
  -ms-user-select: none!important;
  user-select: none!important;
}
</style>

单个子组件代码如下:

<template>
  <div style="width: 650px;height: 45px;padding:10px 0 0 50px;position: relative"  :id= node.grandfather>
    <span style="position: absolute;top: 25px;left: 0;display: inline-block;margin-right: 20px">{{node.weekday}}</span>
    <div class="sliderClass1">

      <div :id= node.father class="sliderClass2"></div>

      <!--上方可编辑滑块-->
      <div :id= node.timeTip class="timeTip" style="top: -50px; display: none;">
        <div class="top"></div>

        <div  class="middle">

          <div style="padding-top: 5px;">
            <input type="text" class="txt"  maxlength="2" onpaste="return false" v-model="leftHour"
                   onblur="this.value=this.value.replace(/[^0-9]/g,'')"
                   oninput="value = value<=24 ? value :'00'">
            :
            <input type="text" class="txt" maxlength="2" onpaste="return false" v-model="leftMinute"
                   onblur="this.value=this.value.replace(/[^0-9]/g,'')"
                   :disabled="check1"
                   oninput="value = value<=60 ? value:'00'"
            >
            -
            <input type="text" class="txt" maxlength="2" onpaste="return false" v-model="rightHour"
                   onblur="this.value=this.value.replace(/[^0-9]/g,'')"
                   oninput="value = value<= 24? value :'00'">
            :
            <input type="text" class="txt" maxlength="2"  :disabled="check2"
                   onpaste="return false" v-model="rightMinute" oninput="value = value <= 60 ? value :'00'">
          </div>

          <div style="padding: 5px 0;">
            <span class="ctrl" @click="deleteElement">删除</span> | <span class="ctrl" @click="changeElement">保存</span>
          </div>

          <span class="close" @click="closeTime"></span>

        </div>

        <div class="bottom"></div>
      </div>

      <!--滑动时左方出现的滑块-->
      <div style="position: absolute;top: 0;z-index: 2020;display: none" :id = node.leftToolTip>
        <div style="background: black;width: 48px;height: 18px;padding-left: 13px">
          <span style="color: white;">{{leftTime}}</span>

        </div>
        <div style="
            position: absolute;
            left: 21px;
            width:0px;
            height:0px;
            border: 5px transparent solid;
            border-top-color: black;">
        </div>
      </div>

      <!--滑动时右边出现的滑块-->
      <div style="position: absolute;top: 0;z-index: 2021;display: none" :id= node.rightToolTip>
        <div style="background: black;width: 48px;height: 18px;padding-left: 13px">
          <span style="color: white">{{rightTime}}</span>
        </div>
        <div style="
            position: absolute;
            left: 21px;
            width:0px;
            height:0px;
            border: 5px transparent solid;
            border-top-color: black;">
        </div>
      </div>

      <!--鼠标悬浮时出现的tooltip-->
      <div style="position: absolute;top: 0;z-index: 2021;display: none" :id= node.centerTip>
        <div style="background: black;width: 80px;height: 20px;border: black solid 1px;padding-left: 13px">
          <span style="color: white">{{centerTime}}</span>
        </div>
        <div style="
            position: absolute;
            left: 37px;
            width:0;
            height:0;
            border: 5px transparent solid;
            border-top-color: #122b40;">
        </div>
      </div>



    </div>

  </div>
</template>

<script>
export default {
  props: {
    node: {
      weekday:'',
      grandfather:'',
      father:'',
      timeTip:'',
      leftToolTip:'',
      rightToolTip:'',
      centerTip:'',
      timeData:''
    }
  },

  data(){
    return {

      // 添加滑块
      addElement: false,

      // 左右时间
      leftTime:0,
      rightTime:0,

      //中间事件
      centerTime: '00:00-00:00',

      // 滑块
      element: '',

      // 滑块左极限
      leftLimit: 0,

      // 滑块右边极限
      rightLimit: 0,

      // 是否滑动
      eleSlider: false,

      // 用户点击滑块的鼠标落下的位置距离远点距离
      downPosition: 0,

      sliderLeft:0,

      sliderWidth:0,

      // 滑块左边拉伸或者缩短
      stretchingLeft:false,

      // 滑块右边拉伸或缩短
      stretchingRight:false,

      // 时间
      leftHour:0,
      leftMinute:0,

      rightHour:0,
      rightMinute:0

    }
  },

  methods:{
    getOffsetLeft(obj){
      let tmp = obj.offsetLeft;
      let val = obj.offsetParent;
      while(val != null){
        tmp += val.offsetLeft;
        val = val.offsetParent;
      }
      return tmp;
    },


    // 初始化滑块
    initSlider(){
      const vm = this
      let father = document.getElementById(vm.node.father)
      while (father.hasChildNodes()){
        father.removeChild(father.firstChild)
      }
      if (vm.node.timeData!=undefined){
        vm.node.timeData.forEach( item => {
          let son = document.createElement('div')
          son.className = 'sonClass'
          let left = (Number(item.startTime.split(':')[0]) +  Number(item.startTime.split(':')[1])/60)*24
          let right =  (Number(item.endTime.split(':')[0]) +  Number(item.endTime.split(':')[1])/60)*24
          son.style.left = left + 'px'
          son.style.width = right-left + 'px'

          son.addEventListener('mousedown',function (e){
            e.stopPropagation()
          })

          // 创建滑块左边子元素
          son.appendChild(vm.createLeftGrandson())

          // 创建滑块右边子元素
          son.appendChild(vm.createRightGrandson())

          // 添加监听事件
          vm.addListener(son)



          father.appendChild(son)
        })
      }

    },

    // 父亲节点鼠标点击创建儿子元素
    down(e){
      const vm = this

      // 创建儿子滑块元素
      const son = document.createElement('div')

      son.className = 'sonClass'


      let paddingLeft = Number(document.getElementById(this.node.grandfather).style.paddingLeft.split('px')[0])

      let leftMargin = vm.getOffsetLeft(document.getElementById(vm.node.grandfather))
      son.style.left = e.x - paddingLeft - leftMargin + 'px'

      // 创建滑块左边子元素
      son.appendChild(vm.createLeftGrandson())

      // 创建滑块右边子元素
      son.appendChild(vm.createRightGrandson())

      // 给滑块添加监听事件
      vm.addListener(son)


      vm.addElement = true

      vm.element = son

      const father = document.getElementById(this.node.father)

      // 节点排序
      let childArr = Array.from(father.childNodes)

      let index  = childArr.findIndex(item =>{
        return Number(item.style.left.split('px')[0]) > Number(vm.element.style.left.split('px')[0])
      })
      let item = father.childNodes[index]

      index !== -1 ?  father.insertBefore(vm.element, item) : father.appendChild(vm.element)

      // 排序后的节点
      let childArr2 = Array.from(father.childNodes)

      let index2 = childArr2.findIndex(item=> item == vm.element)

      // 左右极限
      if (index2 == 0){
        vm.leftLimit = 0
        vm.rightLimit = childArr2.length>1 ?  Number(father.childNodes[index2+1].style.left.split('px')[0]) - 2 :576
      }
      else {
        vm.leftLimit = Number(father.childNodes[index2-1].style.left.split('px')[0]) + Number(father.childNodes[index2-1].style.width.split('px')[0]) + 2
        vm.rightLimit = index2!== childArr2.length -1 ? Number(father.childNodes[index2+1].style.left.split('px')[0]) - 2 :576
      }
    },

    // 给儿子滑块增加各种监听事件
    addListener(son){
      const vm = this
      const paddingLeft = Number(document.getElementById(this.node.grandfather).style.paddingLeft.split('px')[0])

      // 添加滑块鼠标落下监听事件
      son.addEventListener('mousedown',function (e){

        let father = document.getElementById(vm.node.father)


        vm.moveIndex = Array.from(father.childNodes).findIndex(item => item==son )


        vm.sliderDown(e)


        e.stopPropagation()
      })

      //  点击展示时间
      son.addEventListener('mousedown',function (e){
        let father = document.getElementById(vm.node.father)
        father.childNodes.forEach((item,index)=>{
          if (index == vm.moveIndex ){
            item.childNodes.forEach(item2 => item2.style.display = 'block')

            vm.showTime()

          }
          else {
            item.childNodes.forEach(item2 => item2.style.display = 'none')
          }
        })

        e.stopPropagation()
      })

      // 鼠标悬浮
      son.addEventListener('mouseover',function (e){
        if(!vm.addElement){

          let left = Number(son.style.left.split('px')[0])
          let width = Number(son.style.width.split('px')[0])

          let leftTime = vm.getTime(left)
          let rightTime = vm.getTime(left+width)
          vm.centerTime = leftTime + '-' + rightTime

          document.getElementById(vm.node.centerTip).style.left = left + width/2 + paddingLeft -40 + 15 +'px'
          document.getElementById(vm.node.centerTip).style.display = 'block'
          e.stopPropagation()
        }
      })

      //鼠标离开
      son.addEventListener('mouseout',function (e){
        vm.closeCenterTip()
        e.stopPropagation()
      })

    },

    // 创建滑块左边孙子元素
    createLeftGrandson(){
      const vm = this
      const grandson1 = document.createElement('div')
      grandson1.className = 'grandson1Class'

      grandson1.addEventListener('click',function (e){
        e.stopPropagation()
      })

      grandson1.addEventListener('mouseover',function (e){
        e.stopPropagation()
      })

      grandson1.addEventListener('mouseout',function (e){
        e.stopPropagation()
      })

      grandson1.addEventListener('mousedown',function (e){


        vm.stretchingLeft = true
        vm.showTime()
        e.stopPropagation()
      })

      return grandson1
    },

    // 创建滑块右边孙子元素
    createRightGrandson(){
      const vm = this
      const grandson2 = document.createElement('div')

      grandson2.className = 'grandson2Class'

      grandson2.addEventListener('mousedown',function (e){
        vm.stretchingRight = true

        vm.showTime()

        e.stopPropagation()
      })

      grandson2.addEventListener('mouseover',function (e){
        e.stopPropagation()
      })

      grandson2.addEventListener('mouseout',function (e){
        e.stopPropagation()
      })

      return grandson2
    },

    //爷爷节点鼠标滑动控制儿子滑块的大小
    move(e){
      const vm = this
      if (vm.addElement){

        let paddingLeft = Number(document.getElementById(this.node.grandfather).style.paddingLeft.split('px')[0])

        let leftMargin = vm.getOffsetLeft(document.getElementById(vm.node.grandfather))
        let ex = e.x - paddingLeft - leftMargin

        // 滑块左边到原点的距离
        let left = Number(vm.element.style.left.split('px')[0])
        let width =  ex > vm.rightLimit ? vm.rightLimit -left : ex - left

        vm.element.style.width = width + 'px'

        let leftToolTip = document.getElementById(vm.node.leftToolTip)
        vm.leftTime = vm.getTime(left)
        leftToolTip.style.display = 'block'
        leftToolTip.style.left = left + paddingLeft - 24 + 15 + 'px'

        let rightToolTip = document.getElementById(vm.node.rightToolTip)
        vm.rightTime = width > 0 ? vm.getTime(left + width) : vm.getTime(left)
        rightToolTip.style.display = 'block'
        rightToolTip.style.left = left + paddingLeft + width - 24 + 15 +'px'


      }
      e.stopPropagation()
    },

    //爷爷节点鼠标弹起结束儿子滑块的创建
    up(e){
      if (this.addElement) {
        const vm = this

        let width = vm.element.style.width

        let father = document.getElementById(this.node.father)

        if (width == ''||width=='0px'){
          father.removeChild(vm.element)
        }
        vm.closeToolTip()
        vm.addElement = false
      }
      e.stopPropagation()
    },

    // 点击滑块鼠标落下记录位置
    sliderDown(e){

      const vm = this
      const father  = document.getElementById(this.node.father)

      const element = document.getElementById(this.node.father).childNodes[this.moveIndex]

      this.eleSlider = true
      this.downPosition = e.x - Number(document.getElementById(this.node.grandfather).style.paddingLeft.split('px')[0]) + 15
      this.sliderLeft = Number(element.style.left.split('px')[0])
      this.sliderWidth = Number(element.style.width.split('px')[0])

      // 排序后的节点

      let childArr2 = Array.from(father.childNodes)
      let index2 = this.moveIndex

      if (index2 == 0){
        vm.leftLimit = 0
        vm.rightLimit = childArr2.length>1 ?  Number(father.childNodes[index2+1].style.left.split('px')[0]) - 2 :576
      }
      else {
        vm.leftLimit = Number(father.childNodes[index2-1].style.left.split('px')[0]) + Number(father.childNodes[index2-1].style.width.split('px')[0]) + 2
        vm.rightLimit = index2!== childArr2.length -1 ? Number(father.childNodes[index2+1].style.left.split('px')[0]) - 2 :576
      }


    },

    // 移动鼠标控制滑块滑动
    sliderMove(e){

      if (this.eleSlider){

        const vm = this

        vm.closeTime()

        const element = document.getElementById(this.node.father).childNodes[vm.moveIndex]

        // 鼠标滑动时距离远点落下的距离
        let ex = e.x - Number(document.getElementById(this.node.grandfather).style.paddingLeft.split('px')[0])
        let distance = ex - vm.downPosition

        // 向左滑动
        if (distance < 0){
          element.style.left = Math.abs(distance) > vm.sliderLeft - vm.leftLimit ?  vm.leftLimit + 'px' : vm.sliderLeft + distance + 'px'
        }
        // 向右滑动
        else {
          element.style.left = distance > vm.rightLimit -  vm.sliderLeft - vm.sliderWidth ? vm.rightLimit - vm.sliderWidth + ' px': vm.sliderLeft + distance + 'px'
        }
        vm.showToolTip()
        vm.closeCenterTip()
      }
      e.stopPropagation()

    },

    // 鼠标弹起 滑块滑动结束
    sliderUp(){
      const vm = this
      if (vm.eleSlider){
        vm.eleSlider = false

        vm.sliderLeft = Number(document.getElementById(this.node.father).childNodes[vm.moveIndex].style.left.split('px')[0])
        vm.sliderWidth = Number(document.getElementById(this.node.father).childNodes[vm.moveIndex].style.width.split('px')[0])

        vm.closeToolTip()

      }

    },

    // 鼠标滑动拉伸滑块(左边)
    leftStretching(e){

      const vm = this
      if (vm.stretchingLeft){
        let leftMargin = vm.getOffsetLeft(document.getElementById(vm.node.grandfather))

        let ex = e.x -Number(document.getElementById(this.node.grandfather).style.paddingLeft.split('px')[0]) - leftMargin

        let father = document.getElementById(this.node.father)

        father.childNodes.forEach((item,index) => {

          if (index == vm.moveIndex){

            // 鼠标向左滑动拉伸
            if (ex < vm.sliderLeft){
              ex = ex <= vm.leftLimit? vm.leftLimit : ex
              item.style.left =  ex +'px'
              item.style.width = vm.sliderWidth +  vm.sliderLeft - ex + 'px'
            }

            //鼠标向右滑动缩小
            else {
              ex = ex >= vm.sliderLeft + vm.sliderWidth - 4 ? vm.sliderLeft + vm.sliderWidth - 4 : ex
              item.style.left = ex +'px'
              item.style.width = vm.sliderWidth +  vm.sliderLeft - ex + 'px'
            }


          }
        })

        vm.closeTime()

        vm.closeCenterTip()

        vm.showToolTip()

      }

      e.stopPropagation()
    },

    // 鼠标弹起结束拉伸滑块
    endLeftStretching(e){
      const vm = this

      if (vm.stretchingLeft || vm.stretchingRight) {

        vm.stretchingLeft = false
        vm.stretchingRight = false
        let item  = document.getElementById(this.node.father).childNodes[vm.moveIndex]


        vm.sliderLeft = Number(item.style.left.split('px')[0])
        vm.sliderWidth =  Number(item.style.width.split('px')[0])

        vm.closeToolTip()
        vm.closeCenterTip()
      }

    },

    // 鼠标滑动拉伸滑块(右边)
    rightStretching(e){
      const vm = this
      if (vm.stretchingRight){
        let leftMargin = vm.getOffsetLeft(document.getElementById(vm.node.grandfather))

        let ex = e.x - Number(document.getElementById(this.node.grandfather).style.paddingLeft.split('px')[0]) - leftMargin
        let father = document.getElementById(this.node.father)
        father.childNodes.forEach((item,index)=>{
          if (index == vm.moveIndex) {

            item.style.left = vm.sliderLeft + 'px'

            // 鼠标向右滑动拉伸滑块
            if (ex > vm.sliderLeft+vm.sliderWidth){
              ex =  ex > vm.rightLimit ? vm.rightLimit : ex
              item.style.width = ex - vm.sliderLeft + 'px'
            }

            // 鼠标向左缩小滑块
            else {
              ex = ex < vm.sliderLeft + 4 ? vm.sliderLeft + 4 : ex
              item.style.width = ex - vm.sliderLeft + 'px'
            }

          }
        })
        vm.closeTime()
        vm.closeCenterTip()
        vm.showToolTip()
      }


      e.stopPropagation()
    },

    // 关闭tooltip(鼠标移动时候的tooltip)
    closeToolTip(){
      document.getElementById(this.node.leftToolTip).style.display = "none"
      document.getElementById(this.node.rightToolTip).style.display = "none"
    },

    // 展示tooltip
    showToolTip(){
      let element = document.getElementById(this.node.father).childNodes[this.moveIndex]
      let paddingLeft = Number(document.getElementById(this.node.grandfather).style.paddingLeft.split('px')[0])

      let left = Number(element.style.left.split('px')[0])
      let width = Number(element.style.width.split('px')[0])

      this.leftTime = this.getTime(left)
      document.getElementById(this.node.leftToolTip).style.display = "block"
      document.getElementById(this.node.leftToolTip).style.left = left + paddingLeft - 24 + 15 + 'px'

      this.rightTime = this.getTime(left+width)
      document.getElementById(this.node.rightToolTip).style.display = "block"
      document.getElementById(this.node.rightToolTip).style.left = left + paddingLeft + width - 24 + 15 + 'px'

    },

    //关闭中间tooltip
    closeCenterTip(){
      document.getElementById(this.node.centerTip).style.display = 'none'
    },


    // 点击展示滑块上方可编辑tooltip
    showTime(){
      const vm = this
      vm.closeCenterTip()
      let tip  = document.getElementById(vm.node.timeTip)
      let paddingLeft = Number(document.getElementById(this.node.grandfather).style.paddingLeft.split('px')[0])

      let item = document.getElementById(this.node.father).childNodes[vm.moveIndex]

      let width = Number(item.style.width.split('px')[0])

      let left = Number(item.style.left.split('px')[0])

      vm.leftHour = vm.getTime(left).split(':')[0]
      vm.leftMinute = vm.getTime(left).split(':')[1]

      vm.rightHour = vm.getTime(left+width).split(':')[0]
      vm.rightMinute = vm.getTime(left+width).split(':')[1]

      tip.style.display = 'block'

      tip.style.left = (width/2 + left + paddingLeft - 92 + 15) +'px'

    },

    // 关闭tooltip
    closeTime(){
      document.getElementById(this.node.timeTip).style.display = 'none'
    },

    // 改变大小
    changeElement(){
      let father = document.getElementById(this.node.father)
      let left = (Number(this.leftHour) + Number(this.leftMinute)/60)*24
      let right = (Number(this.rightHour) + Number(this.rightMinute/60))*24

      let width = right -left

      if (right>this.rightLimit || left< this.leftLimit) return this.$message.error('超出范围,请从新填写(两次抓图计划时间间隔最低五分钟)!')
      if (width < 2) return this.$message.error('结束时间不得小于起始时间,且时间间隔不能小于5分钟!')

      father.childNodes[this.moveIndex].style.left = left + 'px'
      father.childNodes[this.moveIndex].style.width = width + 'px'
      this.closeTime()

    },


    // 删除元素
    deleteElement(){

      let father =  document.getElementById(this.node.father)

      father.removeChild(father.childNodes[this.moveIndex])
      this.closeTime()
    },

    //计算时间
    getTime(x){
      let hour = Math.floor(x/24)
      let minute = Math.round((x-hour*24)/24*60)
      if (hour < 10 ){
        hour = '0' + hour
      }
      if (minute < 10){
        minute = '0' + minute
      }
      return hour + ':' + minute
    },

    //计算所有的时间
    getTimeArr(){
      let array = []

      let father = document.getElementById(this.node.father)

      father.childNodes.forEach(item => {
        let left = Number(item.style.left.split('px')[0])
        let width = Number(item.style.width.split('px')[0])
        array.push({
          startTime : this.getTime(left),
          endTime : this.getTime(left+width)
        })
      })

      return array

    },


  },

  mounted() {
    const vm = this
    let getOffsetLeft = function(obj){
      let tmp = obj.offsetLeft;
      let val = obj.offsetParent;
      while(val != null){
        tmp += val.offsetLeft;
        val = val.offsetParent;
      }
      return tmp;
    }
    /*vm.leftMargin = getOffsetLeft(document.getElementById(vm.node.grandfather))*/
   /* window.οnresize= function(){
      vm.leftMargin = getOffsetLeft(document.getElementById(vm.node.grandfather))
      console.log(vm.leftMargin)
    }*/


    vm.initSlider()

    const father = document.getElementById(this.node.father)

    const app = document.getElementsByTagName('body')[0]

    // 父节点鼠标落下创建元素
    father.addEventListener('mousedown',function (e) {
      vm.down(e)
      let event = e || window.event
      event.stopPropagation()
    })

    // 祖父节点鼠标移动控制滑块大小 或 滑块移动
    app.addEventListener('mousemove',function (e){
      // 控制滑块创建大小
      vm.move(e)

      // 滑块左右拉伸
      vm.leftStretching(e)
      vm.rightStretching(e)

      //滑块滑动
      vm.sliderMove(e)

      let event = e || window.event
      event.stopPropagation()
    })

    // 祖父节点鼠标弹起结束创建滑块 或 滑块移动
    app.addEventListener('mouseup',function (e){

      vm.up(e)
      vm.sliderUp(e)
      vm.endLeftStretching()

      let event = e || window.event
      event.stopPropagation()
    })



  },

  computed:{

    // 监听两个小时输入框
    check1(){
      return this.leftHour == 24
    },
    check2(){
      return this.rightHour == 24
    }


  },

}
</script>

<style lang="less">
.sliderClass1{
  margin-left: 15px;
  padding: 0;
  float: left;
  width: 582px;
  height: 34px;
  background: url(../../../../assets/timeplan.png) 0 50% no-repeat;
  -moz-user-select:none;
  -webkit-user-select:none;
  -ms-user-select:none;
  -khtml-user-select:none;
  -o-user-select:none;
  user-select:none;
}
.sliderClass2{
  margin: 17px 0 0 0;
  padding: 0;
  left: 2px;
  position: relative;
  width: 576px;
  height: 16px;
}
.sonClass{
  margin: 0;
  padding: 0;
  position: absolute;
  height: 16px;
  background: rgb(99, 125, 236);
  box-sizing: border-box;
}
.grandson1Class{
  margin: 0;
  padding: 0;
  position: absolute;
  top: -1px;
  width: 5px;
  height: 16px;
  background: url(../../../../assets/timeplan-icons.png) -184px -3px no-repeat;
  left: -3px;
  cursor: w-resize;
  display: none;

}
.grandson2Class{
  margin: 0;
  padding: 0;
  position: absolute;
  top: -1px;
  width: 5px;
  height: 16px;
  background: url(../../../../assets/timeplan-icons.png) -184px -3px no-repeat;
  right: -3px;
  cursor: e-resize;
  display: none;
}

.grandson3Class{
  margin: 0;
  padding: 0;
  position: absolute;
  width: 184px;
  text-align: center;
  z-index: 9999;
  left: 238px;
  top: -40px;
  display: block;
}

.timeTip{
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
  visibility: visible;
  margin: 0;
  padding: 0;
  position: absolute;
  width: 184px;
  text-align: center;
  z-index: 9999;
  top: -40px;
  display: block;

  .top{
    font-family: Arial, Helvetica, sans-serif;
    font-size: 12px;
    visibility: visible;
    text-align: center;
    margin: 0;
    padding: 0;
    width: 182px;
    height: 15px;
    border: 1px solid #DDDDDD;
    border-bottom: 0;
    border-top-left-radius: 2px;
    border-top-right-radius: 2px;
    background-color: #FFFFFF;
  }

  .middle{
    font-family: Arial, Helvetica, sans-serif;
    font-size: 12px;
    visibility: visible;
    text-align: center;
    margin: 0;
    padding: 0;
    width: 182px;
    border: 1px solid #DDDDDD;
    border-top: 0;
    border-bottom: 0;
    background-color: #FFFFFF;
    .txt{
      visibility: visible;
      margin: 0;
      padding: 0;
      width: 25px;
    }
    .numrule{
      /deep/.el-input__inner{
        padding: 0 10px;
      }
    }
    /deep/.numrule input::-webkit-outer-spin-button,
    /deep/.numrule input::-webkit-inner-spin-button {
      -webkit-appearance: none!important;
    }
    /deep/.numrule input[type="number"]{
      -moz-appearance: textfield;
    }
    .ctrl {
      font-family: Arial, Helvetica, sans-serif;
      font-size: 12px;
      visibility: visible;
      text-align: center;
      margin: 0;
      padding: 0;
      color: #2f47ff;
      cursor: pointer;
    }
  }

  .bottom{
    font-family: Arial, Helvetica, sans-serif;
    font-size: 12px;
    visibility: visible;
    text-align: center;
    margin: 0;
    padding: 0;
    width: 184px;
    height: 12px;
    background: url(../../../../assets/timeplan-icons.png) -3px -30px no-repeat;

  }

  .close {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 12px;
    visibility: visible;
    text-align: center;
    margin: 0;
    padding: 0;
    position: absolute;
    top: 5px;
    right: 5px;
    width: 10px;
    height: 10px;
    background: url(../../../../assets/timeplan-icons.png) -55px -10px no-repeat;
    cursor: pointer;
  }
</style>

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您可以通过使用 AVPlayer 和 AVPlayerLayer 类来实现视频监控进度条和视频回放页面时间自定义滑块。下面是一个示例代码片段,演示如何实现: 1.创建一个 AVPlayerLayer,将其添加到您的视图层次结构中,并将其绑定到 AVPlayer。 ``` // 创建 AVPlayer AVPlayer *player = [AVPlayer playerWithURL:[NSURL URLWithString:@"yourVideoURL"]]; [player play]; // 创建 AVPlayerLayer AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; playerLayer.frame = self.view.bounds; [self.view.layer addSublayer:playerLayer]; ``` 2.创建一个 UISlider,并在滑动滑块时更新 AVPlayer 的当前时间。 ``` // 创建 UISlider UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(50, 400, 300, 20)]; [slider addTarget:self action:@selector(handleSlider:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:slider]; // 滑动滑块处理程序 - (void)handleSlider:(UISlider *)slider { CMTime videoDuration = player.currentItem.duration; double videoDurationSeconds = CMTimeGetSeconds(videoDuration); double newTime = videoDurationSeconds * slider.value; CMTime time = CMTimeMakeWithSeconds(newTime, player.currentTime.timescale); [player seekToTime:time]; } ``` 3.创建一个自定义滑块,并在拖动滑块时更新视频回放页面的时间轴。 ``` // 创建自定义滑块 UIImageView *thumbImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; thumbImageView.image = [UIImage imageNamed:@"yourImage"]; [slider setThumbImage:[UIImage new] forState:UIControlStateNormal]; [slider addSubview:thumbImageView]; // 拖动滑块处理程序 - (void)handlePan:(UIPanGestureRecognizer *)gesture { if (gesture.state == UIGestureRecognizerStateChanged) { CGPoint translation = [gesture translationInView:self.view]; CGPoint newCenter = CGPointMake(slider.thumbCenter.x + translation.x, slider.thumbCenter.y); if (newCenter.x > slider.frame.size.width) { newCenter.x = slider.frame.size.width; } else if (newCenter.x < 0) { newCenter.x = 0; } slider.thumbCenter = newCenter; CMTime videoDuration = player.currentItem.duration; double videoDurationSeconds = CMTimeGetSeconds(videoDuration); double newTime = videoDurationSeconds * (newCenter.x / slider.frame.size.width); CMTime time = CMTimeMakeWithSeconds(newTime, player.currentTime.timescale); [player seekToTime:time]; } } ``` 希望这可以帮助到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值