3

I have ScrollView and sequence of Surface elements in it. I want to be able to scroll to the latest element as soon as it appears in the array.

Here is a demo, I want it to be scrolled just like in any chat application... old surfaces go beyond the scene, and new will be always at the bottom. The question is the same as here: Famo.us how to make a scrollview be filled from bottom to top (or right to left)?

http://jsfiddle.net/LA49a/

Famous.loaded(function () {
    var Engine = Famous.Core.Engine;
    var Surface = Famous.Core.Surface;
    var Scrollview = Famous.Views.Scrollview;
    var Timer = Famous.Utilities.Timer;

    var mainContext = Engine.createContext();

    var scrollview = new Scrollview();
    var surfaces = [];
    var i = 0;

    scrollview.sequenceFrom(surfaces);

    Timer.setInterval(function () {
        var temp = new Surface({
            content: "Surface: " + (i + 1),
            size: [undefined, 50],
            properties: {
                backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
                lineHeight: "50px",
                textAlign: "center"
            }
        });

        temp.pipe(scrollview);
        surfaces.push(temp);
        i++;
        // scrollview.goToNextPage();
    }, 400);

    mainContext.add(scrollview);
});
Community
  • 1
  • 1
Iurii Tkachenko
  • 3,106
  • 29
  • 34

4 Answers4

1

I'm assuming you're putting in a very large, round number to get the scrollview to move to the end, which shows your 'latest' element.

If you've got surfaces that are the same width (assuming an X orientation of the scrollview) you might get a smoother result by checking for the actual number of pixels you need to move to position the last item at the right edge of scrollview. You have the original array that you ran sequenceFrom() on. Multiply the number of items in that by your surface width and subtract pixels for the scrollview's width (which could be set to 'undefined' in which case you'll need to look at the window's width) to adjust for getting the latest element to the right side of the scrollview instead of the left side.

If your surfaces are not the same size, you might change things to track the x-offset of each surface as you add them to the backing array by just adding a property to the surface. Then you could just ask the surface what its offset is and subtract the right amount for the width of the scrollview.

Hope that helps you get closer.

Dan Zaner
  • 159
  • 1
  • 1
  • 9
  • Hey! Thanks for reply! Yes, I'm using `scrollView.setPosition(20000)`. The questions is how I can calculate the offset of the surface when placing it to the sequence, it's not rendered yet. And as I understood, after I get the offset of the surface I need to do something like this: `scrollView.setPosition(surface.offset - scrollview.height)`, correct? :) – Iurii Tkachenko May 19 '14 at 17:43
  • 1
    From your question, I'm worried there may be no good answer. But maybe some more info will help. What are you setting for the 'size' array option when you create each of your surfaces? – Dan Zaner May 21 '14 at 05:22
1

This is supported in the famous-flex ScrollView by setting the alignment property to 1.

See this demo: https://github.com/IjzerenHein/famous-flex-chat

IjzerenHein
  • 2,690
  • 1
  • 17
  • 13
0

Solved, by rotating ScrollView by 180˚ and all surfaces inside it also by 180˚ http://jsfiddle.net/tamtamchik/LA49a/3/

Famous.loaded(function () {
    var Engine = Famous.Core.Engine;
    var Surface = Famous.Core.Surface;
    var Scrollview = Famous.Views.Scrollview;
    var Timer = Famous.Utilities.Timer;
    var Transform = Famous.Core.Transform;
    var StateModifier = Famous.Modifiers.StateModifier;
    var ContainerSurface = Famous.Surfaces.ContainerSurface;

    var mainContext = Engine.createContext();

    var scrollview = new Scrollview();
    var surfaces = [];
    var i = 0;
    var surfaceHeight = 50;

    scrollview.sequenceFrom(surfaces);

    Timer.setInterval(function () {
        var container = new ContainerSurface({
            size: [undefined, surfaceHeight]
        });

        var temp = new Surface({
            content: "Surface: " + (i + 1),
            size: [undefined, surfaceHeight],
            properties: {
                backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
                lineHeight: "50px",
                textAlign: "center"
            }
        });

        var surfaceRotate = new StateModifier({
            transform: Transform.rotateZ(Math.PI)
        });

        var surfacePush = new StateModifier({
            transform: Transform.translate(window.innerWidth, surfaceHeight)
        });

        container.add(surfacePush).add(surfaceRotate).add(temp);
        container.pipe(scrollview);
        temp.pipe(scrollview);
        surfaces.unshift(container);
        i++;
    }, 400);

    var rotate = new StateModifier({
        transform: Transform.rotateZ(Math.PI)
    });

    var push = new StateModifier({
        transform: Transform.translate(window.innerWidth, window.innerHeight)
    });

    mainContext.add(push).add(rotate).add(scrollview);
});
Iurii Tkachenko
  • 3,106
  • 29
  • 34
0

hmm, that's pretty crafty! Its a couple of extra matrices which could get very slow if you have a lot of text content in those nodes tho...

By using a huge number, this is just to force famo.us to scroll to the end of the view, I assume?

if the render had happened you could also:

pos = getPosition(nodeNum)  // for last elements scrollposition
setPosition(pos)

But if the insert happens in same code block as your movement control it's not rendered yet.

There's a complicated workaround offered here using events to trigger the sizing calculation after the deploy/render has occurred: how can we get the size of a surface within famo.us?

and another trick here to make famous recalculate sizes from the inimitable @johntraver how to make famo.us recalculate sizes?

did you also look at Engine.nextTick() or JQuery.deferred ? It seems that immediately after you insert the content there will be a "not rendered" instant but after an update you could get the sizes OK.

Community
  • 1
  • 1
dcsan
  • 11,333
  • 15
  • 77
  • 118
  • 1
    setPosition works with shitty regularity. If your just doing enough on your screen at once it can get cut and only scroll you a partial distance. Had an app with a slider type scroll view only took a few minutes before you caught it on a slow moment and it wouldn't quite make it all the way. – aintnorest Jun 28 '14 at 11:45