以非线性方式调整一组相邻div的位置

时间:2013-09-08 17:32:55

标签: javascript jquery html css

这不是一个jQuery问题,因为它是一个整体概念性问题。 在我的例子中,我可以使用以非线性方式设置顶值的div填充容器。 每个值的最高值是根据一个公式计算出来的,该公式考虑了左边一个的顶部位置以及容器的高度(小提琴的第33行)。

//this formula sets the top value for each new child added to the container
//height is 100% of its parent which is 20% of the body
//newOne:last is the most recently added child and will have an initial top value of 10%
parseInt($(this).next().css('top'), 10) / $('#queue').height()) * 75  + (parseInt($('.newOne:last').css('top'), 10) * 2) + '%'

我更偶然地偶然发现它似乎工作'好',但如果优化很明显,请指出:) 我遇到的麻烦是一个优雅的公式,用于如何在拖动事件期间平稳地调整孩子。我认为最高值需要根据对左偏移量的一些操作进行调整,但经过几个小时的实验后,我没有发现任何能够在我开始拖动时保持原始位置不变的东西并在我的过程中继续平滑地调整值拖动。当我向左拖动时,孩子应该逐渐接近最小值10%(左侧偏移为0的孩子将具有10%的最高值),并且当我向右拖动时,逐渐从该顶部值移回其初始位置。

$('#queue').draggable({
    axis: "x",
    scroll: false,
    drag: function(){
        //adjust values of each child
        $('.newOne').each(function(){
            var percentLeft = $(this).offset().left / $('footer').width() * 100
            var thisLeft = parseInt($(this).css('left'), 10) / $(window).width() * 100;
            var thisTop = parseInt($(this).css('top'), 10) / $('#queue').height() * 100;
            if (percentLeft >= 0){
                //top value of each one gradually decreases...
                //as it gets closer to an offset value of 0 and minimum top value of 10%
                //non-linear attempt but not even close
                //$(this).css('top', $(this).css('top', 10 + (thisTop - 10 / thisLeft) + '%'));

                //linear step
                $(this).css({'top': 8 + (percentLeft/2) + '%'});
            }
        });
    }
});

http://jsfiddle.net/5RRCS/17/

P.S。我知道我在这里问了很多,但希望有人能够接受挑战:)

更新 偶然发现了exp方法并做了类似的事情:

adjustTop = function(offset){
    return 100 * (1.0-Math.min(0.98,(0.83 + ( 0.17/ (Math.exp(0.007*offset))) )) ) + '%';
};
$(this).css('top', adjustTop($(this).offset().left) );

1 个答案:

答案 0 :(得分:1)

这是我相信你正在寻找的版本。

我做的第一件事就是重构顶部计算,以便初始化和拖动处理程序都能得到相同的结果。

我没有根据子文档对文档的偏移来计算子div的位置,而是将逻辑更改为相对于容器使用位置。

我还删除了z-index,因为子div已经添加了具有正确堆叠顺序的父级 - 最左边的子级是容器中的最后一个元素。

计算每个孩子的身高取决于#queue当前位置是否位于其原点的左侧或右侧。

我还将迭代逻辑更改为行为相同,以简化计算当前元素的起始偏移量:

$($('.newOne').get().reverse()).each(function (index) {
    $(this).css({
        'background': 'rgba(255,255,255,.80)',
        'top': calcTop($(this), index)
    });
});

定位子元素的代码:

function calcTop($ele, index) {
    var elePositionLeft   = $ele.position().left;
    var queuePositionLeft = $('#queue').position().left;
    var footerWidth       = $('footer').width();
    var queueHeight       = $('#queue').height();
    var distanceToTravel  = queuePositionLeft < 0 ? elePositionLeft : footerWidth - elePositionLeft;
    var percentTraveled   = Math.abs(queuePositionLeft) / distanceToTravel;
    var thisPercentLeft   = (elePositionLeft + queuePositionLeft) / footerWidth;
    var queuePercentLeft  = queuePositionLeft / footerWidth;
    var newTop;

    var myStartOffset = (index + 1) * startOffset;
    var topTravel = queuePositionLeft < 0 ? -myStartOffset + startOffset : (queueHeight - startOffset);

    var linear = false;
    if (linear) {
        newTop = myStartOffset + (topTravel * percentTraveled);
        newTop = newTop > startOffset ? Math.round(newTop) : startOffset;
        return newTop;
    } else {
        if (queuePositionLeft >= 0) {
            newTop = myStartOffset + (topTravel * thisPercentLeft * percentTraveled);
            newTop = newTop > startOffset ? Math.round(newTop) : startOffset;
        } else {
            newTop = myStartOffset + (topTravel * (1+thisPercentLeft) * percentTraveled);
            newTop = newTop < startOffset ? startOffset : Math.round(newTop);
        }
        return newTop;
    }
}

重置功能中还有一个小错误 - 它没有将childCount设置回零:

$('#reset').click(function () {
    $('#queue').empty().css('left', 0);
    childCount = 0;
});

Demo Fiddle