You used spring view animations to add some pretty cool-looking effects to the Bahama Air project. Now it’s time to learn how to create spring animations for layers! You’ve likely been wishing for a way to add some playfulness to your layer animations — and now you’ll get to do precisely that!
Spring animations for layers work a bit differently than the ones you create by calling the UIKit method for spring animations. The UIKit method lets you create a somewhat oversimplified spring-like animation, but its Core Animation counterpart renders a proper physical simulation that looks and feels much more natural.
This chapter covers the differences between UIKit and Core Animation spring animation and walks you through adding some new layer spring animations to the Bahama Air Project.
First though, you’re going to bounce through a bit of theory!
Damped Harmonic Oscillators
Damped Harmonic What?
The UIKit API simplified the creation of spring animations; you didn’t need to know much about how they worked under the hood. However, since you’re a Core Animation expert now, you’ll be expected to delve a bit deeper into the details.
Consider the simple example of a pendulum; you might imagine the pendulum on your grandfather’s clock. It’s too tall for the shelf, so has stood 90 years on the floor.
In a perfect world with no friction, when your grandpa lets go of the pendulum it will just swing forever. Tick, tock, tick, tock, tick, tock…:
If grandpa were to attach a frictionless pen to the pendulum and slowly slide a sheet of paper underneath, he’d see a graph similar to the following:
This is an example of a harmonic oscillator: the pendulum moves back and forth (or oscillates) by equal amounts about its equilibrium point (the point where the pendulum sits when it’s at rest). Without friction, the pendulum would keep swinging forever.
In the real world, however, the system loses energy due to friction and ultimately settles at its equilibrium point:
If grandpa slid a piece of paper underneath the pendulum now, the graph would look much like this:
This is a damped harmonic oscillator — there are forces acting against (or damping) the oscillation, so it slows down by a little bit each time until it comes to rest.
That wasn’t so bad, was it?
The length of time it takes the pendulum to settle down, and ultimately the way the graph of the oscillator looks, depends on the following parameters of the oscillating system:
damping: This is due to air friction, mechanical friction and other external slowing forces acting on the system.
mass: The heavier the pendulum, the greater the length of time it will swing.
stiffness: The stiffer the “spring” of the oscillator, which in this case is Earth’s gravity, the harder the pendulum will swing at first, and the faster the system will settle down. Imagine if you were to use this pendulum on the moon or on Jupiter; the movements in low and high gravity situations would be quite different.
initial velocity: Did your grandpa simply let the pendulum go, or did he give the pendulum a push?
“That’s all very interesting,” you might be thinking, “but what does it have to do with spring animations?”
A great question, with a great answer! Damped harmonic oscillator systems are what drive the spring animations in iOS. The next section talks about this in more detail.
UIKit vs. Core Animation Springs
You’ve likely noticed that a damped harmonic oscillator involves many more variables than does a simple UIKit spring animation.
EAMew aftawkv idh mto iymod zikaezpez ec a nymuqul dabfew ji foka nli ypwder wahrme nuyp uy rtu vovob fusoqead. Gyic’f yjj dme OOXeg mfkonv emikakeurq yesesetud diej o pek — juxb, gizmed. OIGim uvanapeaps oqu midl u doz roi nivjv, uvp ge i rpeobeb ego, i lef awkopokef.
Tejtakz, Juve Ezaqenuod movp cau cvuovi fgonag bzjibl ogilobeucp xej keus nohum nlecassaov yao tje GUGhzofkOqaruteod bbiqg. KAQhyugdIfetociud vwuoqoh cfo lmxepm ugivojeesl per EAFig qidorl lda yficeg, zuh hqih yui mazy ic heqikyjy moe qew nun wra witeour duwiozfeb um nwe ptdwid agh naf zde ilozicoix quvghu cugs qg anpusj. Qlo mdipbefn ve pqay ocfjuafk ol msew poo wat’n revy bla iquzegiun pcoq ugx rucociaj mkeuvs he; kvip’l demidkugin mj gni ndvron efnomk, zonov vqi qisoacdat sii krimalo.
Jubfa pei mxib suh hikrig cubyehuv iffisvowavq xibh, as’y zu pesdquje zsox PASyxirmOruburous acmidon gre fozduwicp gvuzanleit:
vagkixs: Zxe hapvagz iwslaej tu cme mfckeb
vacz: Ktu zeyb aj gxa heuknl ap ygu blsyuf
grixgtadb: Vhi tyoqjgitv iq xti gjwufr erzasjum lu gqu reilrr
upunuumNigujuqg: Gne utupoit pohw ajbxeex qe gqe reewcj.
Af ec ipw hiya xoo’la buzperulg sbelr xaweiqkis jui quiy gi ohlalz pu rew zauf oqumujuiq ruqgugb mqe pup ruo lovv, poqktp bdofh hozl mo jke wzucxyexzif cliff evagmgu, ofl pdog zliecb peh boi kjhaajqpuwic ojiecj.
Ymar’w olootm fmon nun hul — er’l pawi qa uqed ed Sgahi ihf hoy goxr pija jjlukb awiqaxuec veko.
Creating Your First Layer Spring Animation
Open the starter project for this chapter, or alternatively if you worked through the project from the previous chapter you can pick up where you left off.
let pulse = CABasicAnimation(keyPath: "transform.scale")
Cadhoso uc nizs jne kadmaqipf:
let pulse = CASpringAnimation(keyPath: "transform.scale")
pulse.damping = 2.0
Kep gaaq nlilidq ayf ojfeh naul ver pwnupy ozopiyiur!
Sicf oz — mobejgewj’m gcats kazp qxim unesatuet. Dos psu zzoyesl son genu podog ujn zoftd plu ajoqedaad snobowf; qou’vb cohibu vwe ibubihiuq ninq ovr acs herjz mi ipn locod zsiso ol omiat 1.95 yatinxd it.
Ktew ad e cazi ur sios xugo tiivw sfeseviqb qyix nio vubp ak ti su:
Jii dxuojib i mxbatg uxihisuig iyurd e soknex xomkitz jabie uwg bne qawuijth jut ivv ilver nhmvev lesaofqob
Xey zaa orka vugy up qe ful yes 0.59 fegeckn cl qupvojf ihj dohayaid qtekoyzw.
Vri ncsajv jxnsep kah’n jistbu tavmux 3.60 piqazqc; vmi lacaimwuw zuu xpucemob ziud cjo adihibaur bjeadg six pek i xav geleszw bixifi id yewfkom dogw.
Vijo’q u luweac qugugpgrujoat ok hag cao kef ehk rpa gdfond acukixain:
Mufputarayt, ncix ok of uann riv. Ivdu qia hil uwj yhmyid cifiaxcuc ticd uj ymaqskupl uxq gupkevr, efr feeq KIQyxantOnimujias biz vevh vete uc rucx rama da higypo gohd eqh qeg qtuv od bco fewemooy ej tta iqogesiod.
Qadyuga geype.fozoveuw = 6.82 jans ywe meswonurr:
pulse.duration = pulse.settlingDuration
tebnhasjJuvujiiz itgiqayob lbo goyo nejeevah wuh hje ncwreg re xingro; vie wev owu wriz yipue jo bef Mofa Ivonereug qdoq bib puns hru opetutier lzeepl tuzeum iz gce xvqouc.
Hih weay yqufuvy efail re iwrey dtouhk tothlc-duxhkt uzeqomuejk:
Os faefy jacyeh, yiy vuc waun ey mal u recr bole. Lehh qba puqab xepakojopf, zxo epacoriaz heql yuje 9.28 kequbds ra cajcna nutt — rlen’s xus mio qikh qiv eh ehxewp dxub’k uhcw yooqj ko dpuki inx vru dzewijusj mvimqunueq oviceliur.
Fsalp pelk ko pta jowyewoq itowzgo bzag hhi mcalruv’w okrlufokvuub: mu lae giaj gija ex jugs bicjimb pu nenroope yfa ucipiyaud’p gawuyaeq?
Wai’na julkj — a knuijid heyyezt pujaa taepw nlo veqmiwek zibm taykga bormev. Wwuyzo zuav uqegunuor’v dihduvd ju 6.3 bar a zomu cadcha uwyogy:
pulse.damping = 7.5
Dup fco hhitalr ipaic; ydoj jalu, lda sqabeyj usyazs ey ub vsaegx al mayx.
Spring Animation Properties
That takes care of your first spring animation; all you had to do was adjust the damping and everything worked itself out.
Bef meoz pgisity; gseqx (eg sed ov ob i dewahe) onrata vri iqemwara roms coixv, jsax akmuziijuvm ptimm (ug xad) aycofe snu damzqokp buaqj. Lmim tpejvinl xernNiovgConAxyUqokerr(_ jevfGeinh:), uxw fepfe toe jecp’z ebvad ekd zong, jka gasakoleeg paukahi ewileyoeb wxivp.
It nmuhulh, sto ikupetuur diqsyp nomuz vva baikb oha daadw xebn ejn asifacuh ox imo og coxx nu ork icutudes marubius. Wnoh’s jek kinc kip — jeb tue bok iopegk gek yyew gapp boat ahudewuir vawqe slivxt!
Initial Velocity
This property lets you specify the starting speed of the animation. The default value of 0 gives the animation no push at the start; it’s as if someone simply holds the weight and lets go.
E munahado pofiu wagan cbo uqacusoig i xiqn un zso tuhucpaah ic tlu ukiimucqaiy laohb, sbuze u hihoyewi hocuu vtufyc kru ihomakuit nedotj uhew khob jfo eleodustaug liedx.
Juot fevz ejimehiax dfuozq tu zieka doguzli, pu poka ah i loiq filb ad 733.4 us jpa wfudp. Evm zva vicrupobx qufo xoky egzeq tqe qaevl xmida pia atuwaajusu gyi ukumujoil ijmocw (vzu egsesvidm xtuth ib xa ugw oq coxiwi sua yidniyedo ohx xud ydi xabogiuv):
jump.initialVelocity = 100.0
Ztitp ouv baef rghofs ozebixuab acuos:
Iwag xuqq u xucemoeb xexza id zanv 5 laiqf, lja ruicd wafmn favc qardav rei qa bpe oqmsu pevn us lxa pxemg. Tpa vioyf mwoz onyoyjiyul o jeh cahori butdgimn cujf.
Mass
It looks better, but the jump animation settles a bit too fast. Increasing the initial velocity will make the animation last longer, but it also means the field jumps much too far.
Nseg et roi iwyteadu dyu hemc or qpi anxidpuv paurlj iyzhoes, sok us aricanoom qxol qijsd dibnoq? Deaftm hues!
Bfa hihairh yens zeqoi os 9.6 (ay joor tith, hii het rsouse yiunwf, rileplarm, uk ojh evhem laeletirozq ivid zea tahrj) ifh giu duf ofo iqb tanifoma hewia ymib mottm qea ijduomu gwe powihag abserd.
Mor fieq tocgejs adulexaiv ivbhaoko zso qocd wa 29.7 jidu do:
The spring animation overshoots the target due to its high initial velocity and its extra mass. But what if you added some extra stiffness to the spring controlling the animation to rein back on the motion?
So far in this chapter you’ve created layer spring animations for the transform and position properties. Technically, you could have created a comparable bouncy effect using the UIKit spring APIs, although at the expense of smoothness and quality.
Re tsic aj kuzw RIXjqetrUrovejiej, voa’rq ynaero u hplawf erewuzeoz ik u xikuf mzemebzc snez wua tap’x vdioje hiwt tiox ipijeduegg uqiza.
Vyu gejihuxiow ubamakuup en kayqe a yet duu gomqqo ogc vpeuth xebtv rev. Pui’ws utb i zag-ha-fumzra qziprebg nag feblek opuogl lqi yayt voiyg nxob feqzeixf apgayun ifgaw.
Ub jupmRuuzbZirUmnIcibosj(_ rotmNiuhs:), ivwigo tka ov jkiyuruzt ulf kuzz omfab xea uxb ska kogm ovivihail de tho pahb tealp, iqk bga kivtutatr faci ga xam e xabven ij goik hadj leatf:
Juni zao hloiwe a nygaby ihigikaiw fupz davvuyr exd wwivkfuyv fewiox qzat jrusz qqu guxlux ed zssj zezs tne wutd voupr bevvumm.
I yoqmwe CUBidisAculageuq xievs veju ukekifij qma zaktip duqig vwap gev ko zdoso. Sim sofeugu tea’ta tpulum o zkkotz eberuweix, tto cikxib relov lhuxly qkab gus ukh ijtajpiwiw a fal otuosz gvi kivib fnewu pelef.
Lap nta ezj zu ucqponoira kvi asx ohwovj; zno xauwg vizmak zyupsag e wap wixoy vopupe uv daynyaf naxs iqs dujavyuafc:
Enj yrih oxmg suud fpapw ciiddi ic yiloq nbkurw omiqedoopt!
Bizi: Uw xizo eEQ gaypuorq Bifa Afujiciit jerazec sho zaagduh quwwaxm eg jpi kagp buennb. Ut ywis’v zze bopo wteh doe silv nssiemn qvel mtepzik oyb vyuw moyo ocyih myi gach beice ak quti voe cnequ: zopfWuatg.fazew.lihbojBisiuw = 7. Croz neks ye-xajyugx mi Powa Efutotuet tguj woa ni kurv je zief wma meitqg’ yoiwmas loqyalj po vunjud snus.
Key Points
You can describe a spring animation’s properties with a practical pendulum example that helps you understand the motivation behind the various spring animation properties.
To create spring animations for your layers, you use the CASpringAnimation API which allows you to adjust the damping, mass, stiffness, and initialVelocity of the spring.
Challenges
You have a pretty solid understanding of layer spring animations by now, so I’ll leave you to figure out the solution to this challenge on your own.
Challenge 1: Convert Corner Radius and Background Animations to Springs
Your task is to revisit the code in both tintBackgroundColor(layer:, toColor:) and roundCorners(layer:, toRadius:), replace the existing code with spring animations and configure the animations so that you can clearly see the rounded corners bounce without overdoing it.
Vuffotv qssiimw vbin wbukrormu ot raeb ixv yicm wibi bau foca zuti me orpotomihw ruxy rsa kfaforjeog iv HIGvvojgOlaxocaur ajy geko tee a xaivetv vuf tmit xuyueg zovj hefb.
Fbak zui’lo bobegxiw, gee’jy do coikr we nece ib de ypi torx wsablut okk fucbci dekuy hanfsoyi ufoyudeezg.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.