【问题标题】:Assign index # according to current section根据当前部分分配索引#
【发布时间】:2013-02-20 04:42:48
【问题描述】:

假设我的总宽度为 585 像素。我想将空间分成相等的部分,并在位置内为每个部分分配一个索引值。如果我有 6 个部分,我可以做这样的事情:(按总宽度/部分数量分配)

    //Set up elements with variables
            this.sliderContent = config.sliderContent;
            this.sectionsWrap = config.sectionsWrap;

            //Selects <a>
            this.sectionsLinks = this.sectionsWrap.children().children();

            //Create drag handle
            this.sectionsWrap.parent().append($(document.createElement("div")).addClass("handle-containment")
                                      .append($(document.createElement("a")).addClass("handle ui-corner-all").text("DRAG")));

            //Select handle
            this.sliderHandle = $(".handle");

var left = ui.position.left,
    position = [];

var position = ((left >= 0 && left <= 80) ? [0, 1] :
    ((left >= 81 && left <= 198) ? [117, 2] :
    ((left >= 199 && left <= 315) ? [234, 3] :
    ((left >= 316 && left <= 430) ? [351, 4] :
    ((left >= 431 && left <= 548) ? [468, 5] :
    ((left >= 549) ? [585, 6] : [] ) ) ) ) ) );

        if (position.length) {
            $(".handle").animate({
                left : position[0]
            }, 400);
            Slider.contentTransitions(position);
        }

但是,如果我有 x 个部分怎么办。这些部分只是像

这样的元素
<li><a></a></li>
<li><a></a></li>
<li><a></a></li>

或者

<div><a></a></div>
<div><a></a></div>
<div><a></a></div>
<div><a></a></div>

如何根据.handle 元素的当前左值划分 585px 的总数并在位置上对索引进行分类?我可以通过使用ui.position.left 知道拖动句柄在哪里,我想要的是能够为每个元素设置一个索引,并能够根据句柄在索引元素中的位置为句柄设置动画。由于每个元素都有索引,我稍后调用一个转换方法并传入当前索引 # 以显示。我上面显示的代码有效,但效率不高。我还需要考虑手柄的宽度以适应截面宽度。 http://jsfiddle.net/yfqhV/1/

【问题讨论】:

  • 你如何到达 0/81/199/... 的位置来检查左边的位置?
  • @Raad 第一个是让手柄对齐,199 是 81 + 117 + 1px 边框;其他的都是117加到前面左边。

标签: javascript jquery jquery-ui jquery-animate


【解决方案1】:

好的,问题中的范围数字之间的差异略有不一致,这使得算法很难准确地 [my made-up-word de jour =)]:

  • 81 到 199 = 118
  • 199 到 316 = 117
  • 316 到 431 = 115
  • 431 到 518 = 118

如果您可以对此进行调整,我有一个解决方案 - 它不是特别聪明的 JavaScript,因此可能有更好的方法来做到这一点(SO JS 人,请随时教育我!)但它确实有效。

首先我们需要一个函数来查找数组范围的索引,一个给定的值落入其中(这取代了嵌套的 if-else 简写),然后我们有一个函数来设置位置数组,最后我们可以做到范围搜索并返回相应的值数组。

这个解决方案应该动态处理不同数量的部分,只要这一行:

var len = $("#sectionContainer").children().length;

进行相应调整。唯一可能需要调整的其他值是:

    var totalWidth = 585;
    var xPos = 81;

尽管如果您有可以从中提取值的元素,您可以设置它们,使其更像是一个动态解决方案。

/**
 * function to find the index of an array element where a given value falls
 * between the range of values defined by array[index] and array[index+1]
 */
function findInRangeArray(arr, val){
  for (var n = 0; n < arr.length-1; n++){

      if ((val >= arr[n]) && (val < (arr[n+1]))) {
          break;
      }
  }
  return n;
}

/**
 * function to set up arrays containing positional values
 */
function initPositionArrays() {
    posArray = [];
    leftPosArray = [];

    var totalWidth = 585;
    var xPos = 81;

    var len = $("#sectionContainer").children().length;
    var unit = totalWidth/(len - 1);

    for (var i=1; i<=len; i++) {
      pos = unit*(i-1);
      posArray.push([Math.round(pos), i]);
      xMin = (i >= 2 ? (i==2 ? xPos : leftPosArray[i-2] + posArray[1][0]) : 0);
      leftPosArray.push(Math.round(xMin));
    }
}

var left = ui.position.left;

initPositionArrays();

// find which index of "leftPosArray" range that "left" falls within
foundPos = findInRangeArray(leftPosArray, left);
var position = posArray[foundPos];

if (position.length) {
  $(".handle").animate({
    left : position[0]
  }, 400);
  Slider.contentTransitions(position);
}

我已经设置了一个jsFiddle 来说明。

享受吧!


编辑

我查看了@JonnySooter 自己的答案,虽然它正确计算了定位,但它不会处理可变数量的部分。

要使其适用于任何个部分,handleContainment div(即即时创建)需要动态设置其宽度(通过内联样式)。 这是通过将节数乘以每个节的宽度(实际上与滑块的宽度相同)来计算的。
这一切都是在创建句柄之后完成的,以便可以从“句柄”css 类中提取宽度,这意味着当在 css 级别应用时,对句柄宽度的更改将级联到例程中。

请参阅此jsFiddle,其中可以更改部分的数量并且滑块可以正常运行。

【讨论】:

  • 感谢您的详细回答。我一直在研究一个单独的解决方案并给出了答案。如果可以的话,比较一下两者,看看你有没有其他的建议给我。如果是这样,我可以接受你的回答。
  • 真棒负鼠!我喜欢它并已接受它作为答案。感谢您花时间完成这件事。
【解决方案2】:
var numSections = // ...;
var totalWidth = // ...;
var sectionWidth = totalWidth / numSections;
var index = Math.floor($(".handle").position().left / sectionWidth);
var leftPosition = index * sectionWidth;
var rightPosition = leftPosition + sectionWidth - 1;

【讨论】:

    【解决方案3】:

    更新

    我自己努力寻找解决方案,这就是我想出的:

    function( event, ui ) {
        var left = ui.position.left, //Get the current position of the handle
            self = Slider, //Set to the Slider object cus func is a callback
            position = 1;
            sections_count = self.sectionsLinks.length, //Count the sections
            section_position = Math.floor(self.sectionsWrap.width() / sections_count); //Set width of each section according to total width and section count
    
        left = Math.round(left / section_position); //Set the index
        position = (left * section_position); //Set the left ammount
    
        if(position < section_position){ //If handle is dropped in the first section
            position = 0.1; //Set the distance to animate
            left = 0; //Set index to first section
        }
    
        if (position.length) {
            $(this).animate({
                left : position //Animate according to distance
            }, 200);
            left = left += 1; //Add one to the index so that I can use the nth() child selector later.
            self.contentTransitions(left);
        }
    }
    

    【讨论】:

    • 只是几件事 - 上面的函数缺少名称,您有滑块菜单的 html 示例吗?
    • 问题中的 HTML 是基本模板。我有我正在使用的 html,但我希望它是可变的。我会更新问题。
    • 该函数也是手柄移动事件的回调,所以不需要名字。
    • 噢!是的,当然不是。但是,您发布的代码似乎与 html sn-p 不匹配(例如,没有 sectionLinkssectionsWrap)。你有没有机会 jsFiddle 你在做什么?
    • Doh![2] 应该像 10 年前那样制作小提琴。无论如何,它是。 jsfiddle.net/yfqhV/1
    猜你喜欢
    • 2022-11-23
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多