美文网首页
jQuery实现可拖动控制进度条

jQuery实现可拖动控制进度条

作者: 祈澈菇凉 | 来源:发表于2021-05-17 17:06 被阅读0次
    <!DOCTYPE HTML>
    <html>
        <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
            <title>jQuery可拖动控制进度条</title>
            <style type="text/css">
                .demo {
                    width: 350px;
                    margin: 100px auto 10px auto
                }
                #g1,
                #g2 {
                    margin-top: 50px
                }
            </style>
            <link rel="stylesheet" href="css/jquery.range.css" />
            <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
            <script type="text/javascript" src="js/jquery.range.js"></script>
            <script type="text/javascript">
                $(function() {
                    $('.single-slider').jRange({
                        from: 0,
                        to: 10,
                        step: 1,
                        width: 200,
                        showLabels: true,
                        showScale: true
                    });
    
                });
            </script>
        </head>
        <body>
            <div class="demo">
                <input type="hidden" class="single-slider" value="5" />
            </div>
        </body>
    </html>
    
    
    

    css

    .slider-container .back-bar {
        height: 10px;
        position: relative;
    }
    
    .slider-container .back-bar .selected-bar {
        position: absolute;
        height: 100%;
    }
    
    .slider-container .back-bar .pointer {
        position: absolute;
        width: 10px;
        height: 10px;
        background-color: red;
        cursor: col-resize;
        opacity: 1;
        z-index: 2;
    }
    
    .slider-container .back-bar .pointer-label {
        position: absolute;
        top: -17px;
        font-size: 8px;
        background: white;
        white-space: nowrap;
        line-height: 1;
    }
    
    .slider-container .back-bar .focused {
        z-index: 10;
    }
    
    .slider-container .scale {
        top: 2px;
        position: relative;
    }
    
    .slider-container .scale span {
        position: absolute;
        height: 5px;
        border-left: 1px solid #999;
        font-size: 0;
    }
    
    .slider-container .scale ins {
        font-size: 9px;
        text-decoration: none;
        position: absolute;
        left: 0;
        top: 5px;
        color: #999;
        line-height: 1;
    }
    
    .theme-green .back-bar {
        height: 15px;
        border-radius: 2px;
        background-color: #eeeeee;
        background-color: #e7e7e7;
    }
    
    .theme-green .back-bar .selected-bar {
        border-radius: 2px;
        background-color: #a1fad0;
    }
    
    .theme-green .back-bar .pointer {
        width: 14px;
        height: 25px;
        top: -5px;
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
        background-color: #e7e7e7;
    }
    
    
    

    jquery.range.js

    /*jshint multistr:true, curly: false */
    /*global jQuery:false, define: false */
    /**
     * jRange - Awesome range control
     *
     * Written by
     * ----------
     * Nitin Hayaran (nitinhayaran@gmail.com)
     *
     * Licensed under the MIT (MIT-LICENSE.txt).
     *
     * @author Nitin Hayaran
     * @version 0.1-RELEASE
     *
     * Dependencies
     * ------------
     * jQuery (http://jquery.com)
     *
     **/
    ;
    (function($, window, document, undefined) {
        'use strict';
    
        var jRange = function() {
            return this.init.apply(this, arguments);
        };
        jRange.prototype = {
            defaults: {
                onstatechange: function() {},
                isRange: false,
                showLabels: true,
                showScale: true,
                step: 1,
                format: '%s',
                theme: 'theme-green',
                width: 300,
                disable: false
            },
            template: '<div class="slider-container">\
                <div class="back-bar">\
                    <div class="selected-bar"></div>\
                    <div class="pointer low"></div><div class="pointer-label">123456</div>\
                    <div class="pointer high"></div><div class="pointer-label">456789</div>\
                    <div class="clickable-dummy"></div>\
                </div>\
                <div class="scale"></div>\
            </div>',
            init: function(node, options) {
                this.options       = $.extend({}, this.defaults, options);
                this.inputNode     = $(node);
                this.options.value = this.inputNode.val() || (this.options.isRange ? this.options.from + ',' + this.options.from : this.options.from);
                this.domNode       = $(this.template);
                this.domNode.addClass(this.options.theme);
                this.inputNode.after(this.domNode);
                this.domNode.on('change', this.onChange);
                this.pointers      = $('.pointer', this.domNode);
                this.lowPointer    = this.pointers.first();
                this.highPointer   = this.pointers.last();
                this.labels        = $('.pointer-label', this.domNode);
                this.lowLabel      = this.labels.first();
                this.highLabel     = this.labels.last();
                this.scale         = $('.scale', this.domNode);
                this.bar           = $('.selected-bar', this.domNode);
                this.clickableBar  = this.domNode.find('.clickable-dummy');
                this.interval      = this.options.to - this.options.from;
                this.render();
            },
            render: function() {
                // Check if inputNode is visible, and have some width, so that we can set slider width accordingly.
                if (this.inputNode.width() === 0 && !this.options.width) {
                    console.log('jRange : no width found, returning');
                    return;
                } else {
                    this.domNode.width(this.options.width || this.inputNode.width());
                    this.inputNode.hide();
                }
    
                if (this.isSingle()) {
                    this.lowPointer.hide();
                    this.lowLabel.hide();
                }
                if (!this.options.showLabels) {
                    this.labels.hide();
                }
                this.attachEvents();
                if (this.options.showScale) {
                    this.renderScale();
                }
                this.setValue(this.options.value);
            },
            isSingle: function() {
                if (typeof(this.options.value) === 'number') {
                    return true;
                }
                return (this.options.value.indexOf(',') !== -1 || this.options.isRange) ?
                    false : true;
            },
            attachEvents: function() {
                this.clickableBar.click($.proxy(this.barClicked, this));
                this.pointers.on('mousedown touchstart', $.proxy(this.onDragStart, this));
                this.pointers.bind('dragstart', function(event) {
                    event.preventDefault();
                });
            },
            onDragStart: function(e) {
                if ( this.options.disable || (e.type === 'mousedown' && e.which !== 1)) {
                    return;
                }
                e.stopPropagation();
                e.preventDefault();
                var pointer = $(e.target);
                this.pointers.removeClass('last-active');
                pointer.addClass('focused last-active');
                this[(pointer.hasClass('low') ? 'low' : 'high') + 'Label'].addClass('focused');
                $(document).on('mousemove.slider touchmove.slider', $.proxy(this.onDrag, this, pointer));
                $(document).on('mouseup.slider touchend.slider touchcancel.slider', $.proxy(this.onDragEnd, this));
            },
            onDrag: function(pointer, e) {
                e.stopPropagation();
                e.preventDefault();
    
                if (e.originalEvent.touches && e.originalEvent.touches.length) {
                    e = e.originalEvent.touches[0];
                } else if (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length) {
                    e = e.originalEvent.changedTouches[0];
                }
    
                var position = e.clientX - this.domNode.offset().left;
                this.domNode.trigger('change', [this, pointer, position]);
            },
            onDragEnd: function(e) {
                this.pointers.removeClass('focused');
                this.labels.removeClass('focused');
                $(document).off('.slider');
            },
            barClicked: function(e) {
                if(this.options.disable) return;
                var x = e.pageX - this.clickableBar.offset().left;
                if (this.isSingle())
                    this.setPosition(this.pointers.last(), x, true, true);
                else {
                    var pointer = Math.abs(parseInt(this.pointers.first().css('left'), 10) - x + this.pointers.first().width() / 2) < Math.abs(parseInt(this.pointers.last().css('left'), 10) - x + this.pointers.first().width() / 2) ?
                        this.pointers.first() : this.pointers.last();
                    this.setPosition(pointer, x, true, true);
                }
            },
            onChange: function(e, self, pointer, position) {
                var min, max;
                if (self.isSingle()) {
                    min = 0;
                    max = self.domNode.width();
                } else {
                    min = pointer.hasClass('high') ? self.lowPointer.position().left + self.lowPointer.width() / 2 : 0;
                    max = pointer.hasClass('low') ? self.highPointer.position().left + self.highPointer.width() / 2 : self.domNode.width();
                }
                var value = Math.min(Math.max(position, min), max);
                self.setPosition(pointer, value, true);
            },
            setPosition: function(pointer, position, isPx, animate) {
                var leftPos,
                    lowPos = this.lowPointer.position().left,
                    highPos = this.highPointer.position().left,
                    circleWidth = this.highPointer.width() / 2;
                if (!isPx) {
                    position = this.prcToPx(position);
                }
                if (pointer[0] === this.highPointer[0]) {
                    highPos = Math.round(position - circleWidth);
                } else {
                    lowPos = Math.round(position - circleWidth);
                }
                pointer[animate ? 'animate' : 'css']({
                    'left': Math.round(position - circleWidth)
                });
                if (this.isSingle()) {
                    leftPos = 0;
                } else {
                    leftPos = lowPos + circleWidth;
                }
                this.bar[animate ? 'animate' : 'css']({
                    'width': Math.round(highPos + circleWidth - leftPos),
                    'left': leftPos
                });
                this.showPointerValue(pointer, position, animate);
                this.isReadonly();
            },
            // will be called from outside
            setValue: function(value) {
                var values = value.toString().split(',');
                this.options.value = value;
                var prc = this.valuesToPrc(values.length === 2 ? values : [0, values[0]]);
                if (this.isSingle()) {
                    this.setPosition(this.highPointer, prc[1]);
                } else {
                    this.setPosition(this.lowPointer, prc[0]);
                    this.setPosition(this.highPointer, prc[1]);
                }
            },
            renderScale: function() {
                var s = this.options.scale || [this.options.from, this.options.to];
                var prc = Math.round((100 / (s.length - 1)) * 10) / 10;
                var str = '';
                for (var i = 0; i < s.length; i++) {
                    str += '<span style="left: ' + i * prc + '%">' + (s[i] != '|' ? '<ins>' + s[i] + '</ins>' : '') + '</span>';
                }
                this.scale.html(str);
    
                $('ins', this.scale).each(function() {
                    $(this).css({
                        marginLeft: -$(this).outerWidth() / 2
                    });
                });
            },
            getBarWidth: function() {
                var values = this.options.value.split(',');
                if (values.length > 1) {
                    return parseInt(values[1], 10) - parseInt(values[0], 10);
                } else {
                    return parseInt(values[0], 10);
                }
            },
            showPointerValue: function(pointer, position, animate) {
                var label = $('.pointer-label', this.domNode)[pointer.hasClass('low') ? 'first' : 'last']();
                var text;
                var value = this.positionToValue(position);
                if ($.isFunction(this.options.format)) {
                    var type = this.isSingle() ? undefined : (pointer.hasClass('low') ? 'low' : 'high');
                    text = this.options.format(value, type);
                } else {
                    text = this.options.format.replace('%s', value);
                }
    
                var width = label.html(text).width(),
                    left = position - width / 2;
                left = Math.min(Math.max(left, 0), this.options.width - width);
                label[animate ? 'animate' : 'css']({
                    left: left
                });
                this.setInputValue(pointer, value);
            },
            valuesToPrc: function(values) {
                var lowPrc = ((values[0] - this.options.from) * 100 / this.interval),
                    highPrc = ((values[1] - this.options.from) * 100 / this.interval);
                return [lowPrc, highPrc];
            },
            prcToPx: function(prc) {
                return (this.domNode.width() * prc) / 100;
            },
            positionToValue: function(pos) {
                var value = (pos / this.domNode.width()) * this.interval;
                value = value + this.options.from;
                return Math.round(value / this.options.step) * this.options.step;
            },
            setInputValue: function(pointer, v) {
                // if(!isChanged) return;
                if (this.isSingle()) {
                    this.options.value = v.toString();
                } else {
                    var values = this.options.value.split(',');
                    if (pointer.hasClass('low')) {
                        this.options.value = v + ',' + values[1];
                    } else {
                        this.options.value = values[0] + ',' + v;
                    }
                }
                if (this.inputNode.val() !== this.options.value) {
                    this.inputNode.val(this.options.value);
                    this.options.onstatechange.call(this, this.options.value);
                }
            },
            getValue: function() {
                return this.options.value;
            },
            isReadonly: function(){
                this.domNode.toggleClass('slider-readonly', this.options.disable);
            },
            disable: function(){
                this.options.disable = true;
                this.isReadonly();
            },
            enable: function(){
                this.options.disable = false;
                this.isReadonly();
            },
            toggleDisable: function(){
                this.options.disable = !this.options.disable;
                this.isReadonly();
            }
        };
    
        /*$.jRange = function (node, options) {
            var jNode = $(node);
            if(!jNode.data('jrange')){
                jNode.data('jrange', new jRange(node, options));
            }
            return jNode.data('jrange');
        };
    
        $.fn.jRange = function (options) {
            return this.each(function(){
                $.jRange(this, options);
            });
        };*/
    
        var pluginName = 'jRange';
        // A really lightweight plugin wrapper around the constructor,
        // preventing against multiple instantiations
        $.fn[pluginName] = function(option) {
            var args = arguments,
                result;
    
            this.each(function() {
                var $this = $(this),
                    data = $.data(this, 'plugin_' + pluginName),
                    options = typeof option === 'object' && option;
                if (!data) {
                    $this.data('plugin_' + pluginName, (data = new jRange(this, options)));
                    $(window).resize(function() {
                        data.setValue(data.getValue());
                    }); // Update slider position when window is resized to keep it in sync with scale
                }
                // if first argument is a string, call silimarly named function
                // this gives flexibility to call functions of the plugin e.g.
                //   - $('.dial').plugin('destroy');
                //   - $('.dial').plugin('render', $('.new-child'));
                if (typeof option === 'string') {
                    result = data[option].apply(data, Array.prototype.slice.call(args, 1));
                }
            });
    
            // To enable plugin returns values
            return result || this;
        };
    
    })(jQuery, window, document);
    
    

    效果


    相关文章

      网友评论

          本文标题:jQuery实现可拖动控制进度条

          本文链接:https://www.haomeiwen.com/subject/fywdlltx.html