<template>
    <div class="app-drag" :style="style">
        <div class="background" />
        <div class="text" onselectstart="return false">
            <slot name="content">
                {{ content }}
            </slot>
        </div>
        <div class="slider" :style="{height,width:sliderWidth}">
            <i @mousedown="rangeStatus?init:''" :class="rangeStatus?successIcon:icon"></i>
        </div>
    </div>
</template>
<script>
const debounce = (function () {
  let timer = 0
  return function (callback, ms) {
    clearTimeout(timer)
    timer = setTimeout(callback, ms)
  }
})();
export default {
    name: 'SliderVerificationCode',
    model: {
        event: 'change',
        prop: 'isLock'
    },
    props: {
        // 成功之后的函数
        successFun: {
              type: Function
          },
        //失败之后的函数
        errorFun: {
              type: Function
          },
          //或者用值来进行监听
        status: {
              type: String
          },
        isLock: { //解锁状态
            type: [String,Boolean,Number,Object],
            required: true,
            default: false
        },
        icon: { //滑块的图标
            type: [String],
            default: 'el-icon-d-arrow-right'
        },
         //成功图标
        successIcon: {
              type: String,
              default: 'el-icon-success'
          },
        activeValue: { //滑块解锁后的值
            type: [String,Boolean,Number,Object],
            default: true
        },
        inactiveValue: { //滑块解锁前的值
            type: [String,Boolean,Number,Object],
            default: false
        },
        content: { //滑块的文字
            type: [String],
            default: `请拖住滑块，拖动到最右边`
        },
        successContent: { //成功后的滑块的文字
            type: [String],
            default: `验证通过`
        },
        contentColor: { //初始滑块轨道的文字颜色
            type: [String],
            default: `#333`
        },
        successColor: { //成功后的滑块的文字颜色
            type: [String],
            default: `#fff`
        },
        height: { //高度
            type: [String],
            default: `48px`
        },
        sliderWidth: { //滑块宽度
            type: [String],
            default: `56px`
        },
        background: { //初始背景
            type: [String],
            default: `#f2f2f2`
        },
        textColor: { //初始滑块的文字颜色
            type: [String],
            default: `#f00`
        },
        sliderBg: { //滑动后背景(原生的background 属性可以为16进制和rgb或标准颜色值)
            type: [String],
            default: `#75CDF9`
        },
        sliderColor: { //滑块的文字颜色(原生的color 属性可以为16进制和rgb或标准颜色值)
            type: [String],
            default: `#000`
        },
        sliderSuccessColor: { //滑动后滑块的文字颜色(原生的color 属性可以为16进制和rgb或标准颜色值)
            type: [String],
            default: `#f00`
        },
        successBg: { //滑动成功后背景(原生的background 属性可以为16进制和rgb或标准颜色值)
            type: [String],
            default: `lightgreen`
        },
    },
    watch:{
        isLock(v){  //重置样式
            !v && this.init();
        }
    },
    computed: {
        style() {
            const { height, background } = this;
            return { height, 'line-height': height, background };
        },
        resize (){
            return document.body.clientWidth;
        }
    },
    mounted() {
        this.init();
        if(window){
            window.onresize = ()=>{
                debounce(()=>{
                    this.init();
                },120);
            };
        }
    },
    data(){
          return {
              disX : 0,
              rangeStatus: false,

          }
      },
    methods: {
        /**
         * 定义一个获取DOM元素的方法-选择器
         */
        selector(selector) {
            return document.querySelector(selector);
        },
        /**
         * 初始化
         */
        init() {
            const box = this.selector('.app-drag'); //容器
            const background = this.selector('.background'); //背景
            const text = this.selector('.text'); //文字
            const slider = this.selector('.slider');//滑块
            const distance = box.offsetWidth && slider.offsetWidth ? (box.offsetWidth - slider.offsetWidth) : 0 ; //滑动成功的宽度（距离）
            let success =  this.inactiveValue;//是否通过验证的标志
            this.disX = 0
            this.rangeStatus = false
            // 初始化的时候 清除所有属性
            slider.style.transition = null;
            // if(this.icon) slider.innerHTML = this.icon;
            background.style.transition = null;
            background.style.background = this.sliderBg;
            slider.style.left = 0 + 'px';
            background.style.width = 0 + 'px';
            text.innerHTML = this.content;
            text.style.color = this.contentColor;
            slider.style.color = this.sliderColor;
            
            
            //二、给滑块注册鼠标按下事件
            slider.onmousedown = (event) => {
                //1.鼠标按下之前必须清除掉后面设置的过渡属性
                slider.style.transition = null;
                background.style.transition = null;
                //说明：clientX 事件属性会返回当事件被触发时，鼠标指针向对于浏览器页面(或客户区)的水平坐标。
                //2.当滑块位于初始位置时，得到鼠标按下时的水平位置
                const ev = event || window.event;
                const downX = ev.clientX;
                if(this.rangeStatus){//不运行
                  return false;
                }
                //三、给文档注册鼠标移动事件
                document.onmousemove = (e) => {
                    const evt = e || window.event;//是为了更好的兼容IE浏览器和非ie浏览器。在ie浏览器中,window.event是全局变量,在非ie中，就需要自己传入一个参数来获取event啦，所以就有了var e = e||window.event
                    //1.获取鼠标移动后的水平位置
                    const moveX = evt.clientX;
                    //2.得到鼠标水平位置的偏移量（鼠标移动时的位置 - 鼠标按下时的位置）
                    let offsetX = moveX - downX;
                    //3.在这里判断一下：鼠标水平移动的距离 与 滑动成功的距离 之间的关系
                    if (offsetX > distance) {
                        offsetX = distance;//如果滑过了终点，就将它停留在终点位置
                    } else if (offsetX < 0) {
                        offsetX = 0;//如果滑到了起点的左侧，就将它重置为起点位置
                    }
                    //4.根据鼠标移动的距离来动态设置滑块的偏移量和背景颜色的宽度
                    slider.style.left = offsetX + 'px';
                    background.style.width = offsetX + 56 +'px';
                    //如果鼠标的水平移动距离 = 滑动成功的宽度
                    if (offsetX == distance) {
                        //1.设置滑动成功后的样式
                        text.innerHTML = this.successContent;
                        text.style.color = this.successColor;
                        slider.style.color = this.sliderSuccessColor;
                        background.style.background = this.successBg;
                        //2.设置滑动成功后的状态
                        success = this.activeValue;
                        //成功后，清除掉鼠标按下事件和移动事件（因为移动时并不会涉及到鼠标松开事件）
                        slider.onmousedown = null;
                        document.onmousemove = null;
                        //3.成功解锁后的回调函数
                        setTimeout(() => {
                            this.$emit('change', this.activeValue);
                            // console.log('解锁成功');
                        }, 100);
                    }
                };
                //四、给文档注册鼠标松开事件
                document.onmouseup = () => {
                    //如果鼠标松开时，滑到了终点，则验证通过
                    if (success == this.activeValue){
                        this.rangeStatus = true;
                      if(this.status){
                          this.$parent[this.status] = true;
                      }
                      //执行成功的函数
                      this.successFun && this.successFun();
                    }else{
                         //反之，则将滑块复位（设置了1s的属性过渡效果）
                    slider.style.left = 0;
                    background.style.width = 0;
                    slider.style.transition = 'left 1s ease';
                    background.style.transition = 'width 1s ease';
                    //只要鼠标松开了，说明此时不需要拖动滑块了，那么就清除鼠标移动和松开事件。
                    document.onmousemove = null;
                    document.onmouseup = null;
                    this.errorFun && this.errorFun();
                    }
                };
            };
           
        }
    }
};
</script>
<style scoped>
* {
    margin: 0px;
    padding: 0px;
    font-family: "微软雅黑";
    box-sizing: border-box;
}
.app-drag {
    width: 360px;
    height: 48px;
    background-color: #e8e8e8;
    position: relative;
    margin: 0 auto;
    border-radius: 8px;
}
.background {
    width: 360px;
    height: 48px;
    position: absolute;
    border-radius: 8px;
}
.text {
    position: absolute;
    color: rgba(51, 51, 51, 100);
    font-size: 16px;
    font-family: SourceHanSansCN-Medium;
    width: 100%;
    height: 100%;
    text-align: center;
    user-select: none;
}
.slider {
    width: 56px;
    height: 44px;
    position: absolute;
    border: 1px solid #ccc;
    cursor: move;
    font-family: "宋体";
    text-align: center;
    background-color: #fff;
    user-select: none;
    color: #666;
    cursor: pointer;
    border-radius: 6px;
}

 i{
    line-height: 44px;
    position: absolute;
    left:0; 
    bottom:0; 
    top:0; 
    right:0; 
    margin:auto; 
    color: #3fcd26;    
    font-size: 24px;
}
</style>