基於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這三部分不是我這種嵌套結構,而是兄弟節點關係,你就得用樣式作相對定位,讓後兩個兄弟節點上移到第一個兄弟元素的位置,這樣,檢查元素的時候,進度條下面的其餘組件的盒子就會浸透到進度條的區域。雖然用戶不會檢查元素,可是時間久了以後也不方便程序員本身觀察,不是嗎。app

也就是說,咱們都但願HTML結構表達的元素和檢查元素的時候顯示的每一個元素的佔位是一致的。這也算是對你的HTML結構是否構造合理的一個評價指標less

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

對如今就有需求使用這個帶事件的進度條的同窗來講,看看這部分,能夠幫助你本身修改、完善它。ide

而對於想要先試用該組件的同窗,則能夠先不看這部分,等你用到發現該組件功能不足的時候,再看這部分代碼也不遲。post

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:進度條高度,傳像素值

事件

  • pbar-drag: 拖動進度條時觸發,回傳value值和百分比值
  • pbar-drag: 點擊進度條某一位置時觸發,回傳value值和百分比值

最後

若是本文對你有幫助,請不要吝嗇手中的點贊喲。
編程貴在實踐,趕忙行動起來吧!

關於做者

技術博客 || GitHub || 掘金主頁

相關文章
相關標籤/搜索