水平单页网站:Mobile-Webkit 滚动和滑动问题

Posted

技术标签:

【中文标题】水平单页网站:Mobile-Webkit 滚动和滑动问题【英文标题】:Horizontal One-Page Site: Mobile-Webkit Scrolling & Swiping Issues 【发布时间】:2014-03-27 02:15:18 【问题描述】:

这是我正在使用的基本演示:http://jsfiddle.net/3N8wY/9/

问题 #1

如果您从普通的 android 浏览器或(更重要的是)ios 设备查看该链接,则该网站将不会滚动。它会做这种奇怪的烦躁/脉冲的事情,而且无处可去。如果您选择向下的链接方式,它有时会滚动,但它永远不会出现在正确的位置。

我相信这与 JS 有关。当我在手机上尝试时,我注意到它没有散列所选链接的新值。

JS

$(document).ready(function () 
    $('.main-nav').on('click', function (e) 
        e.preventDefault();
        var toTarget = $(this).attr('href');
        history.pushState(null, null, toTarget);
        $(window).triggerHandler('hashchange');
    );
);

$(window).on('hashchange', function () 
    if(!window.location.hash) return;
    var $target = $(window.location.hash);
    console.log($target);
    $('html, body').stop().animate(
        scrollLeft: $target.offset().left,
        scrollTop: $target.offset().top
    , 900, 'swing');
);

感谢 JS - Horizontal One-Page site won't go "backwards" to previous DIV


问题 #2

如果您向左或向右滑动一点,它会移动页面。我不要那个。将溢出设置为隐藏对滑动没有帮助。

理想情况下,如果用户向右或向左滑动足够多,它会向所需方向“捕捉”页面,然后推送正确的哈希值。如果他们没有足够的滑动,它会迅速回到当前页面。

话虽如此,如果它根本不动,我会很高兴的。我曾设想用户将使用菜单进行导航,并且只能上下滚动。

有点跑题

有没有人推荐一款桌面浏览器,它可以与 iOS 设备中的浏览器非常相似?我相信驱动股票 Android 浏览器的 webkit 非常相似,所以我想如果我能得到它进行测试,我会在这里杀死两只鸟。在另一个项目中,我注意到我的桌面版 Safari 似乎提供了与我在 iOS 设备上发现的非常不同的结果(绝对定位的元素在每个浏览器中的“top/margin-top”表现不同)。

非常感谢您的阅读和贡献!我非常感激和感激。

【问题讨论】:

【参考方案1】:

问题 #1

原来我没有正确安装 Modernizr(没有在 html 标记中包含 no-js 类),一旦纠正,解决了我在一些股票 Android 浏览器上遇到的哈希问题。

修复后,我仍然遇到奇怪的滚动行为。通常,页面会滚动到所需的位置,然后又跳回来。经过进一步研究,我发现了这个: Jquery Animate ScrollLeft doesnt work on ipad.

这似乎解决了一些表现不佳的人不希望出现的滚动行为,但在 iOS 设备上却没有。这可能与它有关,ScrollLeft and ScrollTop on Ipad using animate chain (jQuery),但我想出了其他可行的方法(将在下面发布)。

据我所知,iOS 设备 (7+) 在任何 scrollLeft 动画之前会自动滚动到顶部。我无法使用任何物理设备,但我可以使用 iMac,在那里我可以使用 iOS 模拟器并观察到不需要的滚动行为。我尝试取消两个滚动操作的链接(左和上,因为大多数帖子会建议您尝试),但这并没有什么不同。

这可能与我滚动的内容(即正文或 html)有关,我在几篇文章中读到过,但弄乱了它并没有得到有用的结果。

在测试时,我意识到只向左滚动,我的脚本终于“正常”运行了。

有趣的是我注意到浏览器会自动滚动到顶部水平滚动到我的目标。因此,如果他们更新代码以使 scrollLeft 功能正常,我将不得不返回并添加一个 scrollTop 功能。暂时……

不完全是“修复”(浏览器的行为不恰当地为我的“利益”工作,令人担忧),但我会接受。

问题 #2

澄清一下,解决这个问题特别棘手,因为页面需要能够左右滚动(水平布局等等),但只有在我想要的时候。

就尝试禁用滑动而言,我确实做得很短。我最接近那里的是一个名为 touchSwipe 的插件;但是,这破坏了太多(某些移动浏览器中的 CSS 布局),我似乎无法重新启用对非链接('a')资产的点击。

我最终做的是创建一个函数来监控窗口的水平滚动位置,并在窗口发生变化时重新定位窗口。在某些浏览器中似乎有点错误,但似乎我已经接近让“每个人”都开心了。

编辑:将函数更改为更兼容的 window.scrollTo(),只需要在我触发它之前获取位置。还没有测试过不喜欢它的浏览器(到目前为止,手指交叉)。

旁注

最后,当我进行 RWD 测试时...

我被 Chrome 的“调整窗口大小”插件宠坏了,并没有意识到其他浏览器的工作插件的可用性不佳。因此,我创建了一个包含 20 个左右不同比例的 iframe 的测试平台,以匹配最流行的设备尺寸。

当我谈到移动设备尺寸时,我意识到浏览器的滚动条扭曲了我的比例。我之前研究过自定义滚动条,所以我深入研究它以尝试在整个字段中均衡变量。

在尝试了许多不同的插件之后,“nicescroll”是我唯一可以正常工作的插件(http://nicescroll.areaaperta.com/)。如果您要使用它,请务必运行移动测试 (http://www.detectmobilebrowsers.com/),并且仅在非移动设备上运行它(诚然,此脚本似乎无法在某些移动浏览器上运行,但它比没有)。我测试的所有移动浏览器都已经有一个类似的滚动条(默认情况下),所以完全没有必要(而且它会破坏一些移动浏览器)。

工作 JS

$(document).ready(function() 

    var loadedTarget = $(window.location.hash);

    function unbindWindow()  $(window).unbind('scroll'); 

    function repositionWin() 
        unbindWindow();
        var targetPosLeft = loadedTarget.offset().left;
        $(window).on('scroll', function(e) 
            var alteredPosLeft = $(window).scrollLeft();
            var alteredPosTop = $(window).scrollTop();
            if (alteredPosLeft != targetPosLeft) 
                window.scrollTo(targetPosLeft, alteredPosTop),
                unbindWindow(),  // MAY BE UNNECESSARY, IOS SCARED ME INTO IT, SAME AS BELOW 
                repositionWin();
                       
        );
    

    function browserResult() 
        if (jQuery.browser.mobile === true) 
            $('body').css("overflow-x":"hidden","overflow-y":"scroll");
            repositionWin();
        
        else 
            setTimeout ((function()
                $("html").niceScroll(
                    cursorcolor: '#231f20',
                    cursoropacitymax: '0.5',
                    scrollspeed: '100',
                    mousescrollstep: '50'
                );
            ), 300);
            setTimeout (repositionWin, 300);
        
    
    browserResult();

    $('.main-nav-link').click(function(e)      
        e.preventDefault();
        var toTarget = $(this).attr('href');
        history.pushState(null, null, toTarget);

         // CODE SPECIFIC TO PROJECT (NAMELY FLEXSLIDER PAUSE/PLAY STUFF) OMITTED

        $(window).triggerHandler('hashchange');         
    );

);

$(window).on('hashchange', function () 

    if(!window.location.hash) return;
    var target = $(window.location.hash);
    var targetHash = window.location.hash;

    var iOS = ( navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false );

    var currentPosition = $(window).scrollLeft();

    var targetPosLeft = target.offset().left;

    var targetPosTop = target.offset().top;

    function unbindWindow()  $(window).unbind('scroll'); 

    function repositionWin() 
        unbindWindow();
        $(window).on('scroll', function() 
            var alteredPosLeft = $(window).scrollLeft();
            var alteredPosTop = $(window).scrollTop();          
            if (alteredPosLeft != targetPosLeft) 
                window.scrollTo(targetPosLeft, alteredPosTop),
                unbindWindow(),
                repositionWin();
                       
        );
    

    function fadePages() 
        if (targetPosLeft == currentPosition) 
        
        else 
            function fadePageOut() 
                $('.page-container').stop(true,false).animate(
                    opacity: "0.25",
                    transition: "opacity 0.1s 0.0s ease"
                );
            
            function fadePageIn() 
                $('.page-container').stop(true,false).animate(
                    opacity: "1.0",
                    transition: "opacity 0.3s 0.0s ease"
                );
            
            fadePageOut();
            setTimeout (fadePageIn, 900);
        
    

    function pageChange() 
        if (jQuery.browser.mobile === true) 
            if (iOS === true) 
                unbindWindow();
                $('html,body').stop(true,false).animate(
                    scrollLeft: targetPosLeft, 1400);
                    setTimeout (repositionWin, 1500);
            
            else 
                unbindWindow();
                $('html,body').stop(true,false).animate(
                    scrollLeft: targetPosLeft, 1200, function() 
                        $(this).stop(true,false).animate(
                            scrollTop: targetPosTop
                        , 200, repositionWin);
                );
            
        
        else 
            fadePages();
            unbindWindow();
            $('html,body').stop(true,false).delay(100).animate(
                scrollLeft: targetPosLeft,
                scrollTop: targetPosTop
            , 1300, repositionWin);
        
    


            // WAITING FOR OTHER ANIMATIONS TO COMPLETE SO THAT MOBILE DEVICES AREN'T TOO OVERLOADED

    if ($('#mini-site-menu-button-container').is(':visible') === true && $('#main-menu-wrapper').hasClass('show-main-menu') === true) 
        setTimeout (pageChange, 300)
    
    if ($('.footer-container').is(':visible') === true)  
        setTimeout (pageChange, 500)
    
    if ($('.form-instructions-wrapper').hasClass('expand-form-instruct') === true) 
        setTimeout (pageChange, 500)
    
    if ($('.quick-quote-container').hasClass('toggle-open') === true) 
        setTimeout (pageChange, 500)
    
    if ($('#mini-site-menu-button-container').is(':visible') === false && $('.footer-container').is(':visible') === false && $('.form-instructions-wrapper').hasClass('expand-form-instruct') === false && $('.quick-quote-container').hasClass('toggle-open') === false) 
        pageChange();
    
    if ($('#main-menu-wrapper').hasClass('show-main-menu') === false && $('.footer-container').is(':visible') === false && $('.form-instructions-wrapper').hasClass('expand-form-instruct') === false && $('.quick-quote-container').hasClass('toggle-open') === false) 
        pageChange();
    

);

干杯。

我会随着时间的推移进行更新,或者如果我找到更好的解决方案来解决这两个问题。在此之前,我实际上编写任何自己的代码(这不全是“我的”)的编程经验为零(更改选择器几乎是我的“技能”的范围),所以请原谅任何明显的错误。

【讨论】:

以上是关于水平单页网站:Mobile-Webkit 滚动和滑动问题的主要内容,如果未能解决你的问题,请参考以下文章

css 根据窗口和滚动滑入和滑出文本

10款流行的 jQuery 插件

10款流行的 jQuery 插件

效果超赞的单页jQuery插件

使用箭头按钮水平滚动窗口

在颤动的webview中禁用水平滚动