Famo.us' Scrollview pagination: How to snap only when NEAR an edge? - famo.us

The Famo.us Scrollview has a pagination feature that allows you to snap to the closest item.
Imagine you have a small container which has items with lots of content.
As soon as you want to scroll down to read the content outside the container, it either snaps back to the top, or snaps to the next item.
Does anybody know how to activate pagination only within a thresshold (X pixels) of an edge? That would be awesome.
Codepen demonstrating the problem here: http://codepen.io/markmarijnissen/pen/AGxaC?editors=001
var scroll = new Scrollview({
paginated: true,
pagePeriod: 500,
pageStopSpeed: 0.01, // mysterious option which might provide solution
pageSwitchSpeed: 100, // mysterious option which might provide solution
});

https://github.com/Famous/famous/blob/master/views/Scrollview.js
The TOLERANCE constant is not configurable yet. But you could easily contribute to make it configurable ;)

Related

ScrollViewReader scrollTo with .center anchor bug?

So I'm try to use ScrollViewReader to programmatically scroll a horizontal scroll view. I thought it would work like scrollToItem with .centeredHorizontally in UIKit, and for the most part it does, but the last few elements in the scroll view are being forcefully scrolled to the center of the screen, despite the fact that the scroll view isn't normally able to scroll that far over (without snapping back after releasing the drag, at least). This ends up creating white space across the trailing half of the screen.
I've seen some other questions about this and it seems like the general opinion is that it's not a bug? On the one hand I suppose we're telling the scroll view to center the item, and it's doing just that -- so, not a bug? On the other hand, that's not how similar functionality worked in UIKit. Also, this behavior is only happening on the trailing end of the scroll view! If it was the intended behavior I would expect that scrolling to the first element in the scroll view using .center anchor would force it into the center of the screen and leave leading white space, but this doesn't happen.
Is there an elegant solution to this? Or do we have to calculate the width of our elements + spacing and figure out based on the screen width whether we should anchor .center or just scroll to the last element with anchor .trailing in order to replicate the UIKit behavior?
I found a package (Amzd/ScrollViewProxy) that was made before ScrollViewReader was released that functions much the same as ScrollViewReader, but also seems to not have the bug (if it is a bug) detailed in the question.
Usage examples can be seen on the repository page, but here's a quick minimal example.
ScrollView(.horizontal) { scrollProxy in
ForEach(sections) { section in
Text(section.text)
.scrollId(section.id)
}
.onChange(of: index) {
scrollProxy.scrollTo(
sections[index].id,
alignment: .center
)
}
}
The package adds a convenience init to ScrollView to give access to the scrollProxy.
I can confirm this behavior and think it should be considered a bug. Especially since the scroll view will "jump" into position on the first touch event.
As of iOS 15.4 Beta 1 this is fixed for me. Maybe give it another try.

How to make a Famo.us Scrollview not bounce

I have a client that doesn't like the bounce effect on the edge hit of the scrollview. So I'm looking to make the scrollview not bounce and act more 'normal'. In truth I'd really like it to bounce but only on the top.
From looking at the scrollview I've got no idea how to do this with a scrollview without heavily modifying it. At that point I'm not sure that using a scroller and a draggable wouldn't be a better solution.
Any thoughts?
Edit: why was this down-voted?
Note that on OS X or iOS this is not possible, as Apple likes the bounce of a page and it is native behaviour. Famous does add on top of that, however, and THAT can be turned off:
for a ScrollContainer:
new ScrollContainer({
scrollview : {
edgeGrip : 1
}
});
for a Scrollview:
new Scrollview({
edgeGrip : 1
});
It's as simple as that ;-)
The scrollview will not bounce anymore unless the operating system wants it to bounce.
I tried Stephan's suggestion to use edgeGrip and it doesn't stop the edge bouncing running under Chrome. The other edge parameters didn't improve the behavior either. However I did find that speedLimit helps to reduce the bounce. Not a perfect solution but it might be enough depending on your requirements.
new Scrollview({
speedLimit: 0.6
});
Update: This doesn't seem to help as much with mobile Chrome :-/

Nest scrollviews with exclusive direction

I want to nest two scrollviews. The outer one should allow only scrolling in x-drection the inner one only y-direction.
It seems that the MouseSync of the inner scrollview always takes the mouse-event and invokes prevent-default regardless of the direction-settings.
How can such behavior be implemented?
I tried to comment first to see your use case but didn't get a response.
I needed something similar to display a list of customers and their data where to see the next customers info the design wanted to be able to scroll right or left while still being able to scroll up or down for more details on that customer. Now you can just pipe the scrollviews together but that gives an odd effect where when you slide your finger down unless its directly down no left right the whole page swivels around. I ended up using a paginated scroll view for x-direction populated by views that where a standard scrollview in the y-direction. Doing it this way I was able to set a some rules that made the left right transition not kick in till after so many pixel drag in that direction.
The codes here:
https://github.com/vizidrix/famous/blob/master/page-swaper/PageSwaper.js
If that isn't what your looking for let me know your use case.

RaphaelJS Multiple animate same element

I currently have the following working fiddle
var moveAnim = Raphael.animation({ progress: 1 }, 5000, 'bounce').repeat(Infinity);
I animate a circle along a line.
I also want to make the circle flash at the same time but I can't seem to work out a way to do this?
I thought about adding the circle to a set and applying the additional animation to this but I can't see to get this either!
Any ideas?
This is a hack and I make no attempt to hide it, but it could be made a bit nicer.
There's a couple of problems depending on 'how' you want to animate the flash. The main problem is having 2 simultaneous animation on the same object, as Raphael doesn't do this (to my knowledge). Its easier if you want to animate an alternate attribute than the same one. If you want to animate a scale to indicate a flash, you will need to append the scale transform to the end of the path transform string ('t,s').
Example here, just uses opacity attribute.
Probably the nicest method would be to include something that figures out time running and amends an attribute manually within the animation function (paper.customAttributes.progress). However, that will probably take a bit longer.
Another alternative could be to animate another object off screen, that does all the calculations for you. It feels a bit ugly, but should work.
So earlier we create a dummy object off screen...
var dummy = paper.circle(-100,-100,10).attr({ opacity: 0 });
Within the progress func, you can then set the real circles opacity to be the same as the offscreen one.
this.attr('opacity', dummy.attr('opacity'));
And we get the dummy animation triggering later
dummy.animate(flashingAnim);
jsfiddle
As mentioned, I think there are cleaner ways, but may involve you writing a small linear animation func separately, but this may help if performance isn't an issue and you don't mind extra elements in the dom.
An alternative solution that I came up with is a looping callback. The very sound of a looping callback sounds ugly but I guess thats what an animation is?
It does appear that you can attach multiple animations to an element! Here's a an example
function animateIn() {
flashingCircle.animate({ fill: '#f00' }, 1000, animateOut);
}
function animateOut() {
flashingCircle.animate({ fill: '#fff' }, 1000, animateIn);
}
animateIn();

Infinite parallax scrolling with famo.us

I have a scrollview and an image as a background in different surface with lower z-index. I want to scroll the image with half the speed of the scrollview.
Any ideas on how to implement it ?
I can't give you a COMPLETE solution, but this should take you down a decent path.
1) Famo.us has worked on multiple scrollViews. Each has a slightly different method to get the 'scrollTop' value from it.
The one created earlier only gives you the scrollTop value for the first visible element in the list. So, in this case you can get how many elements have been scrolled away and calculate the actual value yourself. OR if you have a small, and limited number of the elements in the scrollView you should wrap all the elements in a single view and pass a singleView to the scrollView. This way Famo.us has to do calculations for off-screen elements, but if the number of elements is small enough, it can make many animations/calculations much easier.
The second scrollView was call LimitedScrollView internally. I don't have much experience with it yet, but it should give you the correct values anyway.
2) ScrollView fires events on scroll. use that to update the value of a transitionable.
Pseudo Code:
scrollView.on('scroll', function(){
transitionable.set(scrollView.scrollTop)
});
3) You can now bind the transform value for the background to the transitionable.
Pseudo Code:
background.transformFrom(function(){
return Transform.translate(0, -transitionable.get()/2, 0);
});
Now, things should work correctly.
Hope that helps.