3

ここの最初のページで問題を簡単に見ることができます:http://m.vancouverislandlife.com/

下にスクロール(上にスライド)して、コンテンツがページを離れることを許可します。コンテンツが跳ね返ることはなく、永久に失われます。ただし、コンテンツページにあふれ、スクロール可能であると想定されるページでは、スクロールは正しく機能します(この例については、[宿泊施設]> [b&b]を参照し、下にスクロールしてください)。

私のコンピューターでは、最初のページのスクロールが常にで止まっていることに気づきました-899px。この問題を経験した人を他に見つけることができず、何をしようとしても、それを修正することはできません!ヘルプ!

(ただし、iPhoneやiPod Touchのターゲットオーディエンスは、画面のスペースが非常に少ないため、これによる影響を受けないため、必ずしも緊急ではありません。)

さて、新しい問題。iScrollの問題を解決するために、カスタムスクリプトを作成しました。ただし、実際のデバイスでは正しく機能していません。デスクトップブラウザでは、問題なく動作します。モバイルでは、時々トップに戻って、いくつかのタッチを認識しません。これはおそらく、デフォルトのイベントをキャンセルし、少しハックする必要があったためです。どうすればこれを修正できますか?(うん-+500の賞金の単純な問題。悪くないね?)

スクリプトは次のとおりです。Webサイトは通常の場所にあります。

function Scroller(content) {
    function range(variable, min, max) {
        if(variable < min) return min > max ? max : min;
        if(variable > max) return max;
        return variable;
    }

    function getFirstElementChild(element) {
        element = element.firstChild;

        while(element && element.nodeType !== 1) {
            element = element.nextSibling;
        }

        return element;
    }

    var isScrolling = false;
    var mouseY = 0;
    var cScroll = 0;
    var momentum = 0;
    if("createTouch" in document) {
        content.addEventListener('touchstart', function(evt) {
            isScrolling = true;
            mouseY = evt.pageY;
            evt.preventDefault();
        }, false);
        content.addEventListener('touchmove', function(evt) {
            if(isScrolling) {
                evt = evt.touches[0];

                var dY = evt.pageY - mouseY;
                mouseY = evt.pageY;
                cScroll += dY;
                momentum = range(momentum + dY * Scroller.ACCELERATION, -Scroller.MAX_MOMENTUM, Scroller.MAX_MOMENTUM);

                var firstElementChild = getFirstElementChild(content);

                content.style.WebkitTransform = 'translateY(' + range(cScroll, -(firstElementChild.scrollHeight - content.offsetHeight), 0).toString() + 'px)';
            }
        }, false);
        window.addEventListener('touchend', function(evt) {
            isScrolling = false;
        }, false);
    } else {
        content.addEventListener('mousedown', function(evt) {
            isScrolling = true;
            mouseY = evt.pageY;
        }, false);
        content.addEventListener('mousemove', function(evt) {
            if(isScrolling) {
                var dY = evt.pageY - mouseY;
                mouseY = evt.pageY;
                cScroll += dY;
                momentum = range(momentum + dY * Scroller.ACCELERATION, -Scroller.MAX_MOMENTUM, Scroller.MAX_MOMENTUM);

                var firstElementChild = getFirstElementChild(content);

                content.style.WebkitTransform = 'translateY(' + range(cScroll, -(firstElementChild.scrollHeight - content.offsetHeight), 0).toString() + 'px)';
            }
        }, false);
        window.addEventListener('mouseup', function(evt) {
            isScrolling = false;
        }, false);
    }

    function scrollToTop() {
        cScroll = 0;
        content.style.WebkitTransform = '';
    }

    function performAnimations() {
        if(!isScrolling) {
            var firstElementChild = getFirstElementChild(content);
            cScroll = range(cScroll + momentum, -(firstElementChild.scrollHeight - content.offsetHeight), 0);
            content.style.WebkitTransform = 'translateY(' + range(cScroll, -(firstElementChild.scrollHeight - content.offsetHeight), 0).toString() + 'px)';
            momentum *= Scroller.FRICTION;
        }
    }

    return {
        scrollToTop: scrollToTop,
        animationId: setInterval(performAnimations, 33)
    }
}

Scroller.MAX_MOMENTUM = 100;
Scroller.ACCELERATION = 1;
Scroller.FRICTION = 0.8;
4

6 に答える 6

4

#wrapperAndrewは、 divの高さの設定に関して正しい方向に進んでいたと思います。彼がそれを指摘したように、

that.maxScrollY = that.wrapperH - that.scrollerH;

通常、これは機能します。しかし、に変更#contentしたposition: fixedので、ラッパー要素はコンテンツを「ラップ」しなくなりthat.wrapperH、値は0になり、問題が発生します。

免責事項:スクリプト全体を確認しなかったため、ここで間違っている可能性があります

高さを手動で設定すると#wrapper、たとえば500px、次のようになります。

that.maxScrollY = 500 - that.scrollerH;

ここでの愚かさは、コンテンツが多く、ウィンドウが小さい場合that.scrollerH、値が比較的500に近いこと700pxです。2つの違いは、200px200ピクセルしかスクロールできないため、フリーズしたように見えます。これは、その値をどのように設定するかということmaxScrollYです。

解決策(少なくともChromeブラウザの場合):

事実上コンテンツが含まれていないため#wrapper、計算に使用することはできません。これで、これらのディメンションを確実に取得できる唯一のものが残ります#content。この特定のケースでは、content要素のscrollHeightyieldを使用すると必要なものが得られるようです。これはおそらく、期待される動作をするものです。

that.maxScrollY = that.scrollerH - that.scroller.scrollHeight;

scrollerHoffsetHeight、ウィンドウに表示されるおおよその高さです。scroller.scrollHeightスクロール可能と見なされる高さです。コンテンツがページの長さを超えない場合、それらは互いにほぼ同等です。それはスクロールがないことを意味します。コンテンツが多い場合、これら2つの値の違いは、必要なスクロールの量です。

まだマイナーなバグがあり、これはすでに存在しているようです。コンテンツが多い場合、最後のいくつかの要素は、一番下までスクロールするとバーで覆われます。これを修正するには、次のようなオフセットを設定できます。

that.maxScrollY = that.scrollerH - that.scroller.scrollHeight - 75;

75という数字は任意です。少しパディングするために2または3ピクセルのバー自体の高さである場合は、おそらく最適です。幸運を!

編集:

昨夜言及するのを忘れましたが、この問題をデバッグするために使用した2つのサンプルページを次に示します。

長いページ
短いページ

于 2011-08-25T06:26:53.687 に答える
1

ラッパーdivの高さは0のようです。したがって、すべての計算は負であり、その高さをウィンドウの高さに設定すると、スクロールの問題が修正されます。firebugとchromesデバッグバーを使用してラッパーの高さを手動で設定すると、スクロールが正常に機能します。

#content divのサイズはサイズ変更時に変更されるようです。おそらく、#wrapper divのサイズを変更してから、#contentにサイズを継承させることをお勧めします。

[編集] あなたは私を信じていないのでcodez、iscroll-lite.jsから

refresh: function () {
  var that = this,
      offset;
  that.wrapperW = that.wrapper.clientWidth;
  that.wrapperH = that.wrapper.clientHeight;
  that.scrollerW = that.scroller.offsetWidth;
  that.scrollerH = that.scroller.offsetHeight;
  that.maxScrollX = that.wrapperW - that.scrollerW;
  that.maxScrollY = that.wrapperH - that.scrollerH; 

に変換されるあなたのページでは、

that.wrapperH = 0;
that.maxScrollY = -that.scrollerH

スクロールが終了すると、このコードが呼び出されます。

var that = this,

resetX = that.x >= 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x,
resetY = that.y >= 0 || that.maxScrollY > 0 ? 0 : that.y < that.maxScrollY ? that.maxScrollY : that.y;
...
that.scrollTo(resetX, resetY, time || 0);

ほらthat.maxScrollY > 0 ??maxScrollYが負の場合、上にスクロールしても元に戻ることはありません

于 2011-08-23T19:28:58.447 に答える
1

これはCSSの問題である可能性があります。スタイルシート(mobile.cssの22行目)で、position:fixedから削除してみてください#content

これにより、ドキュメントを正常にスクロールできるようになります(コンピューターでは垂直スクロールバー、モバイルブラウザーでは「スライド可能」)。

ドキュメントの通常のフローを終了する要素position:fixedは、ブラウザウィンドウを基準にして配置されます。これがおそらく、スクロールに問題がある理由です。固定位置は通常、ページがスクロールされた場合でも(つまり、ページの上部に「固定」された通知バー)、常に同じ場所にとどまる必要がある要素に使用されます。

于 2011-08-23T19:42:40.357 に答える
1

明確な解決策はありませんが、私が目指す方向はもっとあります:#wrapperと#contentのオーバーフロー:隠されたペアの#contentの位置:修正されており、問題の原因のようです。

position:fixedが#contentから削除されている場合、スクロールは可能ですが、「空白」のdivが誤って階層化されています(Firefox 5でテスト済み)。

于 2011-08-23T20:04:37.690 に答える
0

変更された質問は、新しい回答を保証します。コードを見てみると、「移動」関数の各ステップで運動量を計算していることがわかりました。移動が終了した後に勢いが使用されるため、これは意味がありません。これが意味するのは、最初にマウスの位置をキャプチャし、最後に差を計算することでした。そこで、2つの新しい変数を追加しました。

var startTime;
var startY;

スタートイベント(マウスダウン/タッチスタート)の中に、私は追加しました、

startY = evt.pageY;
startTime = evt.timeStamp || Date.now();

次に、エンドハンドラー用に次のものがあります。

var duration = (evt.timeStamp || Date.now()) - startTime;
if (duration < 300) {
    var dY = evt.pageY - startY;
    momentum = range(momentum + dY * Scroller.ACCELERATION, -Scroller.MAX_MOMENTUM, Scroller.MAX_MOMENTUM);
} else {
    momentum = 0;
}

また、mousemove/touchmoveの内部から運動量計算を削除しました。これを行うと、iPhoneで見られたジャンプ動作が削除されました。他の望ましくない動作(ウィンドウ全体が「スクロール」する)も見られますが、あなたはそれらを取り除くために働いていると思いますので、私は試みませんでした。

幸運を。これは、テスト用に複製したコード化されたページです。また、このセクションのコードを自由にリファクタリングして、重複したコードを削除しました。あなたがそれを見たいならば、それはmobile3.jsの下にあります。

于 2011-08-31T06:28:44.087 に答える
0

スクロールを処理するための独自の小さなスクリプトを作成することになりました。

// A custom scroller
function range(variable, min, max) {
    if(variable < min) return min > max ? max : min;
    if(variable > max) return max;
    return variable;
}

var isScrolling = false;
var mouseY = 0;
var cScroll = 0;
if("createTouch" in document) {
    // TODO: Add for mobile browsers
} else {
    content.addEventListener('mousedown', function(evt) {
        isScrolling = true;
        mouseY = evt.pageY;
    }, false);
    content.addEventListener('mousemove', function(evt) {
        if(isScrolling) {
            var dY = evt.pageY - mouseY;
            mouseY = evt.pageY;
            cScroll += dY;

            var firstElementChild = content.getElementsByTagName("*")[0];

            content.style.WebkitTransform = 'translateY(' + range(cScroll, -(firstElementChild.scrollHeight - content.offsetHeight), 0).toString() + 'px)';
        }
    }, false);
    window.addEventListener('mouseup', function(evt) {
        isScrolling = false;
    }, false);
}

他のいくつかの部分を変更します。ダウンロード時間も大幅に節約できると思います。

ただし、5日以内に回答を受け付けて賞金を授与する予定です。

于 2011-08-25T21:35:44.427 に答える