1

我正在尝试在 famo.us 中构建一个粘性滚动视图,但我被困在两个地方。

1)正文在标题顶部滚动。当我在将其添加到 _mainScrollview 之前将 Transform.translate(0, 0, 1) 添加到标题时,它什么也不做。

2) 当 _mainScrollview 卡住时,如何保持 _bodyScrollview 的速度?

/***
 * A view that scrolls, sticks the header at stickAt,
 * and then allows the body to scroll.
 */
function Sticky(options) {
    View.apply(this, arguments);

    options = options || {};

    this.options = Object.create(Sticky.DEFAULT_OPTIONS);
    for (var i in Sticky.DEFAULT_OPTIONS) {
        if (options[i] !== undefined) this.options[i] = options[i];
    }

    // setup the scrollviews

    this._bodyScrollview = new Scrollview({});
    this._bodyScrollview.sequenceFrom([this.options.body]);

    this._mainScrollview = new Scrollview({});
    this._mainScrollview.sequenceFrom([this.options.header, this._bodyScrollview]);
    this._eventInput.pipe(this._mainScrollview);

    // track the velocities

    this._mainScrollview.sync.on('update', function (data) {
        this._mainVelocity = data.velocity;
    }.bind(this));

    this._bodyScrollview.sync.on('update', function (data) {
        this._bodyVelocity = data.velocity;
    }.bind(this));

    this.add(this._mainScrollview);
}

Sticky.prototype.render = function () {
    // If the main scrollview is scrolled up (velocity < 0)
    // past the stickAt point, stick it and unstick the body scrollview.
    if (this._mainVelocity < 0) {
        if (this._mainScrollview.getPosition() >= this.options.stickAt) {
            this._eventInput.unpipe(this._mainScrollview);
            this._eventInput.pipe(this._bodyScrollview);

            Tools.forcePosition(this._mainScrollview, this.options.stickAt, true);

            this._mainVelocity = 0;
        }
    }

    // If the main scrollview is scrolled down (velocity > 0)
    // past 0, stick it and unstick the main scrollview.
    if (this._bodyVelocity > 0) {
        console.log(this._bodyScrollview.getPosition());
        if (this._bodyScrollview.getPosition() <= 0) {
            this._eventInput.unpipe(this._bodyScrollview);
            this._eventInput.pipe(this._mainScrollview);

            Tools.forcePosition(this._bodyScrollview, 0, true);

            this._bodyVelocity = 0;
        }
    }

    return View.prototype.render.call(this);
};

/**
 * Force a scrollview to a position
 */
Tools.forcePosition = function (scrollview, position, noSpring) {
    if (noSpring) {
        scrollview._springState = 0;
        scrollview._physicsEngine.detachAll();
    }

    scrollview.setVelocity(0);
    scrollview.setPosition(position);    
};
4

3 回答 3

1

您可以通过使用著名的 flex FlexScrollView 来做到这一点,请参阅此演示:

https://github.com/IjzerenHein/着名-flex-chat

教程:https ://github.com/IjzerenHein/ Famous-flex/blob/master/tutorials/FlexScrollView.md

于 2014-11-08T19:53:34.860 回答
0

1)我怀疑您的标题大小错误并且与主要滚动内容重叠。使用检查器检查并根据需要修改尺寸。(请参阅 Famo.us常见陷阱:为什么我没有获得此点击?

2) 订阅edgeHitScroller 的事件并手动设置速度(就像你停止滚动时所做的那样)。

顺便说一句,而不是这个

ScrollView
    HeaderSurface
    ScrollView
        Content

我会这样布局:

 HeaderSurface
 ScrollView
     HeaderSurface
     Content1
     Content2
     Content3

所以一个 HeaderSurface 在 RenderTree 中被引用了两次。所以我会克隆 HeaderSurface,如果你滚动到某个点,你会显示第一个(粘性)HeaderSurface。这与第二个(滚动查看的)HeaderSurface 重叠。

于 2014-04-22T06:16:34.333 回答
0

1)事实证明这是Chrome的问题,它适用于Safari。解决方法是在正文之后创建标题。

2) 传递速度被证明是困难和复杂的——当我粘贴标题时,身体会反弹,因为它在同一个滚动视图内。

我重建了视图以使用一个带有表示标题的填充节点的滚动视图。然后我根据滚动视图的位置手动转换标题。

HeaderSurface
BodyScrollview
    HeaderFiller
    BodySurface

这是代码:

/***
 * A view that scrolls sticks the header at stickHeaderAt
 * and allows the body to scroll underneath the header.
 */
function Sticky(options) {
    View.apply(this, arguments);

    options = options || {};

    this.options = Object.create(Sticky.DEFAULT_OPTIONS);
    for (var i in Sticky.DEFAULT_OPTIONS) {
        if (options[i] !== undefined) this.options[i] = options[i];
    }

    // Setup the body scrollview.

    // Add a filler node to represent the header.
    // In render we will manually transform the header depending on where the scrollview is.
    var headerFiller = new RenderNode(new Modifier({
        size: this.options.header.getSize()
    }));
    headerFiller.add(new Surface);

    this._bodyScrollview = new Scrollview({});
    this._bodyScrollview.sequenceFrom([headerFiller, this.options.body]);

    this.add(this._bodyScrollview);

    this._eventInput.pipe(this._bodyScrollview);

    // Create a wrapping container surface for the header after
    // the body as a workaround of a bug where chrome does not
    // respect our transform on the header.

    var headerContainer = new ContainerSurface({
        size: this.options.header.getSize(),
        transform: Transform.translate(0, 0, 1)
    });
    headerContainer.add(this.options.header);

    // Setup the header node.

    // Transform the header on top of the body (broken in chrome).
    this._headerModifier = new StateModifier({
        transform: Transform.translate(0, 0, 1)
    });
    var headerNode = new RenderNode(this._headerModifier);
    headerNode.add(headerContainer);

    this.add(headerNode);
}

Sticky.prototype = Object.create(View.prototype);
Sticky.constructor = Sticky;

Sticky.DEFAULT_OPTIONS = {
    header: null,
    body: null,
    stickHeaderAt: 0
};

Sticky.prototype.render = function () {
    // If the body scrollview is on the first page handle sticking / unsticking the header.
    // Otherwise the body is scrolled up enought that the header is already stuck, so ignore it.
    if (this._bodyScrollview._node.getNext()) {
        var scrollviewPosition = this._bodyScrollview.getPosition();

        // Stop the header when the scrollview hits stickHeaderAt.
        if (scrollviewPosition > this.options.stickHeaderAt) {
            this._headerModifier.setTransform(Transform.translate(0, -1 * this.options.stickHeaderAt, 1));
        }
        // When the scrollview is below the stickHeaderAt point
        // move the header with the scrollview.
        else {
            this._headerModifier.setTransform(Transform.translate(0, -1 * scrollviewPosition, 1));
        }
    }

    return View.prototype.render.call(this);
};

/**
 * Reset the header and body to the top.
 */
Sticky.prototype.reset = function () {
    this._headerModifier.setTransform(Transform.translate(0, 0, 1));

    this._bodyScrollview.goToPreviousPage();
    Tools.forcePosition(this._bodyScrollview, 0, true);
};
于 2014-04-23T00:13:23.710 回答