zoukankan      html  css  js  c++  java
  • 基于Vue的事件响应式进度条组件

    写在前面

    找了很多 Vue 进度条组件!,都不包含拖拽和点击事件,input range倒是原生包含input和change事件,但是直接基于input range做进度条的话,样式部分需要做大量调整和兼容性处理。即使做好了,将来需要修改外观,又是一番折腾。

    基于以上两个原因,做了一个可以响应input和change事件(即一个是拖动进度条到某处,一个是在进度条某位置点击使其值变为该位置)的div实现的Vue组件,这样既满足了对进度条事件的需求,也带来了如有需求变动,样式修改很方便的好处。

    事件响应式进度条的应用场景主要是自定义video播放器的进度条。

    效果图

    以上就是可以利用本组件实现的一些效果,他们都能响应input和change两种事件。

    首先是模板部分

    认真看一下上图,怎么构造HTML模板还是需要一番考虑的,我也是改了好几次,最后定的这个结构。首先有一层外包div就不说了。然后外包div下面就一个class = 'progress'的div,这个div内部的div是表示进度条已划过部分(class="left"),class="left"这个div内部又包含一个div来表示我们可以拖动的滑块小球。

    说一下好处,这样的结构,做出来的样式,在页面检查元素的时候,能够清晰看到每个div和页面上展示的部分是重合的。

    如果你的进度条 表示整个长度的div、表示左半部分的div、表示滑块的div这三部分不是我这种嵌套结构,而是兄弟节点关系,你就得用样式做相对定位,让后两个兄弟节点上移到第一个兄弟元素的位置,这样,检查元素的时候,进度条下面的其他组件的盒子就会浸透到进度条的区域。虽然用户不会检查元素,但是时间久了之后也不方便程序员自己观察,不是吗。

    也就是说,我们都希望HTML结构表达的元素和检查元素的时候显示的每个元素的占位是一致的。这也算是对你的HTML结构是否构造合理的一个评价指标

    
    <template>
        <div class="progress-wrapper" :style="wrapStyle">
            <div class="progress" @mousedown="mousedownHandler" @mouseover="mouseoverHandler"
                 @mousemove="mousemoveHandler" @mouseup="mouseupHandler" :style="pBarStyle">
                <div class="left" :style="leftStyle">
                    <div class="ball" :style="ballStyle"></div>
                </div>
                <slot></slot>
            </div>
        </div>
    </template>
    

    js部分

    对现在就有需求使用这个带事件的进度条的同学来说,看看这部分,可以帮助你自己修改、完善它。

    而对于想要先试用该组件的同学,则可以先不看这部分,等你用到发现该组件功能不足的时候,再看这部分代码也不迟。

    
    export default {
            name: 'ProgressBar',
            props: {
                leftBg: String,
                bgc: String,
                ballBgc: String,
                height: String,
                 String,
                max: {
                    type: Number,
                    default: 100,
                },
                min: {
                    type: Number,
                    default: 0,
                },
                value: {
                    type: Number,
                    default: 36,
                },
            },
            data: function () {
                return {
                    pValue: this.value,
                    pMax: this.max,
                    pMin: this.min,
                    wrapStyle: {
                        'width': this.width,
                    },
                    pBarStyle: {
                        'backgroundColor': this.bgc,
                        'height': this.height,
                    },
                    leftStyle: {
                        'width': this.progressPercent + '%',
                        'background': this.leftBg,
                        'height': this.height,
                    },
                    ballStyle: {
                        'backgroundColor': this.ballBgc,
                        'height': this.height,
                        'width': this.height,
                        'borderRadius': parseInt(this.height) / 2 + 'px',
                        'right': - parseInt(this.height) / 2 + 'px',
                    },
                    // 标记是否按下鼠标
                    isMouseDownOnBall: false,
                }
            },
            computed: {
                progressPercent(){
                    return (this.pValue - this.pMin) / (this.pMax - this.pMin) * 100;
                },
                progressElement(){
                    return this.$el.getElementsByClassName('progress')[0];
                },
            },
            methods: {
                mousedownHandler(e){
                    if(e.which === 1){
                        this.isMouseDownOnBall = true;
                    }
                },
                mousemoveHandler(e){
                    if(this.isMouseDownOnBall === true){
                        // 修改进度条本身
                        let decimal = (e.clientX - this.$el.offsetLeft) / this.progressElement.clientWidth;
                        let percent = decimal * 100;
                        this.leftStyle.width = percent + '%';
                        // 修改value
                        this.pValue = this.pMin + decimal * (this.pMax - this.pMin);
                        this.$emit('pbar-drag', this.pValue, percent);
                    }
                },
                mouseupHandler(e){
                    if(this.isMouseDownOnBall){
                        // 修改进度条本身
                        let decimal = (e.clientX - this.$el.offsetLeft) / this.progressElement.clientWidth;
                        let percent = decimal * 100;
                        this.leftStyle.width = percent + '%';
                        // 修改value
                        this.pValue = this.pMin + decimal * (this.pMax - this.pMin);
                        this.$emit('pbar-seek', this.pValue, percent);
    
                        this.isMouseDownOnBall = false;
                    }
                },
                mouseoverHandler(e){
                    // 没有按左键进入进度条
                    if(e.which === 0){
                        this.isMouseDownOnBall = false;
                    }
                }
            },
            watch: {
                max(cur, old){
                    this.pMax = cur;
                },
                min(cur, old){
                    this.pMin = cur;
                },
                value(cur, old){
                    this.pValue = cur;
                },
                progressPercent(cur, old){
                    this.leftStyle.width = cur + '%';
                }
            },
            mounted(){
                // 数据验证
                if(this.max < this.min){
                    console.error("max can't less than min !");
                }
                // 初始百分比
                this.leftStyle.width = (this.pValue - this.pMin) / (this.pMax - this.pMin) * 100 + '%';
            },
        }
    

    安装、使用

    地址

    代码库地址在GitHub

    安装、使用

    
    
    npm install vue-draggable-progressbar --save
    
    import progressBar from 'vue-draggable-progressbar'
    

    用例:

    
    <progress-bar ref="aa"></progress-bar>
    
    <progress-bar width="40%" leftBg="greenyellow" bgc="#ccc" ballBgc="red"></progress-bar>
    
    <progress-bar width="60%" leftBg="linear-gradient(to right, yellow, pink)" bgc="#ccc" ballBgc="red"></progress-bar>
    
    <progress-bar width="80%" leftBg="yellow" bgc="#ccc" ballBgc="red" height="30px"></progress-bar>
    
    <progress-bar leftBg="greenyellow" bgc="#ccc" ballBgc="rgba(255,0,0,0.2)" height="40px"></progress-bar>
    
    <progress-bar leftBg="greenyellow" bgc="#ccc" ballBgc="red" :max="max" :value="value" :min="min"
                  @pbar-drag="drag" @pbar-seek="seek"></progress-bar>
    
    

    组件props

    • leftBg:进度条已划过部分背景色
    • bgc:进度条还未划过部分背景色
    • ballBgc:滑块背景色
    • width:进度条占父组件的宽度百分比,传百分比数值
    • height:进度条高度,传像素值

    事件

    • pbar-drag: 拖动进度条时触发,回传value值和百分比值
    • pbar-drag: 点击进度条某一位置时触发,回传value值和百分比值

    最后

    如果本文对你有帮助,请不要吝啬手中的点赞哟。
    编程贵在实践,赶紧行动起来吧!

    关于作者

    技术博客 || GitHub || 掘金主页

    原文地址:https://segmentfault.com/a/1190000013123304

  • 相关阅读:
    Postman使用教程
    CAD和ArcGIS转换 矢量配准
    SAP CRM Advanced search和Simple search里Max hit表现行为的差异
    SAP CRM Product simple search的启用步骤
    如何快速定位SAP CRM订单应用(Order Application)错误消息抛出的准确位置
    如何动态修改SAP CRM WebClient UI表格栏的宽度
    如何在SAP CRM WebClient UI里创建web service并使用ABAP消费
    如何处理SAP CRM Web Service错误
    如何使用SAP CRM WebClient UI实现一个类似新浪微博的字数统计器
    如何开启SAP CRM基于WORD模板创建附件的功能
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9923627.html
Copyright © 2011-2022 走看看