根据按钮点击移动到特定 div

Move to specific div based on button click

我试图根据上一个和下一个按钮移动 div(这里是问题编号)。以便所选问题始终在屏幕上可见。

这是演示:http://jsfiddle.net/arunslb123/trxe4n3u/12/

屏幕:

单击并问题编号,然后单击上一个或下一个按钮以了解我的问题。

我的代码:

$("#next")
.click(function () {
    $(".c.current-question")
        .each(function () {
            var divIdx = $(this)
                .attr('id');
            var scrollTo = $('#' + divIdx)
                .position()
                .left;
            $("#scrollquestion")
                .animate({
                    'scrollLeft': scrollTo
                }, 800);
        });
});

$("#prev")
.click(function () {
    $(".c.current-question")
        .each(function () {
            var divIdx = $(this)
                .attr('id');
            var scrollTo = $('#' + divIdx)
                .position()
                .left;
            $("#scrollquestion")
                .animate({
                    'scrollLeft': -scrollTo
                }, 800);
        });
});

使用scrollLeft有点棘手。我根据定位对您的用例进行了一次小重做,然后根据容器的 left 移动它。棘手的部分是在滚动到最右边时可靠地计算负位置。另外,需要考虑宽度和边距。

检查下面的片段:

var $wrap = $("#numWrap"), $strip = $("#strip"), 
    $leftArrow = $(".wrapper > .arrows").first(), 
    wrapWidth = $wrap.width() + $leftArrow.width(), 
    margin = 10;
    
fill(20); select($(".numberItem").first());

$strip.on("click", ".numberItem", function() { select($(this)); });

function select($elem) {
    $(".numberItem").removeClass("selected");
    $elem.addClass("visited").addClass("selected");
    focus($elem[0]);    
}

function focus(elem) {
    var stripPos = $strip.position(), 
        numPos = $(elem).offset(), 
        elemWidth = $(elem).width() + margin, 
        numRight = numPos.left + elemWidth;
    
    if (numRight > wrapWidth) {
        $strip.css({"left": stripPos.left - elemWidth}); 
    }
    if (numPos.left < (margin + $leftArrow.width()))  {
        $strip.css({"left": stripPos.left + elemWidth}); 
    }
}

$(".wrapper").on("click", "a.arrow", function() {
    var stripPos = $strip.position();
    if (this.id == "lft") {
        $strip.css({"left": stripPos.left + (wrapWidth / 2)}); 
    } else {
        $strip.css({"left": stripPos.left - (wrapWidth / 2)});
    }
});

$(".controls").on("click", "a.arrow", function() {
    var $sel = $(".selected"), numPos, $sel, elemWidth; 
     $elem = $sel.length > 0 ? $sel.first() : $(".numberItem").first();
    if (this.id == "lft") {
        $sel = $elem.prev().length > 0 ? $elem.prev() : $elem;
        select($sel); 
    } else {
        $sel = $elem.next().length > 0 ? $elem.next() : $elem;
        select($sel);
    }
    numPos = $sel.offset(); elemWidth = $sel.width() + margin;
    numRight = numPos.left + elemWidth;
    if (numPos.left > wrapWidth) {
        $strip.css({"left": -($sel.text()) * $sel.width() });
    }
    if (numRight < 0) {
        $strip.css({"left": +($sel.text()) * $sel.width() });
    }
});

function fill(num){
    for (var i = 1; i <= num; i++) {
        var $d = $("<a href='#' class='numberItem'>" + i + "</a>");
        $strip.append($d);
    }
}
* { box-sizing: border-box; padding: 0; margin: 0; font-family: sans-serif; }
div.wrapper { 
    background-color: #ddd; width: 100vw; height: 64px; 
    clear: both; overflow: hidden; margin-top: 16px;
}
div.arrows { 
    float: left; width: 10%; min-width: 24px; height: 64px; line-height: 64px;
    text-align: center; vertical-align: middle; overflow: hidden;
}
div.numWrap { 
    float: left; height: 64px; line-height: 64px;
    width: 80%; vertical-align: middle; 
    overflow: hidden; position: relative;
}
div.strip { 
    position: absolute; left: 0px;
    width: auto; white-space: nowrap; 
    transition: left 1s;
}
a.numberItem { 
    display: inline-block; text-align: center; margin: 0px 8px;
    background-color: #fff; border-radius: 50%; width: 48px; height: 48px; 
    font-size: 1.2em; line-height: 48px; text-decoration: none;
}
a.numberItem.visited { background-color: #fff; color: #000; border: 2px solid #01aebc; }
a.numberItem.selected { background-color: #01aebc; color: #fff; }
div.controls { clear: both; }
div.controls > div.arrows { width: auto; margin: 0 12px; }
a, a:focus, a:active, a:link, a:visited { 
    display: inline-block; 
    text-decoration: none; font-weight: 600; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
    <div class="arrows">
        <a id="lft" class="arrow" href="#">&#x3008;</a>
    </div>
    <div id="numWrap" class="numWrap">
        <div id="strip" class="strip"></div>
    </div>
    <div class="arrows">
        <a id="rgt" class="arrow" href="#">&#x3009;</a>
    </div>
</div>
<div class="controls">
    <div class="arrows">
        <a id="lft" class="arrow" href="#">&#x3008;&nbsp; Previous</a>
    </div>
    <div class="arrows">
        <a id="rgt" class="arrow" href="#">Next &nbsp;&#x3009;</a>
    </div>    
<div>

解释:

  1. 在数字容器上使用absolute定位,嵌套得到100%宽度

标记:

<div class="wrapper">
    <div class="arrows"><a id="lft" class="arrow" href="#">&#x3008;</a></div>
    <div id="numWrap" class="numWrap">
        <div id="strip" class="strip"></div> <!-- nesting here -->
    </div>
    <div class="arrows"><a id="rgt" class="arrow" href="#">&#x3009;</a></div>
</div>

CSS:

div.wrapper { 
    background-color: #ddd; width: 100vw; height: 64px; 
    clear: both; overflow: hidden; margin-top: 16px;
}
div.arrows { 
    float: left; width: 10%; min-width: 24px; height: 64px; line-height: 64px;
    text-align: center; vertical-align: middle; overflow: hidden;
}
div.numWrap { 
    float: left; height: 64px; line-height: 64px;
    width: 80%; vertical-align: middle; 
    overflow: hidden; position: relative; /* relatively positioned */
}
div.strip { 
    position: absolute; left: 0px;        /* absolutely positioned */
    width: auto; white-space: nowrap; 
    transition: left 1s;                  /* instead of jquery animate */
}

有了这个结构,我们现在可以使用left来控制滚动了。

  1. 对于部分被遮挡的数字,请尝试轻轻地将焦点对准(微移到视图中)部分被遮挡的数字。这可以通过检查 position 相对于父级并向其添加 width/margin 并考虑左箭头的宽度(它可能会透过)来完成。

Javascript:

function focus(elem) {
    var stripPos = $strip.position(), 
        numPos = $(elem).offset(), 
        elemWidth = $(elem).width() + margin, 
        numRight = numPos.left + elemWidth;

    // if it is towards right side, nudge it back inside
    if (numRight > wrapWidth) {
        $strip.css({"left": stripPos.left - elemWidth}); 
    } 
    // if it is towards left side, nudge it back inside
    if (numPos.left < (margin + $leftArrow.width()))  {
        $strip.css({"left": stripPos.left + elemWidth}); 
    } 
}
  1. 一旦用户将列表滚动得太远然后尝试单击 上一个/下一个 按钮到 select 个问题,那么我们需要移动整个容器最多 selected 编号。我们可以很容易地做到这一点,方法是将问题编号乘以元素宽度,然后将 left 更改为正数(if 向右 )或负数(if 向右左).

Javascript:

// if left of element is more than the width of parent
if (numPos.left > wrapWidth) {
    $strip.css({"left": -($sel.text()) * $sel.width() });
}
// if right of element is less than 0 i.e. starting position
if (numRight < 0) {
    $strip.css({"left": +($sel.text()) * $sel.width() });
}

这里有一个 fiddle 可以玩:http://jsfiddle.net/abhitalks/aw166qhx/

您需要进一步使其适应您的用例,但您明白了。