8

When swiping between stories in Instagrams new feature "Stories" (you know that cube-like transition when going from one story to another) I can't manage to understand how they do it!

First of all, if you dig deeper into the functionality you find that it works exactly like the UIPageViewControllers transition:

- It bounces when swiping fast from one view to another.
- You can pause the swipe in the middle of the transition by touching the screen.

The developing team couldn't have used a solution based on the more known workarounds out there, e.g:
https://www.appcoda.com/custom-view-controller-transitions-tutorial/
Because as far as I know my two statement above is not possible to achieve with anything else than the PageViewController.

This leaves me thinking that the Instagram Developer Team gained access to a new transition style for the PageViewController, also known as Cube-scroll, or is it a workaround that I'm not aware of?

Any ideas?

alengqvist
  • 491
  • 5
  • 15
  • 1
    Not sure how your two points imply `UIPageViewController`. Watching [here](https://developer.apple.com/videos/play/wwdc2016/216/) explains how to make interactive, interruptible custom transitions between any two view controllers. – beyowulf Sep 29 '16 at 21:52
  • With the first point I mean when doing a fast swipe gesture, the paging to the next view takes place, but because the swipe gesture is so fast the paging also bounces in to the next view after so some pixel of that view also is displayed, before bouncing back to the correct view. That behavior is something I have only seen in the UIPageViewController or ScrollViews with paging enabled. I will have a look at the video. I intend to find a working solution for this, so I would appreciate an answer or some tips on how to solve it. – alengqvist Sep 29 '16 at 22:30

2 Answers2

8

I took a shot at recreating this functionality a while back. You can check the source code on GitHub: https://github.com/oyvind-hauge/OHCubeView

I'm using a scroll view (with paging enabled) and, for each subview I'm manipulating these as a function of the given view's current x-offset in the scroll view. The actual animations are done on each subview's layer using Core Animation (more specifically, transforming an identity matrix, given by CATransform3DIdentity, using the method CATransform3DRotate).

The shadow effects are also applied to the subview's layers (view.layer.opacity), with the amount of shadow determined by how much of the view is showing on screen.

My implementation solves both of your concerns (bounces when swiping, can pause swipes). I'm sure this could have also been implemented using the a UIPageViewController, but I hate working with those.

oyvindhauge
  • 3,496
  • 2
  • 29
  • 45
  • Do you know how to make this work with ios 8? Is there any way I can modify it? I really want to use this, it's perfect for what I'm doing, but really want to keep my app compatible for ios 8. – Wayne Filkins Nov 28 '16 at 23:44
  • That's great that you want to use it. It's been a while since I looked at the code, but let me get back to you on this. – oyvindhauge Nov 29 '16 at 09:05
  • 1
    @WayneFilkins, so the reason why I cannot support iOS 8 is because I'm using UIStackView, which is only available from iOS 9. This class is not easily removed, since it is a fundamental part of the implementation. Sorry about this. – oyvindhauge Nov 29 '16 at 09:21
  • I can't seem to get your component to work. I fixed most of the swift issues as i'm compiling with xcode 9/swift3 but when I run my app, the subviews x coordinates are offset by half the screen width. There seems to be a problem in the setAnchorPoint method? I cannot figure it out. Any idea what I might have done wrong? I have followed the setup process as shown on the github page. – Jovan Oct 23 '17 at 12:56
  • Hi @Jovan! Let me take a look at this when I get back from work. I’ll let you know here. – oyvindhauge Oct 23 '17 at 12:58
  • 1
    @Jovan I updated the repo to support Swift 3.x (if you are using pods you can pull version 1.0.1). – oyvindhauge Oct 23 '17 at 19:57
  • Thank you for the quick response! I'll have a look right away. cheers – Jovan Oct 24 '17 at 09:58
  • Can this effect be created using javascript and css? Thanks – user1788736 Jun 15 '20 at 21:45
  • @user1788736 yeah it can probably be done using a html5 canvas and some 3d js lib, but I have little js experience so I wouldn't be able to help you. – oyvindhauge Jun 16 '20 at 13:47
0

I think you are overthinking the controller's part here. The effect can easily be achieved using a CATransformLayer and three-sided cube-like view structure, where there is one view which aligns with the screen plane, and two others rotated -90 and 90 degrees on their y axis. Then, getting a pan gesture to rotate the scene. After a successful 90 degree turn (in either direction), you can either quickly reset the scene (so that keeping on rotating appears as if continues, but actually the camera shifted back to initial position) or you can have a full 360 degree rotation, and just update previous and next "pages". A single controller can handle this scene. If you prefer to have each page as a controller, it is possible, you can still use one controller for the scene, and then use the page controllers as child controllers, and setting their views as described above.

See this article for more information on CATransformLayer. Their example already creates something that is quite close to what you need.

Léo Natan
  • 56,823
  • 9
  • 150
  • 195