基于Vue的事件响应式进度条组件

写在前面

找了不少vue进度条组件,都不包含拖拽和点击事件,input range却是原生包含input和change事件,可是直接基于input range作进度条的话,样式部分须要作大量调整和兼容性处理。即便作好了,未来须要修改外观,又是一番折腾。vue

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

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

效果图

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

首先是模板部分

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

说一下好处,这样的结构,作出来的样式,在页面检查元素的时候,可以清晰看到每一个div和页面上展现的部分是重合的。编程

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

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

<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部分

对如今就有需求使用这个带事件的进度条的同窗来讲,看看这部分,能够帮助你本身修改、完善它。app

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

export default {
        name: 'ProgressBar',
        props: {
            leftBg: String,
            bgc: String,
            ballBgc: String,
            height: String,
            width: 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:进度条高度,传像素值
  • max:进度条最大值
  • min:最小值
  • value:当前值

事件

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

最后

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

关于做者

做者:云荒杯倾

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

相关文章
相关标签/搜索