Hashchange历史记录打破iScroll

时间:2014-06-25 16:24:43

标签: javascript jquery iscroll

我使用iScroll创建了以下应用程序:http://preview.na-software.co.uk/Demo/FutureLearning4/#/section-0

当用户左右轻拂或点击底角的箭头时,应用程序会移动内容部分,通过更改哈希值来更新历史记录,以便用户可以来回移动到其他部分并为其添加书签等。

然而!如果您访问类似:http://preview.na-software.co.uk/Demo/FutureLearning4/#/section-2的哈希,然后导航几个部分,然后使用后退按钮,则会出现两个问题:

1。)它滚动到第一个屏幕(即使currentSection正确,并且iScroll已被告知正确的部分)。

2.。)如果多次单击后退或前进按钮,则会停止动画并使其混淆并粘在两个部分之间。

查看代码,看到正确的索引和元素被传递给hashcchange上的iScroll,并且控制台注销了偏移量,我发现问题是因为偏移设置不正确...但是只是执行refresh()不会解决问题,因为它会重置位置。

任何人都可以看到问题出在哪里或者找到解决问题的方法吗?

我应该注意,只有当您在不是第0部分的URL上进入应用程序然后滚动应用程序时,才会发生此错误。这是因为您的交互将正确创建偏移量。但是如果你进入像第3部分这样的URL,那么偏移将是不正确的,因此如果有意义的话,散列更改将无法正常工作。

hashchange方法如下:

// handle hashchange events
$(window).hashchange( function(){

    // read the hash to find out what the new section number is
    var nums = location.href.match(/(section)-\d+/g).map(
        function(x){ return +x.replace(/\D/g,"") }
    );
    // set currentSection
    currentSection = nums[0];

    // if the hashchange was called by user scrolling
    if(hashCalledByScroll){
        // no need to anything as they have already updated hash and scrolled
        hashCalledByScroll = false;
    } else {
        // find the section to scrollTo
        sectionToScrollTo = $('#horizontal > .sections > .section').eq(currentSection).attr('id');
        // tell iscroll to scroll to the section
        horizontal.scrollToElement( '#' + sectionToScrollTo, null, null, true );
    }

    // hide the menu on hashchange
    hideMenu();

});

2 个答案:

答案 0 :(得分:3)

测试您的网站时,我注意到以下情况:每当我通过第3部分访问网站,然后输入第2部分的网址时,导航会将我发送到第0部分。

我相信这与您在1)中遇到的行为相同。

所以我调查并得出以下分析:

在函数horizontal.scrollToElement( '#' + sectionToScrollTo, null, null, true )中 iScroll检索给定utils.offset(el)的{​​{1}} [iScroll.js#772]。这个偏移告诉它,滚动到的元素在哪里。

iScroll遍历元素及其所有 offsetParents 以添加其偏移量。 这个就是破坏的地方:el对其父级有一个负偏移,它不应该有。

反过来,这会弄乱<div class="sections"> - 坐标。

要了解我在说什么:scrollTo

这一切都只是分析。我解决这个问题的方法是避免document.querySelector('.sections').offsetLeft,而是使用scrollToElement()

scrollTo()

因此,只需计算您想要去的部分的位置。

关于2)我不确定是否可以做很多事情。快速跳转打破了许多旋转木马。也许延迟回调 ... } else { // find the section to scrollTo sectionToScrollTo = $('#horizontal > .sections > .section').eq(currentSection).attr('id'); // tell iscroll to scroll to the section var posLeft = -$('#' + sectionToScrollTo)[0].offsetLeft; var posTop = -$('#' + sectionToScrollTo)[0].offsetTop; horizontal.scrollTo(posLeft, posTop, 1000); } // hide the menu on hashchange hideMenu(); }); ,验证当前状态的有效性。

我注意到的另一件事是您可能会意外停止过渡。尝试在转换中途单击,按住并释放光标 - 您需要快速。

希望这有帮助。

答案 1 :(得分:2)

找不到最佳解决方案并且它不能解决主要问题,但它有效。

$(window).hashchange(function () {
    if (hashCalledByScroll) {
        hashCalledByScroll = false;
    } else {
        var hpage = window.location.hash;
        var hpage = hpage.replace('#/section-', ''); //get number of target page
        var cpage = currentSection; //number of current page
        var count = parseInt(hpage) - parseInt(cpage); //difference
        while (count > 0) { //if difference positive: go forward count-times
            horizontal.next();
            count--;
        }
        while (count < 0) { //if difference negative: go backward count-times
            horizontal.prev();
            count++;
        }
    }
    hideMenu();
});

FIDDLE