jQuery UI 滑块:如何使滑块处理冲突在最小值/最大值下很好地工作?

Posted

技术标签:

【中文标题】jQuery UI 滑块:如何使滑块处理冲突在最小值/最大值下很好地工作?【英文标题】:jQuery UI slider: how do I make slider handle collisions work nicely at min/max values? 【发布时间】:2020-05-29 17:07:57 【问题描述】:

https://codepen.io/ophello/pen/BaNaPdp?editors=0010

我有一个 jquery.ui 滑块,同时设置了两个手柄,以及一个允许它们相互碰撞和推动的偏移实现。

但是,如果您用两个滑块将鼠标快速移动到一端,则最后记录的值会卡在鼠标退出范围时的任何值。我该如何解决这个问题?

这是处理冲突的代码:

if (ui.values[0] >= ui.values[1]) 
    if ($(ui.handle).index() == 0)  // if the left handle is being dragged
        ui.values[0] = ui.value + offset;
        ui.values[1] = ui.value + offset + 1;
        $(this).slider("values", 1, ui.value + 1 + offset * 2);
     else 
        ui.values[0] = ui.value - offset - 1;
        ui.values[1] = ui.value - offset;
        $(this).slider("values", 0, ui.value - 1 - offset * 2);
    

当其中一个值被最大化时,这会阻止手柄发生碰撞:

if (ui.values[0] < 1 && ui.values[1] < 1) 
    ui.values[0] = 0; // why doesn't this work at high speeds?
    ui.values[1] = 1; // why doesn't this work at high speeds?
    $(this).slider("values", 1, 1 + offset);
    return false;
 else if (ui.values[0] > yMax - 1 && ui.values[1] > yMax) 
    ui.values[0] = yMax - 1; // why doesn't this work at high speeds?
    ui.values[1] = yMax;     // why doesn't this work at high speeds?
    $(this).slider("values", 0, yMax - 1 - offset);
    return false;

我无法将最终滑块值重置为其最小值!当您将两个滑块一起快速向右或向左滑动时,值应以 0-1 或 99-100 结束。但是,如果您快速执行此操作,您将获得随机结果。

【问题讨论】:

【参考方案1】:

您的代码实际上是有效的,即使您评论的行也无济于事。如果您在该行之后退出函数,它将按您的预期工作。

$(function() 
  var offset = 3;
  var x = 45;
  var y = 55;
  var yMax = 100;

  $("#value").val(x + " – " + y);

  $("#slider").slider(
    orientation: "horizontal",
    range: false,
    min: 0 - offset, // apply offset to address handle collision
    step: 1,
    max: yMax + offset, // apply offset
    values: [x - offset, y + offset], // apply offset
    slide: function(event, ui) 
      ui.values[0] = ui.values[0] + offset; // apply offset
      ui.values[1] = ui.values[1] - offset;

      // collision/push handler
      if (ui.values[0] >= ui.values[1]) 
        if ($(ui.handle).index() == 0) 
          ui.values[0] = ui.value + offset;
          ui.values[1] = ui.value + offset + 1;
          $(this).slider("values", 1, ui.value + 1 + offset * 2);
         else 
          ui.values[0] = ui.value - offset - 1;
          ui.values[1] = ui.value - offset;
          $(this).slider("values", 0, ui.value - 1 - offset * 2);
        
      

      // replace the section below with this to see the other behavior
      // if (ui.values[0] < 0 || ui.values[1] > yMax)  return false 

      if (ui.values[0] < 1 && ui.values[1] <= 1) 
        ui.values[0] = 0
        ui.values[1] = 1
        // this is supposed to tell the RIGHT slider handle to STOP MOVING 
        // by setting its value to 1, but it doesn't do ANYTHING
        $(this).slider("values", 1, 1 + offset); // why doesn't this line do anything???
        return false;
       else if (ui.values[0] > yMax - 1 && ui.values[1] > yMax) 
        ui.values[0] = yMax - 1
        ui.values[1] = yMax
        // this is supposed to tell the LEFT slider handle to STOP MOVING 
        // by setting its value to 1, but it doesn't do ANYTHING
        $(this).slider("values", 0, yMax - 1 - offset); // why doesn't this line do anything???
        return false;
        
      

      // if (ui.values[0] < 0 || ui.values[1] > yMax)  return false 

      // Try commenting out the above section and replacing
      // it with this one line to see a closer version of the
      // intended behavior. The problem with this implementation
      // is that it misbehaves when the mouse is flicked outside
      // the slider area while pushing both sliders together.





      // update displayed diameter values
      $("#value").val(ui.values[0] + " – " + ui.values[1]);
    
  );
);
body 
  font-family: Helvetica, Arial, sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 70px;


*:focus 
  outline: none;
  -moz-box-shadow: none;
  -webkit-box-shadow: none;
  box-shadow: none;


input 
  font-size: 13px;


input 
  border: 0;
  color: #f6931f;
  text-align: left;


#container 
  display: inline;
  padding: 0 0 25px;
  width: 220px;
  margin-left: 10px;
  border: none;


.ui-slider 
  margin-top: 10px;


.ui-slider .ui-slider-handle 
  height: 19px;
  width: 11px;
  margin-left: -6px;
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div id="container">
  <input type="text" id="value" readonly style="width:75px">
  <div id="slider" style="width:212px;height:11px;"></div>

  <p>
  </p>
</div>

【讨论】:

不完全是......如果你在它们碰撞在一起时向右或向左跑,数字仍然会停留在奇怪的值上。试试看。【参考方案2】:

我想通了,部分感谢 Mouser!

“return false”的问题在于它会暂停整个滑块过程,直到它检测到另一个动作。因此,我需要确保我的代码在调用该函数之前强制满足我想要的条件。我强制显示和值与预期结果匹配,然后调用返回函数。查看我的原始帖子链接以查看它的工作原理!

【讨论】:

以上是关于jQuery UI 滑块:如何使滑块处理冲突在最小值/最大值下很好地工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何使滑块控件的滑块更宽? (使用 MFC)

如何动态更改 jquery ui 滑块的最小值、最大值?

如何使滑块自动移动[关闭]

如何使滑块输入独立于内部的反应变量?

如何使滑块图像更暗?

如何使滑块值保留一位小数?