【问题标题】:Combined total for multiple jQuery-UI Sliders多个 jQuery-UI 滑块的总和
【发布时间】:2010-08-15 05:49:26
【问题描述】:

我正在尝试实现一个页面,其中有 4 个 jQuery-UI 滑块,并且我想让所有 4 个滑块的总和永远不会超过 400。

我不介意这是以哪种方式实现的,它可以从 0 开始,一旦您更改 1 个滑块,剩余的可用总数就会减少,或者将滑块设置为超过最大值,就会减少另一个滑块的值滑块。

附:滑块以 10 为增量。

欢迎所有想法和建议,如果您想测试,我已经设置了jsFiddle

【问题讨论】:

    标签: jquery jquery-ui slider range


    【解决方案1】:

    来吧:

    var sliders = $("#sliders .slider");
    
    sliders.each(function() {
        var value = parseInt($(this).text(), 10),
            availableTotal = 400;
    
        $(this).empty().slider({
            value: 0,
            min: 0,
            max: 400,
            range: "max",
            step: 10,
            slide: function(event, ui) {
                // Update display to current value
                $(this).siblings().text(ui.value);
    
                // Get current total
                var total = 0;
    
                sliders.not(this).each(function() {
                    total += $(this).slider("option", "value");
                });
    
                // Need to do this because apparently jQ UI
                // does not update value until this event completes
                total += ui.value;
    
                var max = availableTotal - total;
    
                // Update each slider
                sliders.not(this).each(function() {
                    var t = $(this),
                        value = t.slider("option", "value");
    
                    t.slider("option", "max", max + value)
                        .siblings().text(value + '/' + (max + value));
                    t.slider('value', value);
                });
            }
        });
    });
    

    这是一个简单的演示:http://jsfiddle.net/yijiang/Y5ZLL/4/

    【讨论】:

      【解决方案2】:

      制作了上述答案的更新版本以显示 100% 的百分比。因此,当您向上调整一个滑块时,其他两个会减少,使每个滑块的百分比加起来为 100%。还可以轻松设置初始值

      JSfiddle

      var sliders = $("#sliders .slider");
      var availableTotal = 100;
      
      sliders.each(function() {
          var init_value = parseInt($(this).text());
      
          $(this).siblings('.value').text(init_value);
      
          $(this).empty().slider({
              value: init_value,
              min: 0,
              max: availableTotal,
              range: "max",
              step: 2,
              animate: 0,
              slide: function(event, ui) {
      
                  // Update display to current value
                  $(this).siblings('.value').text(ui.value);
      
                  // Get current total
                  var total = 0;
      
                  sliders.not(this).each(function() {
                      total += $(this).slider("option", "value");
                  });
      
                  // Need to do this because apparently jQ UI
                  // does not update value until this event completes
                  total += ui.value;
      
                  var delta = availableTotal - total;
      
                  // Update each slider
                  sliders.not(this).each(function() {
                      var t = $(this),
                          value = t.slider("option", "value");
      
                      var new_value = value + (delta/2);
      
                      if (new_value < 0 || ui.value == 100) 
                          new_value = 0;
                      if (new_value > 100) 
                          new_value = 100;
      
                      t.siblings('.value').text(new_value);
                      t.slider('value', new_value);
                  });
              }
          });
      });
      

      【讨论】:

      • 根据我的经验,只有将 step 设置为 1 并将行 var new_value = value + (delta/2); 更改为 var new_value = value + (delta); 时,它才能完美运行
      • @ZZ5 如果您总共只有 2 个滑块,则该答案有效,而此答案仅在您有 3 个滑块时有效。具有 N 个滑块的通用解决方案会更复杂。此外,总体而言,用户体验非常糟糕(即尝试选择 70% - 15% - 15%)。
      【解决方案3】:

      我发现当其他滑块(除了您正在移动的滑块之外)移动时,会分散注意力。我还修改了 Yijiang fiddle 现在只是在达到 400 时让它停止。如果你想让那个滑块走高,你首先必须降低其他的一个,就像第一个一样,但它会保持滑块相对于总体总数。

      这意味着当您将一个滑块设置为 25% 和另一个滑块设置为 50% 时,它们看起来分别为 25 和 50。

      JSfiddle

      var sliders = $("#sliders .slider");
      
      sliders.each(function() {
          var value = parseInt($(this).text(), 10),
              availableTotal = 400;
      
          $(this).empty().slider({
              value: 0,
              min: 0,
              max: 400,
              range: "max",
              step: 10,
              animate: 100,
              slide: function(event, ui) {
      
                  // Get current total
                  var total = 0;    
      
                  sliders.not(this).each(function() {
                      total += $(this).slider("option", "value");
                  });    
      
      
                  var max = availableTotal - total;            
      
                  if (max - ui.value >= 0) {
                      // Need to do this because apparently jQ UI
                      // does not update value until this event completes
                      total += ui.value;
                      console.log(max-ui.value);
                      $(this).siblings().text(ui.value);
                  } else {
                      return false;
                  }
              }
          });
      });
      

      【讨论】:

      • 关于常数和滑块问题的唯一正确答案是整个互联网!赞一个!
      【解决方案4】:

      这些答案中没有一个对以任何有效的方式改变滑块相互关系最有效......他们中的大多数人在计算中留下了一个或多个,或者不尊重总体限制,我需要一些东西来允许用户在 HTML5 游戏中选择他们的筹码,所以如果其他人有类似的问题,我想出了这个……如果你不需要把它与改变投注筹码之类的东西联系起来,那就拿出停止选项或更改它以满足您的需要

          <div id="chip_holder" style="float:right;margin-right:20px;">
          <ul id="sliders">
          <?php
          $chips = array("1" => array("blue", "1 Point", "1"), "5" => array("red", "5 Points", "5"), "10" => array("gold", "10 Points", "10"));
      
              $t = 0;
              $value_per_row = floor($my_points / count($chips));
                $totalc = 0;
              foreach($chips as $key => $value){
              $value = floor($value_per_row / $value[2]);
              $totalc = $totalc + $value_per_row;
              ?>
              <li style="display:inline-block;">
                    <input type="number" style="display:none;" id="hidden_value_<?php echo $key; ?>" value="<?php echo floor($value);  ?>" min="0" max="<?php echo $my_points; ?>" step="<?php echo $chips[$key][2]; ?>" />
                    <span id="slide_<?php echo $key; ?>" title="<?php echo $key; ?>" class="chip_slider" alt="<?php echo $key / $my_points; ?>"></span>
                    <span id="chip_label_<?php echo $key; ?>" title="<?php echo $key; ?>" class="chip_label"><?php echo $value; ?></span>
              </li>
          <?php
              $t++;
              }
              if($totalc < $my_points){
              $min = min(array_keys($chips));
              $remainder = floor(($my_points - $totalc) / $chips[$min][2]);
          ?>
              <script>
      
                  $('#hidden_value_<?php echo $min; ?>').val(parseInt($('#hidden_value_<?php echo $min; ?>').val()) + parseInt(<?php echo $remainder; ?>));
                  $('#chip_label_<?php echo $min; ?>').text(parseInt($('#hidden_value_<?php echo $min; ?>').val()));
              </script>
              <?php } ?>
                  <li id="checkout_button" onclick="javascript: checkout_now();"><?php echo CASHOUT; ?></li>
      
              </ul>
               <ul id="chips_stay_put">
               <?php
                  $t = 0;
                  foreach($chips as $key => $value){
                  ?>
                    <li class="chip_holder" style="width:70px;">
                        <span id="chip_holder_<?php echo $key; ?>" class="<?php echo $value[0]; ?>" alt="<?php echo $key; ?>"></span>
                   </li>
                      <?php
                  $t++;
                  }
              ?>
              </ul>
              </div>
      <script>
       function drop_chips(id, chips){
      
      $('.chip_label').each(function(){
      
              id =$(this).attr('id');
               idx =$('#' + id).attr('title');
          chips = parseInt($('#chip_label_' + idx).text());
          cls = $('#chip_holder_' + idx).attr('class');
      
          $('#chip_holder_' + idx).html('');
      
          m = minMaxTitle($('.chip.' + cls));
      
          if(m>0){
              start = 0;
          }else{
              start = m;
          }
          htmlH = '';
      
              while(m<=chips){
              start= start + m;
                  zIndex = parseInt(start) + parseInt(100);
      
                  htmlH += '<span id="chip_' + idx + '_' + m + '" class="chip ' + cls + '" style="position:absolute;top:-'+ (m * 3) + 'px;z-index:' + zIndex + ';" alt="' + cls + '" title="' +m+ '">' + idx +  '</span>';
      
                  m++;
      
          }
      
          $('#chip_holder_' + idx).html(htmlH);
      
      
              $('.chip').draggable({
                drag: function( event, ui ) {
                    var snapTolerance = $(this).draggable('option', 'snapTolerance');
                    var topRemainder = ui.position.top % 20;
                    var leftRemainder = ui.position.left % 20;
      
                    if (topRemainder <= snapTolerance) {
                    ui.position.top = ui.position.top - topRemainder;
                    }
      
                    if (leftRemainder <= snapTolerance) {
                    ui.position.left = ui.position.left - leftRemainder;
                    }
                } ,
      
                revert : function(event, ui) {
                      // on older version of jQuery use "draggable"
                        // $(this).data("draggable")
                        // on 2.x versions of jQuery use "ui-draggable"
                        // $(this).data("ui-draggable")
                        $(this).data("uiDraggable").originalPosition = {
                        top : 0,
                        left : 0
                        };
                        // return boolean
                        return !event;
                        // that evaluate like this:
                        // return event !== false ? false : true;
                    }
      
              });
          });
      
      }
      var sliders = $("#sliders .chip_slider");
      
      sliders.each(function() {
          var slider_id;
          var value = parseInt($(this).text(), 10),
              availableTotal = parseInt($('#my_points_hidden').val());
      
          $(this).empty().slider({
              value: parseInt($('#' + $(this).attr('id')).prev('input').val()),
              min: 0,
              max: parseInt($('#' + $(this).attr('id')).prev('input').attr('max')),
              range:parseInt($('#' + $(this).attr('id')).prev('input').attr('max')),
              orientation:"vertical",
              step: 1,
              animate: 100,
              stop: function( event, ui ) { drop_chips() },
              slide: function(event, ui) {
      
               // Update display to current value
                  $(this).siblings('.value').text(ui.value);
      
                  // Get current total
                  var total = 0;
      
              var slider_id = $(this).attr('title');
      
                  sliders.not(this).each(function() {
                      total += $(this).slider("option", "value");
                  });
      
                  // Need to do this because apparently jQ UI
                  // does not update value until this event completes
                  total += ui.value;
      
                  var delta = availableTotal - total;
      
                  // Update each slider
                  sliders.not(this).each(function() {
                      var t = $(this),
                          value = t.slider("option", "value");
      
                      var new_value = value + (delta/2);
      
                      if (new_value < 0 || ui.value == 100) 
                          new_value = 0;
                      if (new_value > 100) 
                          new_value = 100;
      
                      t.siblings('.value').text(new_value);
                      t.slider('value', new_value);
                      id = $(this).attr('id');
      
                      title = $('#' + id).attr('title');
                      initial_slider = total - new_value;
                      console.log(slider_id);
              $('#chip_label_' + slider_id).text(parseInt(parseInt(ui.value) / parseInt($('#hidden_value_' + slider_id).attr('step'))));
                      $('#chip_label_' + title).text(parseInt(parseInt(new_value) / parseInt($('#hidden_value_' + title).attr('step'))));
                    });
      
              }
      
          });
      });
      
      </script>
      

      【讨论】:

        【解决方案5】:

        这个帖子是我努力构建它的一个很好的起点,希望它可以帮助其他人。 https://codepen.io/jmester13/pen/jOEyNEe

        $(document).ready(function() {
          slider = new Slider();
        });
        
        var Slider = (function() {
        
          var Slider = function() {
        
            this.initialise();
          }
        
          Slider.prototype = {
        
            initialise: function() {
              this.vars();
              this.setup();
              this.slideEvent();
            },
        
            vars: function() {
              // vars
              _this = this;
              this.container = $('.sliders');
              this.slider = $('.slider');
              this.slide = $('.slide');
              this.controls = $('.control');
              this.value = $('.value');
              this.totalPercentage = 100;
            },
        
            setup: function() {
              // set equal width depending on how many sliders there are when initalised 
              var counter = 0;
              this.slide.each(function() {
                counter++;
              });
        
              var initWidth = this.totalPercentage / counter;
        
             this.slide.width(initWidth + '%');
             this.slide.attr('data-percent', initWidth + '%');
             this.value.text(initWidth + '%');
            },
        
            getPercentWidth: function(target) {
              // get percentage of current width
              target.attr('data-percent', (100 * parseFloat(target.css('width')) / parseFloat(target.parent().css('width'))));
            },
        
            slideEvent: function() {
              // listen for mouse down on the controls
              this.controls.on('mousedown', function(event) {
                this.slideDrag(event);
              }.bind(this));
            },
        
            slideDrag: function(event) {
              event.preventDefault();
        
              this.target = $(event.target);
              this.prevMousePos = 0;
        
              this.target.parent().addClass('active');
              // listen mousemove and mouseup events on the document: only if the mousedown happend on one of the controls 
              $(document).on('mousemove', this.slideMove);
              $(document).on('mouseup', this.slideEnd);
            },
        
            slideMove: function() {
              _this.mousePos = event.pageX; 
              _this.amount = [];
        
              // get info on widths, offsets and positions
              var offset = _this.slider.offset().left;
              var sliderWidth = _this.slider.width();
              var posX = Math.min(Math.max(0, _this.mousePos - offset), sliderWidth);   
        
              // checks direction
              if (_this.mousePos < _this.prevMousePos)  {
                _this.direction = 'left';
              } else {
                _this.direction = 'right';
              }
        
              //console.log(_this.direction);
        
              // update mouse position
              _this.prevMousePos = _this.mousePos;
        
        
        
              // set new width of the active slider
              _this.target.parent().width(posX / sliderWidth * 100 + '%');
              _this.calcPercent();
            },
        
            calcPercent: function() {
              var totalWidth = 0;
              var sliderLength = 0;
              var leftoverAmount = 0;
        
              // loop through each slide
              _this.slide.each(function() {
        
                sliderLength++;
                _this.getPercentWidth($(this));
        
                if ($(this).hasClass('active')) {
                  // set active percentage
                  _this.active = parseFloat($(this).attr('data-percent')).toFixed(0);
        
                } else {
        
                  // add non active widths into an array
        
                  _this.amount.push(parseFloat($(this).attr('data-percent')).toFixed(0));
                }
        
               //totalWidth += parseFloat($(this).attr('data-percent'));
        
              });
        
              // find out the leftover amount
              leftoverAmount = _this.totalPercentage - _this.active;
              _this.nonActiveAmount = 0;
              $.each(_this.amount, function() {
        
               _this.nonActiveAmount += parseFloat(this) ;
              });
        
              var x = leftoverAmount / 100;
              var y = _this.nonActiveAmount / 100;
              var z = _this.active;
        
        
              _this.slide.each(function() {
        
                if (!$(this).hasClass('active') || !$(this).hasClass('locked')) {
                   console.log($(this));
        
                  var v = x * (parseFloat($(this).attr('data-percent')) / y);
                  $(this).width(v + '%');
        
                $(this).find('.value').text(Math.round(v) + '%');
        
                }
              });
        
            },
        
            slideEnd: function() {
              // kill the events on mouse up.
              _this.target.parent().removeClass('active');
              $(this).off('mousemove', slider.slideMove);
              $(this).off('mouseup', slider.slideEnd);
            },
          }
        
          return Slider;
        
        }());
        

        【讨论】:

          【解决方案6】:

          这对我来说是一次很好的经历。我希望它对其他人也有帮助。

          $(document).ready(function(){
              var sliders = $(".slider");
              var available = 100;
              sliders.slider({
                value: 0,
                min: 0,
                max: available,
                range: "max",
                step: 1,
                animate: 0,
                slide: function(event, ui){
                  var total = 0;
                  var arr = new Array();
                  sliders.not(this).each(function() {
                    var t = $(this);
                    arr.push(t);
                    total += t.slider("option", "value");
                  });
                  total += ui.value;							
                  var delta = available - total;
                  if(delta<0){
                    return false;
                  }
                  $(this).parent('.slidecontainer').find('.setval').text(ui.value);
                  $.each(arr, function(idx, ele){
                    let v = ele.slider("option", "value");
                    let vm = v + delta;
                    $(ele).parent('.slidecontainer').find('.max').text(vm);
                  });
                }
              });                    
            });
          <link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css" rel="stylesheet"/>
          <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
          <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
          <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
          
          <div class="col-lg-8">
            <div class="slidecontainer">
              <div class="slider"></div>
              <p class="value">Value:<span class="setval"></span> 
              Max: <span class="max"></span>
              </p>
            </div>
          </div>	
          <div class="col-lg-8">
            <div class="slidecontainer">
              <div class="slider"></div>
              <p class="value">Value:<span class="setval"></span> 
              Max: <span class="max"></span>
              </p>
            </div>
          </div>

          【讨论】:

          • 点评来源: 欢迎来到 Stack Overflow!请不要只用源代码回答。尝试对您的解决方案如何工作提供一个很好的描述。请参阅:How do I write a good answer?。谢谢
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-04
          相关资源
          最近更新 更多