How do I set fire to a UIView in Swift? - ios

How do I produce an animation that simulates the burning effect of fire consuming an UIView from top to bottom in Swift?
I found Fireworks, an app that allows users to tweak and try out different settings of CAEmitterLayer with instant results. The effects are great for applying to a whole screen but how would I use it for my purpose - where the UIView must disappear as the fire consumes it from one end to the other?
Is there some tutorial on consuming UIViews with fire using the particle emitter anywhere? I know that I’m supposed to show some code but anything I put here would be irrelevant. I’ve also exhausted my search engine looking for something similar. That’s how I found the Fireworks app actually.
This seems to be a use case that shouldn't be uncommon.

I haven't done much with CAEmitterLayer, so I decided to try my hand at this.
I created a project that does this an posted it on Github. It uses the approach in this Youtube video as a starting point. You can download it here:
FireEmitter project
Here is a small thumbnail of what it looks like:
The project includes a custom subclass of UIView called BurnItDownView
The BurnItDownView is meant to contain other views.
It has one public method, burnItDown(). That triggers the animation.
There are multiple parts to the animation:
A CAEmitterLayer set up to simulate flames burning off a flat surface:
An animation that lowers the emitter layer from the top of the view to the bottom,
A CAGradientView applied as a mask to the view that starts ot fully opaque (with colors of [.clear, .white, .white] and locations of [-0.5, 0, 1] (where the clear color is above the top of the view) and animates the locations property of the gradient view to mask away the view contents from top to bottom. (Animating the locations property to [0, 0, 0], so the entire gradient layer is filled with clear color, fully masking the view's layer.)
Once the view is fully masked, it starts lowering the "birthRate" of the emitter layer in steps until the birth rate is 0. It then holds this step for 2 seconds until all the flame particles have animated away.
Once the flame is fully "extinguised", it resets the locations array to the original value of [-0.5, 0, 1]. This causes an "implicit animation" so the view animates back from the bottom, but quickly
Finally, it resets the emitter layer and emitter cells back to newly a newly created emitter layer and emitter cell to get it ready for the next pass of the animation. (I couldn't figure out how to restore the emitter back to its original state. It was simpler to just create new ones.) It also invokes an Optional completion handler passed to the burnItDown() method. (The app's view controller uses the closure to re-enable the "Burn it down" button.

I was once in your shoe before and came across this Open source library called particle animations.
I would NOT recommend using the library itself since it's deprecated. But I would recommend referring to its source code to get an idea of how to use CAEmitterLayer and CAEmitterCell to make the looks of a Fire!
As you could see from its readme, it has direct examples of Fire. It also states that even Apple and Facebook uses CAEmitterLayer and CAEmitterCell to produce the effect of a fire.
Feel free to ask for more questions.

Related

AVPlayerLayer Popgesture Glitch

EDIT: https://bitbucket.org/KevinvandenhoekBeast/avplayerlayerpopgesture/overview <-- A simple sample project that recreates the problem, click on the video to push the detailviewcontroller, then popgesture back. The animations happen in the NavigationAnimator, and the popgesture logic is in the NavigationInteractor. The NavigationTransitioningView protocol defines the methods that are used by the animator to transition the video from one frame to the other.
Hello fellow developers,
For the past few evenings I’ve been struggling with a persistent and 100% reproducable animation glitch. I’ve been working on an app that has custom navigation transition animations that work both ways (push and pop). The transition I made is having a UIView type object moving in the transitioncontext from 1 view to the other, and so far it’s been working wonderfully using a protocol that I made for the two involved viewcontrollers, which lets them tell the animator what view they want to transition, and their respective from and to frames.
I use this on images, and on videoplayers, IE when the user clicks on an image in a collectionView the image frame animates from its origin in the original viewcontroller towards the position it should take in the detailViewController. The same happens for playing videoplayers. It works perfectly when I simply push a viewcontroller, and pop, for both videoplayers and images. However, recently I implemented a custom pop gesture (with a UIPercentDrivenInteractiveTransition subclassing class). The popgesture seemed to work wonderfully and I was looking at some beautifully lerped animation states, until I tried it with a videoplayer and the horror started.
When doing the popgesture with a videoplayer that is animated from one frame to another (as in CGRect) there is some extremely glitchy behaviour. The popgesture pretty much consistently cancels after a (very) short amount of time, generally at about 0.1 ish progress (an interesting detail: if I swipe very quick the gesture is completed and nothing bugs/glitches), but despite cancelling, the pop does (seem to) happen and I land back at the previous viewcontroller. This is where things get really funky. The visibility / frame of the viewcontroller is changed somewhat, like there is some clipping (somewhere past halfway the view cuts off), and the entire view seems to be shifted (upwards in my case), and generally repeating the popgesture worsens things. However, tapping on the view still responds as if the view is in its normal position (without the shift upwards). This leads me to believe this is some sort of a layer glitch with some of the stuff happening when animating an AVPlayerLayer with a UIPercentDrivenInteractiveTransition.
When I don't update the playerlayer containing view it’s frame while animating, the bug doesn’t occur. Similarly, when I remove the player’s layerClass override, and simply add an AVPlayerLayer as a sublayer (and update it’s frame in the layoutSubviews call), I also don’t experience the bug, but I get the side effect that the playerlayer immediately jumps to it’s final frame, despite the containing view animating properly).
I’m sincerely hoping there is someone that has a deeper knowledge in CALayers, and maybe recognizes these symptoms and could hopefully point me to what’s really causing them. Many thanks in advance.
I useful, I’m willing to upload a video of the issue.
tl;dr using a custom UIPercentDrivenInteractiveTransition subclass to lerp the frame property of a view with a layerClass of AVPlayerLayer from 1 CGRect to another causes very strange things to happen in the destination viewcontroller (its root view visually shifting / changing frame / clipping, while the touch area is as if the view isnt shifted (IE tapping a collectionViewCell highlights / selects the cell above)), despite the exact same animation logic working flawlessly when used without the UIPercentDrivenInteractiveTransition subclass popgesture handling.

How is the Instagram Stories cube transition done in iOS?

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?
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.
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.

Observe progress of UIView.animateWithDuration/CABasicAnimation?

Is there a way to observe the "time progress" of UIView.animateWithDuration...family of methods from UIView /alternatively CA animations?
I am animating a view's frame and I need to be informed how it is progressing.
My line of thinking was I can either
1) tap into CAAnimation related stuff or
2) observe the animated properties (like frame) and do my own calculations each screen frame.
Approach 1) turns out to be a dead end, inspecting the internal of how CAAnimations work told me absolutely nothing...and 2) is flawed as the "model layer tree is updated immediately and tapping into the presentation tree is difficult as the presentation layer is nil when you start.
I am pretty desperate, I was thinking that hooking into CADisplayLink will give me a tick and then I simply check something that is affected by the animation but there is nothing to tap to.
Do you think going the NSTimer way that is launched in the same scope as the animation method is ok? If I know animation duration then I can generate the progress myself.
If all you want is the time value, then you can do math on the CACurrentMediaTime() minus the animation start time. I have a sample project on Github called KeyframeViewAnimations that does exactly that.
That project supports pausing and resuming and scrubbing both UIView and CAAnimation based animations. In both cases it digs into the underlying CAAnimations.
I have another project that uses the values of the animated layer's presentationLayer in order to do hit testing so you can tap on an in-flight view and start/pause the animation. That one can be found here:
iOS-CAAnimation-group-demo
My code uses an NSTimer to update the progress of the animation. It would be better to use a CADisplayLink timer, as you mentioned.
I am also looking at the new UIViewPropertyAnimator class that was added to iOS 10. That makes pausing, reversing, and scrubbing UIView animations easy without having to dig into the underlying CAAnimations. See this thread I just posted:
Is there a way to observe changes to fractionComplete in UIViewPropertyAnimator

Swift: Change label text value as animation plays

I've followed this answer to create an animated circle, and it works just fine. In addition to the path, I draw a text in the center of the view with drawInRect. I would like that text to change during the animation, to reflect the percentage of the path that is visible at each moment. How can I achieve that?
Thanks.
The most promising post would likely be this one. It describes creating a new CALayer that keeps track of the progress, which can then fire a call back.
Otherwise you'll likely need to wangle something together by observing your view's presentationLayer.

iOS - How to make an animation track touches

What is the best way to implement a smooth reversing animation which tracks touches? I am referring to those animations in which, for example, if the user executes a swipe gesture some elements smoothly animate on screen, and others off, but if the user instead slowly drags a pan gesture back and forth the same objects will move forward/backward as a percent in accordance with the touch position. This is seen in many app intros and also in transitions. I have found
One tutorial which discusses the built-in facility for this but it is only between view controller transitions, not providing the full granular control I see in many apps (http://www.doubleencore.com/2013/09/ios-7-custom-transitions/)
Jazzhands, which is a kit by IFTTT, but this is a packaged solution that might not cover how the solution is best implemented at a lower level (https://github.com/IFTTT/JazzHands)
A question here for which one answer shows how you might execute an animation after a gesture ends (iOS Touch, Gestures, Animation)
What I don't grasp - and I'm comfortable using CAAnimations and gestures - is how something can be both animated and interactive.
Typically, when I create an animation, I commit the animation and it goes from start to finish. While I could interrupt the animation as touches continue, that seems like it would be stilted.
On the other hand, moving things in response to user input is easy, but that is not animated.
How is the effect achieved where something can change according to an animation, but also have that exact same animation occur tied to touches, and yet still also have it so that although the animation reaches completion it doesn't really "finish" (become irreversible) unless the user releases touch, while at any point during interaction if the user releases panning then the animation either reverts backwards to its starting position or animates to completion depending on the last touch location and velocity. These requirements are baffling.
The glimpses of this technique I see all involve keyframe animations, but what I don't understand is where the touch events intersect with an animation to create these smooth effects I see.
Any tips, examples, or tutorials are most welcome.
What I don't grasp - and I'm comfortable using CAAnimations and gestures - is how something can be both animated and interactive.
It is because, having set up an animation, you can set that animation to any "frame" you wish. Thus you can track the animation in correspondence to the movement of a gesture.
The way this works is that an animation is a feature of the render tree, belonging to a CALayer. CALayer implements the CAMediaTiming protocol. The timeOffset of a CALayer thus determines what "frame" of an animation that layer displays. If a complex animation involves many different layers, no problem; just set the timeOffset of their mutual superlayer, to control the frame of the entire animation.
That in fact is exactly how the new iOS 7 interactive custom transition feature works (to which you rightly refer in your question). For instance, in this example code:
https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch06p296customAnimation2/ch19p620customAnimation1/AppDelegate.m
... I keep updating the UIPercentDrivenInteractiveTransition to tell it how far through the gesture the user is, and the animation therefore tracks the gesture. Now ask yourself: how the heck is this possible???
Well, the UIPercentDrivenInteractiveTransition, in turn, behind the scenes, keeps adjusting the layer's timeOffset to portray the animation at the corresponding frame. (You can actually add logging code to my example to see that this is true.)
Moreover, when I end the gesture at an incomplete point, the animation either hurries to its end or runs backwards to its beginning - again, this is because of the CAMediaTiming protocol, which lets you change the speed of the animation, including a negative value to run it backwards.

Resources