我正在尝试在famo.us中构建一个Sticky scrollview,我在两个地方陷入困境。
1)身体在标题顶部滚动。当我将一个Transform.translate(0,0,1)添加到标题中,然后将其添加到_mainScrollview之前,它什么也没做。
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);
};
答案 0 :(得分:1)
您可以使用着名的Flex FlexScrollView执行此操作,请参阅此演示:
https://github.com/IjzerenHein/famous-flex-chat
教程:https://github.com/IjzerenHein/famous-flex/blob/master/tutorials/FlexScrollView.md
答案 1 :(得分:0)
1)我怀疑你的标题大小是错误的并且与主要滚动内容重叠。检查使用检查器并根据需要修改大小。 (参见Famo.us Common pitfalls: Why am I not getting this click?)
2)订阅滚动条的edgeHit
事件并手动设置速度(就像停止滚动条时一样)。
ScrollView
HeaderSurface
ScrollView
Content
我会这样布局:
HeaderSurface
ScrollView
HeaderSurface
Content1
Content2
Content3
因此,在RenderTree中引用了两个HeaderSurface。因此我将克隆HeaderSurface,如果滚动经过某个点,则显示第一个(粘性)HeaderSurface。这与第二个(scrollviewed)HeaderSurface重叠。
答案 2 :(得分:0)
1)这对Chrome来说是一个问题,它适用于Safari。解决方法是在正文后创建标题。
2)绕过速度传递被证明是困难和复杂的 - 当我坚持标题时,身体会反弹,因为它在同一个滚动视图内。
我重建了视图以使用一个带有表示标题的填充节点的scrollview。然后我根据scrollview的位置手动转换标题。
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);
};