JQuery Slider, how to make “step” size change

后端 未结 12 735
遥遥无期
遥遥无期 2020-11-27 10:59

Is it possible to use the JQuery Slider (range slider / dual slider) to have non-linear (non consistent \"step\" size) values?

I want to horizontal Slider to look li

相关标签:
12条回答
  • 2020-11-27 11:18

    Not sure if you want the slider scale to be in proportion to your values* but if so, I provided a solution to this for someone else who asked the same question. You can find my solution here. Basically I make use of the slide event that gets triggered when you move the slider to mimic the stepping, but based off a custom array defining the steps. This way it only allows you to "step" to your predefined values, even if they're not evenly spread.

    *In other words if you want your slider to look like this:

    |----|----|----|----|----|----|----|
    0   10   20  100  1000 2000 10000 20000
    

    then go with one of the other solutions here, but if you want your slider to look like this (diagram not to scale):

    |--|--|-------|-----------|-----------|--------------------|--------------------|
    0 10 20     100         1000        2000               10000                20000
    

    Then the solution I linked to may be more what you're after.


    Edit: Ok, this version of the script should work with dual sliders:

    $(function() {
        var values = [0, 500, 750, 1000, 1250, 1500, 2000, 2500, 75000, 100000, 150000, 200000, 250000, 300000, 350000, 400000, 500000, 1000000];
        var slider = $("#price-range").slider({
            orientation: 'horizontal',
            range: true,
            min: 0,
            max: 1000000,
            values: [0, 1000000],
            slide: function(event, ui) {
                var includeLeft = event.keyCode != $.ui.keyCode.RIGHT;
                var includeRight = event.keyCode != $.ui.keyCode.LEFT;
                var value = findNearest(includeLeft, includeRight, ui.value);
                if (ui.value == ui.values[0]) {
                    slider.slider('values', 0, value);
                }
                else {
                    slider.slider('values', 1, value);
                }
                $("#price-amount").html('$' + slider.slider('values', 0) + ' - $' + slider.slider('values', 1));
                return false;
            },
            change: function(event, ui) { 
                getHomeListings();
            }
        });
        function findNearest(includeLeft, includeRight, value) {
            var nearest = null;
            var diff = null;
            for (var i = 0; i < values.length; i++) {
                if ((includeLeft && values[i] <= value) || (includeRight && values[i] >= value)) {
                    var newDiff = Math.abs(value - values[i]);
                    if (diff == null || newDiff < diff) {
                        nearest = values[i];
                        diff = newDiff;
                    }
                }
            }
            return nearest;
        }
    });
    

    Note that it looks a little funny down the far left end, since the jumps are so close together compared to the right hand end, but you can see its stepping as desired if you use your keyboard arrows to move the slider. Only way to get around that is to change your scale to not be quite so drastically exponential.


    Edit 2: Ok, if the spacing is too exaggerated when you use the true values, you could use a set of fake values for the slider & then look up the real value this corresponds to when you need to use the real value (in a similar way to what the other solutions here suggested). Here's the code:

    $(function() {
        var trueValues = [0, 500, 750, 1000, 1250, 1500, 2000, 2500, 75000, 100000, 150000, 200000, 250000, 300000, 350000, 400000, 500000, 1000000];
        var values =     [0,   1,   2,    3,    4,    5,    6,    7,    10,     15,     20,     25,     30,     40,     50,     60,     75,     100];
        var slider = $("#price-range").slider({
            orientation: 'horizontal',
            range: true,
            min: 0,
            max: 100,
            values: [0, 100],
            slide: function(event, ui) {
                var includeLeft = event.keyCode != $.ui.keyCode.RIGHT;
                var includeRight = event.keyCode != $.ui.keyCode.LEFT;
                var value = findNearest(includeLeft, includeRight, ui.value);
                if (ui.value == ui.values[0]) {
                    slider.slider('values', 0, value);
                }
                else {
                    slider.slider('values', 1, value);
                }
                $("#price-amount").html('$' + getRealValue(slider.slider('values', 0)) + ' - $' + getRealValue(slider.slider('values', 1)));
                return false;
            },
            change: function(event, ui) { 
                getHomeListings();
            }
        });
        function findNearest(includeLeft, includeRight, value) {
            var nearest = null;
            var diff = null;
            for (var i = 0; i < values.length; i++) {
                if ((includeLeft && values[i] <= value) || (includeRight && values[i] >= value)) {
                    var newDiff = Math.abs(value - values[i]);
                    if (diff == null || newDiff < diff) {
                        nearest = values[i];
                        diff = newDiff;
                    }
                }
            }
            return nearest;
        }
        function getRealValue(sliderValue) {
            for (var i = 0; i < values.length; i++) {
                if (values[i] >= sliderValue) {
                    return trueValues[i];
                }
            }
            return 0;
        }
    });
    

    You can fiddle with the numbers in the values array (which represent the slider stop points) until you get them spaced out how you want. This way you can make it feel, from the user's perspective, like it's sliding proportionally to the values, but without being as exaggerated. Obviously if your true values are dynamically created, you may need to come up with an algorithm to generate the slider values instead of statically defining them...

    0 讨论(0)
  • 2020-11-27 11:18

    Somebody posted this on the jQuery website. See:

    http://forum.jquery.com/topic/non-linear-logarithmic-or-exponential-scale-for-slider

    and

    http://jsbin.com/ezema

    It is exactly what yo have, but way simpler (like 1 line of code).

    0 讨论(0)
  • 2020-11-27 11:18

    I had to do something similar and even though this is a late response, someone else may happen on to this thread just as I did, and find my solution useful. Here is the solution I created:

    http://jsfiddle.net/YDWdu/

    So apparently, postings containing links to jsfiddle "must be accompanied by code".
    OK - here ya go, stackoverflow... Some lovely "code" for you.
    
    0 讨论(0)
  • 2020-11-27 11:19

    if min and max value are the same, slider value don't change

    change this part

            if (ui.value == ui.values[0]) {
                slider.slider('values', 0, value);
            }
            else {
                slider.slider('values', 1, value);
            }
    

    into

            if ( ui.values[0] == ui.values[1] ) {
                slider.slider('values', 0, value);
                slider.slider('values', 1, value);
            }else{
                if (ui.value == ui.values[0]) {
                    slider.slider('values', 0, value);
                }else {
                    slider.slider('values', 1, value);
                }
            }
    
    0 讨论(0)
  • 2020-11-27 11:26

    One option for you is use a step size of one and reference an array containing your selected values. Start at 0, go up to 20, get array[value_of_slider] to get your actual value. I don't know sliders well enough to tell you whether or not there is a way to give it a custom set of values.

    0 讨论(0)
  • 2020-11-27 11:27

    here's how i did mine. demo here - http://janpatricklara.com/web/extra/jQueryUISliderUnevenSteps.html

    have an array of your desired values

    var amts=[50,100,150,200,225,250,300];
    

    have the slider increment from 0 to the length of the array, with steps of 1. output the value from the index of the array instead of using the slider's actual value.

    this way the increments and steps are evenly distributed. after that you can just grab the value of the label or save it to a var.

    $('#amtslider').slider({
        min:0,
        max:amts.length-1,
        step:1,
        value:0,
        change:function(event, ui){
            //alert(amts[$(this).slider("value")]);
            //alert($(this).slider("value"));
            $('#lbl_amt').val(amts[$(this).slider("value")]);
        },
        slide:function(event, ui){
            $('#lbl_amt').val(amts[$(this).slider("value")]);
        }
    });
    
    0 讨论(0)
提交回复
热议问题