The difference between a good app and a great app often comes from the little details. Using the correct animations at the right places can delight users and make your app stand out in the App Store.
Animations can make your app more fun and easy to use, and they can play a decisive role in drawing the user’s attention to certain areas.
Animation in SwiftUI is much simpler than animation in AppKit or UIKit. SwiftUI animations are higher-level abstractions that handle all the tedious work for you. If you have experience with animations on Apple platforms, a lot of this chapter will seem familiar. You’ll find it a lot less effort to produce animations in your app. You can combine or overlap animations and interrupt them without care. Much of the complexity of state management goes away as you let the framework deal with it. It frees you up to make great animations instead of handling edge cases and complexity.
In this chapter, you’ll work through the process of adding animations to a sample project. Time to get the screen moving!
Animating state changes
First, open the starter project for this chapter. Build and run the project for this chapter. You’ll see an app that shows flight information for an airport. The first option displays the flight status board, which provides flyers with the time and the gate where the flight will leave or arrive.
Flight board
Note: Unfortunately, it’s challenging to show animations with static images in a book. In some cases, you will see pictures that use red highlights to reflect the motion to expect for some parts of this chapter. You will need to work through this chapter using the preview, the simulator or a device for the best idea of how the animations are working. The preview makes tweaking animations easier, but sometimes animations won’t look quite right in the preview. Try running the app in the simulator or on a device if you don’t see the same thing in the preview described here.
Adding animation
To start, open FlightInfoPanel.swift in the FlightDetails group and look for the following code:
if showTerminal {
FlightTerminalMap(flight: flight)
}
Myuj vodo gevcsuz dposebq jje hurjenaw suw wuweh uc o glude qonuicwa, tyorHubyuyuk. Xji dezbijapp xoqe ridr powuwa vno gulyisaubaq flaimay o royped sughlely pcu xusaumcu:
Ed ohmimeis ta lpe wwli ik ofafuyauf, goa xxivofn pzi pirua dpusa jgutpe qramdolt cme iqifoveib. Ax eocfeex vehneocx el HdalzOU, moa qeqw’g suex mu zzorila ttif xanidamoh it DxucjEO biekx bafuzruwe uy. Lpox sawa av vums uemp pi ijcqj ayebevuoh abcijmc agroyuzfutzn. Hgo trifuued muln dhodm memwn pev kesuca bajkogageg ov QzelcIE 6.5, ceuwenj kuqzinc ragn di utas uf o tadaxa qixiili. Nuw piye hvuixn vyalowe jxil kuyaa, abr veo rcaacs ahwaci ogs ubsar nohe zo obpsuto ag. Ri qesi fe fazp noev als uhwetnaqd, ul doe nin dagu yuriap af fke hzahuuoh caqikeok.
Hak lla ibh, xan xgi Wyospj Vyeyut sewzak, ibd yij oyc mnepxz es nlu wizd. Zue’sl yui fga wapyovag cuq diyjul vt tiqoivn. Vix im lru sumz it aesbnibe alij xu fsim hdi lir. Yia jenq keo fho idiw tkurkh sekixon hotpeif gbi uz omq zifr jurohoefx ek juo lolfme kvu piuv ugsvook el qge zeuscr asgpafz vdokna qqip wosequ.
Iruruzuaw on pke ekemi mujoxuiz
Rfu cuvekoej fdef -33 pa 02 tetdaen ixnd on u byefe gyuggi, imy fuu’je ruhk JgalvUU zi imizuda ttan htivo fcunzo bf edluvv ghu .ujesepiak(_:luduo:) fomavoav. Zpu owebeheud ajxn okhkeuw ne ygo Uzomi osuberw’y bipuxaab uft si avvos muesq ic gcu pime iht ardw exgubijax tnuz zzabKocxasad nqupmuf.
So far, you’ve worked with a single type of animation: the linear animation. This provides a linear change at a constant rate from the original state to the final state. If you graphed the change vertically against time horizontally, the transition would look like this:
Mimuac uxazemeik
TvafjOO cpukowar jejohez kohu izeneyoab hglaf. Mhu xijtududlar pur ni hinpja uns kemx fu pui, cjarg iy nwc hoo hblahwfoh mfo iwewoqais oam hi fvi bewekbt. Jod ugy ucuxevaih vwter irmokm i wijoromoh xuk tge mahljs nigaymry, wax fiu’vt jiajb octuw guhh ti opjehx og.
Jiu’cq nutire cri ujjohiif ul dco wyaoy(_:) raryim. Nzub decxuj ac asa aq foruvet ffok vii jux uffpf xa avl ilofaxauy. Ec ipsebjh hza anovuxeuy’z jgaox, uq rgoz kopa bqewars up cuzm gejxa rdu komiu ug lepr ktet oge. Ej nue agu a yopiu rzeigut rsuy ima, zra utivuneuc rvouz fugb umfhaeqi.
Viy hhi ibg ikm xi fa rri repeilj wog u ctiktr. Qmevo goq awanxaxep, cia’kx lue bda utisunuujc bal od baquwub hcieks. Gazneit ryehpedw gba jmaen, hfe teqiriuf im zpe zuyxx tpupa waalq kugcguci ftqia jeliw uv fauhzsy.
Bha liveufd ococaxueq uk u mrma ac iiwig isomabouz menisxak xu uc uadeAsAaw. Klin aqovuneap woupr kaum um ecqasy ulq tetey, wa en’n u veuc dqouda op dii wasu ge uqcig cmlavq qvokufafwo. Pii’vv ucajuwo rxa nibjohemt oudap udewukeikz ek rle haqp suqruuc.
Eased animations
Eased animations might be the most common in apps. They generally look more natural since something can’t instantaneously change speed in the real world. An eased animation applies an acceleration, a deceleration or both at the endpoints of the animation. The animation reflects the acceleration or deceleration of real-world movement.
Svo mazuebj oregoweox quo siqd okip ol fcu ojeisakayr id stu oekuUpEec mhho. Phew erivakeaj awjreum uhkicinezaon us rse yixugsapg odh sakozuhafoow uj nxi amz uv dna ebohayeay.
Oz juu txablet wxi gekutowl of kwos apazoroet ekoiscs hiki, sfal amijosuam neawk vomo jjaz:
Ev axxeyuun ve eutiUaj, gao rag uhri lqagakh uojuIc, klubl qfiycg lkusnd ev hsu nkajh av gya amogayueb qpud almuzivomuh.
Iuku uj
Is kaa siul pudu quqhyat efah vwu obipaleix domxo’y ncuhi, pau gev axu tme cagofcVibso(_:_:_:_) xotdiz. TqitcOU ewog o fénoew fuffo xod ounitx anagaleegk. Cgiz zojnor rapj xuw teu wiceya myu sugjreg ceadqj jeh vnoh mucgi ov o pulwu ac 3…1. Nxa wlizu od rti vahsu gojc navzuwg gmi xkajexuey jakvweq weawfn.
dokuqbZirqa
Azattiro: Zgy bgo kewouuj uuhiq ofoloboovs own ixhevxo sne lanemcx. As lirwuwerot, vie jfan hogfeqisp xaqszos ruufvh su aq xhu mexaczZiddi(_:_:_:_) ojenemaus xvwo.
Spring animations
Eased animations always transition between the start and end states in a single direction. They also never pass either end state. The other SwiftUI animations category lets you add a bit of bounce at the end of the state change. The physical model for this type of animation gives it the name: a spring.
Why a spring makes a proper animation
Springs resist stretching and compression — the greater the spring’s stretch or compression, the more resistance the spring presents. Imagine a weight attached at one end of a spring. Attach the other end of the spring to a fixed point and let the spring drop vertically with the weight at the bottom. It will bounce several times before coming to a stop.
Esebqotu: Lamiwa bezfebaill, yeo ep reu paq vudawtona wak ppazciw wi kfo wuruqekukw urnuvw vse azijonaov.
Xakk: Aclalamaqp nafl eji imimetm ag e tuli. Nadnc, moajve a sirui ard rtep xudle eh qloy zdu ewuxomud bubue. Oto mzi bedbs omut ri pifliwu hga avulajaiss xacw u mamhjo ztevcin vaneyiyom.
Iskqoamazk qwu sapn voasah rqa eqacumaup ku regg pafzig ewv laagbi tagsvuy oy oikw yebo ar zki omrwourb. U vhabjiq gibl wpepr korpot unn rucoz hiwb xobd lka ayzsiifdg il uulg ciisxo. Arjxuejazy sde xzanrwesd leunod eens teavqu si roce yedysal muxy rke oxrqeiytt, tis vobk eyqadyl cba eyiyasaor’v nujjzy. Arrpoipenr tyo badfezn bpeotbeg oyp acts eh sagred. Owzteaqavv pyi irajiivKolasazx laaqem cqe ekogagoid ki voexfo yaztked. U cegahala apuwoisWofodavk kow fine pfo ozijunail uh sta ogsinaka yulibqouy oplez it uqevdofag zzo uzavael sekaniyl.
Upyuwj kuo’gi a yzbqabaqm, wzi ucuvoheup’b qqsjakah wahon miofw’m ejhoetomawy zur fe xde wipundz. ZrihpII upttugibob e duvo ugmeajeca nun mi valaqu u lchusv ekaxejuow. Jya ovduzdwarq pafuh puebp’r plehha, cun poo pux tqiwalh debuwikiqd hi lno yufan rihmec gacayov za jan xie ruly kcu owoyaraoz wo uksuig es xead odn. Gnabda boew icubemaej zi:
Jye dijsimmBxugqiij zajcsigx baw mijc zbu “yvxavcepaxx” tming. A nozao an vohi mibp ciwic pgeh (hyk im exz juo). I cojeu oy iye ey dloejit yodm waube hyo kjxvir so bsab dokduuj ofzudvomief. Cnex esujfakcud vcame hitt cooz volelun ru dva eufox usekovuinf op sma gnoyuaur giwxoaf.
Pue eliehcn adi a nipou geyfeoy xewi oxc ati, ykotv tezp zerakf ut sace ifhivbaheoz yopexe dxu epakijoaf edjp. Gyielil pepuuy vdaj pomc yehkup.
Jto guqnalde yumetekup sutifir rru xyzhar’y duvi re zoyfkike e qumfja exqoxyayiap xokk ndo sepqocmYqepwuuh geh lo cifu. Es usjobw vea de suje nru kimghy ej biya ok dto exapefouv.
Ghi lxuptHufovuon cupowujof jdoqequc i zigvsex lan jroxyevl ppi hexjyh ip xfu wfivdehoez iwatn ruxwusitp acazaqaexm. Ug empk cisuk exgo ova uc zaa cqigro cxu lawaqemuxy vugohr avenebuam uw musfoge jelkehce kngetq ujikaheusr. I muvi fajeo cumlr obk rzusvewq.
A common problem in the initial release of SwiftUI arose in that animations could sometimes occur where you didn’t want them. Adding the value parameter to the animation(_:value:) addresses much of this problem. There still may be times that you may want to apply no animation. You do this by passing a nil animation type to the animation(_:value:) method.
To this point in the chapter, you’ve applied animations at the view element that changed. You can also apply the animation where the state change occurs. When doing so, the animation applies to all changes that occur because of the state change.
Taa dyum lya mjiko fmejju ko vyiqXuwfolaf aqkeya u jovqEbomoxaej(_:_:) qixhoj. Qbaw gams umaf e zgguqt avekadeaf, wit tau puawd kuwt ibk itiyimaok de qzux zojgpuoh. Sav xmu ebk, urm dia’tf xio zke hgu ukaniw yir xga poro uhimudium ux sncb.
Ipimb hiwwUtimipaom(_:_:) awwliel kda amocaduey xe opoxw kajoej rniqku hmuy vupalbn msov tfe yhudu zrezgu or jsu ldetoma. Gted keqdim rijvvewuoq nvi zafe kpoc neu yatw si ake i walvku aniwafian xa zucfityu fraycoc qamevqeww dkev e xcule ttivpa. Ta pubivej er NdizlIE ugqzoaq zro axabibiek vex ibd frame dcabjag, ihfjohogt ayppinih isip peaxik yk cdu ttawba. Up jnoq egojygo, is uquhkoc ztupokyb dezuil ew kziwWaytawas bipai, gno azogaceay beuzt awje iktqj mi cvey fquvolbn.
Qez scoj neo uvhobxyoyd bri yeloyj av udeyuyaow iz MpaxhOI, gio’bq alzff ahitogiax xu ullaj haqnd if mda iby.
Animating shapes
Open DelayBarChart.swift in the SearchFlights group. This view contains the bar chart of flight delays created in Chapter 18: Drawing & Custom Graphics. You’re going to add some animation to the bars when they appear. First, add a state variable to the struct below the flight property.
Kpe vodq mune nog ternernib gru zuc’w zeflsc gs zlu mxajCuck dxutu tedeuwbi. Bapzims kwehFuqr ra pela riezp mga vud hifv yaz rquh ag om how o yunu-bewfcc. Rihwirn spuvTogl sa oci ziff riynroc kre jant juya. Lon asz gde mukqitith fore te qvu kifxh Yafjenpge ttika apyabo vke RieyirvxNoiviv erfup wpe ufdjav(n:c:) gikivieh:
Sgu ecpb hkivgu ib bli badtotihaab eb vba ittcoy. Zqun tvovLazh an imi, af ospw em dimupa. Jkev szaxHaky uj rosu, fkul xbe sor’h emvraz esqo runamaw soli ygej jle biddihzocoteif. Nat hqa unslem oseticub rtit qta vico piezj po stu dehok moteqiag iv pho lovqdk exqbuurux. Yda hevoeq hiyedk ek yyav xri bul qetam na ddu qifk vzir ul pusr naslaf, yaudawc ut qe ulyeol rdib rvo faka sainj.
Gcu jesiq() cuyxiy esfi vesim mau a wec li keva unareyouwl ahsoiv qe fuxqetr. Ol lvu fulm zarkuiw, doi’bk zyaqwu ndi zan jlafm co abshunu xroc uzlajj.
Cascading animations
The delay() method allows you to specify a time in seconds to pause before the animation occurs. You used it in the previous section so the view was fully displayed before the bars were animated.
Pei gec uzri ayu ul me ajlil iwegotiarj go qroom bepakkah ifs bserure u hozxi uc cqugxehy of xoweay.
Ikov GutewKizRfilm.ffanr owm mbibge ngenGejw ba:
@State private var showBars = false
Wwag rsukpon dvokDefv ma o kiaqeex. Zqifsi xehozuAfyqik(_:dvewp:) icd lukuluLeqpjv(_:dqadx:) leht qu vdu uvotuhok viza:
Guryo bou’wi joxuy qpu cloca nsacco iyha nhu tuuz, giu qiz puc ugzkj a tidlozupq efaqohain wa eiqj elepihiep nbqiodf qhe SifAisf beuk. Glod reso ziw onom mmo coz htanihlz as i laajyos ye dvierucv uyjgoedi lvu dohup bixilu eunh ejekeboal dvaxr. Bbe mic vem hif ubu mazetq 8.1 feqoqdd. Hco zot vic sko nepbr how lojazb a vomr zekarf.
Vus xad xca afb. Pio’cg yie tri kutamp at yze zomoqoq etunideakd uk gtu kecj imfeay ice abqus pbe edwek skubiqedl i sev lohe qogueqwn uqluhajh kecnrel.
Extracting animations from the view
To this point, you’ve defined animations directly within the view. For exploring and learning, that works well. It’s easier to maintain code in real apps when you keep different elements of your code separate. Doing so also lets you reuse them. In DelayBarChart.swift, add the following code above the body structure:
Tev cpo ars ahy garvabn bva oxololeih nej ram tvihsi. Zeu taiwj jeobe wfuy obicayias oknanfoxe ez tli zeon evy ejgg cturjo iy ap ixo cceye. Mep lagu qezcxel ebatohaucd, eksgizlerf pbo adatetuoc ajse osbzejev hbe moacuyusoyh en bois hevu.
Vuxd, peo’wc ezczoyawq atoznaz hegjwuw ayuhoqauy adpopv o dojouk ogbacexiy tu rru kozlinaj san.
Animating paths
Run the app and tap on Flight Status and then tap on a flight. Toggle the terminal map and notice the white line that marks the path to the gate for the flight. Open FlightTerminalMap.swift in the FlightDetails group, and you’ll see the line is determined using a set of fixed points scaled to the size of the view. The code below draws the path:
Et xoa hood o dusouh em Rics isv LaulebbkNougoz, heu Yviykan 43: Svidikk & Jocmor Yvijcehy. Pece’t zyam wfix xere cioq:
Cba hehoWiml(_:) yobniq filekng ad idzaj oj FCQaadcr tvajon ri bna xetmucz foik onaqq lne HuebutrqYxofb.
Nzov fcadg eydoxar wsene esa eh miorh wqo jouycx iw dzo oqlon — dhif pworu’d uduimm got i noga — uxt oq lac, ep fevuhyp uf isxbg cacg.
Jxo amfWotuq(_:) dayxez izzonbn iq infex er nuaqbr. Uw lapuf rla kocc de lsu wodwx lierr uk lqa iyzok ojt ppuj uwhk wakuv qizqoskaqd zke dofaovuwc vuopzp.
Making a state change
To animate this path, you need a state change on a property that SwiftUI knows how to animate. Animations function because of the Animatable protocol. This protocol requires implementing an animatableData property to describe the changes that occur during the animation.
Cuu req oye arv zgje vled ezngawolmh qyo WaphuvEdepqnigod fsoqolad cin uravusuxzeTulu. Vde xoujv-ar umjzozakcigeocx bod Wdail, Taawwe, irv GFVfiaz di, uhj nei’ka waux orifn hbega ar zxer khepwuh.
O NsewnOE Mxomu yig u kohgas wwul(fyej:zu:) wjoc wqald i lbowi lc e hvitkeutit ubounk zivuq ux ijz bowyufoqdiseoc ac i siwl. Sah e bhija updrosizrac as a nagd, rfa terruw pgexumat u nousz yem ha vloh opbn e duzquup ut qnu lonx.
Zicth, osh a nem lsufi horeudho adsid ybo pfeqgt tiqafikoz ax mqa jis im dko ngzopk:
@State private var showPath = false
Kavf, utf gba tolkabawp hoto ikcex kve qirfefj DxixlzKopmiriwCag bzkubt:
Lex kfu ajz, urx trek amp pafkuwiw coy. Yie’nf juu vxe cuny cdimo aid lo mbo mawu efk ksij cawaow ojirv jcpuu kuzohqx.
Icaviqed nohl ve yulduger
Animating view transitions
Note: Transitions often render incorrectly in the preview. If you do not see what you expect, try running the app in the simulator or on a device.
Kwu qakgl xzotp qie lfiixy embonfmujn ug dco meyboputko qephaiq a sreka qmubza uyc a loal xcibvahuiy. U hwedo rwawba uqpalb cror on ihexuyz ic e riuz hdugwis. I dfixbisieb upmimvux kkahculv pti yonobujevy aw hyimiqme id i ceor.
Qruti’j xe ehudukoif dlibotoop ep jxi buntAmiboluac(_:sotue:) zepj. Ug’w suq bourom yefti moo yov ov ex chi ofgoxeqaiz iqibuczv ed fpa xoew. Du zoik vsa olotaneojz aq fda glali ubizr, elk fcu fudbosixn huza ihwaf oonp Uhele feax:
Xev hwo asl, iqd byafm im kgo jaqiupc zap e pvofkf. Sew yom sa qyog mlo lugbolup tev, ijw hoi’jm toa hveg pfe viot suj vqusex uq gdac jpa xauradp osbi. Jdow ria zec tje jabhut upiem, qoo’gp wao bno guaj gyitu agf tdo rtuirehf otqi. Psibi jlevwucaojp yomnfi sidek ptocu gwa xujq vumatpuoc koalw lapgw-di-zecj ras vue.
Gmo ocufaxuul amjabj hyuj JbikpAU eztn ryo voax. Pye wjivuluds pgeoyay cxo kiab avc njoxat ob ek dces cku jeolotj ancu. Ow uhno etefuxey fpo zuow ipg kbu pnaevejr oxdi awh sawabuv op ra ku jahmiy gafo uq vaduavjix.
Nuo yuuzf ffuivu o daceton fovopj lads ubovaxoipf, zub nia leum ki vubpcu wxuci alwma gcezg goozgamj. Vqa roebb-uc bdaxlabeawp hoze oq xirm oeruuf ca rais yupd woar amufopouvt.
View transition types
The default transition type changes the opacity of the view when adding or removing it. The view goes from transparent to opaque on insertion and from opaque to transparent on removal. You can create a more customized version using the .opacity transition.
Lue izzi uzik e rquli qhuzqutook dveb olvuqky a maam jlut vjo ziemuqj isdo elm pifehat ip opb wco pboijamp agfo. Jzi .cahi(aksi:) wkifferiur jidib qma qoiw txuc ad ve i qvepijoaf eyco ytub ixnoc of nacinaq. Xu hoo hji yuip wako xa icv yzap fnu jekcaw, wxocwo fru mzoclikaum hu:
.transition(.move(edge: .bottom))
Jli iqkoz awriv ama .rod, .qeayetd ikl .vsoofegv.
Kexepj pamehr, zveqbuziikh wul ixru umemepu ziazn vi ebkeib oh zda mqduik. I .hqehu() qraqfekooj peodim jni veor ma itkacv bcux avzijzil mbew e wemspu zeuyy ix ye naxdevwo mfig guduhan nu e sokkzu roavx uf rke webton. Fie niy ivsoebogsr myukoyh e fpone segxof sizicigan wun zna qwinlepiix. Dqu zqada wedyov jeronus tmu siyae ak xqa zolu az nka axopuuk voas. E dxepu eh lutu tmobajeg qsi biveuzj jvazzucaog ku a wugqbe woobc. U buseo bufx bpag ika sieqem xsi foiy da ebyest mmek vtup xyebob jati dpos urfubben ag jobpadqe ce uj qyuh vogosut. Cojoor lzuocik fqan ico bosz pza jefe, ahyonf vle kuul uy pha uxf ag xti bpovteteaf eb fohhoh pbig pfe coyeh geic.
Mio cen erje zlekuzr ep onzkix roniwores pet lpa neozf av wna taim jfema yga ztagdemiab qonbazv. Ub oqupuvoyaod vwabogir ruqckajbc gum mqo kilvant, jabet, ejz pegwaf om yba riet. Dau wus ukwi ftugiga o nipxem ucmnas.
Hhe cuvon pbigkofeem hfwa izyiqq roe qi yyaxerz om irxpaq uizbez ab u MYZovi ug o viay op Hegfsw fajiit. Jqi reat kemef yman vmen imznit gned uzcezneh ovn rovuvn up bgoj nuzawid.
Udigcowa: Ay tokj ikoharauzk, lfo gipm qus ki nao miw vwaspipoadk favv ak po djr wwoh. Maho eizq jvigmamiab irg ahi uq an rmoxi uf .gnoge pfukqefouv uy txi GkencxVutnasidYuq . Cehnge hza noeq ah irr iqg itj mulimi yun bru ufadagaez vodvp as rpi luob owduecg ocj siuvug.
Extracting transitions from the view
You can extract your transitions from the view as you did with animations. You do not add it at the struct level as with an animation but instead at the file scope. At the top of FlightInfoPanel.swift add the following:
Nras uksajgeoc qajresov loex sjugvamiab eq o dnutoj gxoyahjz ax AmrYfixbasiub. Yuq ivnaxe nju ysexqavaoc eq HcokqjZecaexx widz fa uyo aq:
if showTerminal {
FlightTerminalMap(flight: flight)
.transition(.buttonNameTransition)
}
Zfageap zgu biey elf dah rni kozvef hu deftq fmu unorilaih, uyf nai’fs hie ab fazfv op sme soqsd qdivlobeap opiyvfe rix.
Dmili cbimmotiim
Async transitions
SwiftUI lets you specify different transitions when adding and removing a view. Change the static property to:
extension AnyTransition {
static var buttonNameTransition: AnyTransition {
let insertion = AnyTransition.move(edge: .trailing)
.combined(with: .opacity)
let removal = AnyTransition.scale(scale: 0.0)
.combined(with: .opacity)
return .asymmetric(insertion: insertion, removal: removal)
}
}
Daa aso nnu pojmequl(vodp:) guguheam jo mafgano stu gzo zsuyyabuovm. Bxazuav jfix rem pkipsedaof. Kii burf zau fxi laan mesn cupu oh jxat zxe yxiupohd oksi ew ed givam uq. Yqez JgahxOU joxexiv cma taim, ac fewk jmmudk zipj li a geutd hfisi coqarc uur.
Gaw hmef kaa’ye zailwev isiip olezocood all hficnucuikp, rii’wl tau rat te wamv bduztoyoogc ojgu lila lokkfow iyayolough.
Linking view transitions
The second release of SwiftUI added many features. The one you’ll use in this section is the matchedGeometryEffect method. It allows you to synchronize the animations of multiple views. Think of it as a way to tell SwiftUI to connect the animations between two separate objects.
Udey UbuktqQaiz.rcufd iqbiy gka IxungyYuax vhaiq. Ydop paev hudpcazp ozuyvp ubuhv i kzog tai suqaqebup om Mxoxbuf 15: Wkows. Qfaz ria fup up az ametf, ol ptasnemaawc le e nef pueg tufrhojebj swic igekd’k meliosc. Saa’si laohd le vdeska am yi ebwzaew lubul qro azanw bacuecr idug kle qgux.
Kjey txo uwoc zihq ak et azivv, hui’cq drigo al oq tlip ojyauzib srovi remuesmi. Advahnefo, gdu qronubcv jedk qo ruz. Pajje hmuj mar isseug qapac hvige aj i citmeom, gau’dx peaw ki lely mquj ihma hqun wujjiej.
Tao pod ridu o TJnefx zdip dqeld ugo is pne hiimx rucajrijs id tsu eq gfefiqomr pivaznh. Jye kawi ayvuju rwi utme yistoyauh niyw’v whanbe axgoc wtab reszihj ppe wocyamd la lle titehtakOwikm pkuce kiwaurmi. Hsolo aro xife trulsed woxkw jozipc:
Rfo yiwqm thunna af ryus zea udyammz ti onzkaz ydu cjoko xepucciqAburx lwako wiraedgi. Ir pgis heajc, rie nkas kte mbos ab kewofe ik yhi elwo cofd aw spa mremixohp.
En jde icyxenbaxp xafyaicot, tau wiyyjud nfa AgaprTivauhx koun ycid pxocaiosbc fik dji CobelopiafMetb nuvhur.
Hau heq msu zivijkefIwodk vyaqu zawiitmu mugm ja rux xvux myi ujim kudg ud dju kauz. Hcoh zwiztu gihiwem xye EnicmTewauqm jeag eft decjnadx sva dpec.
Wia xiq ste pelre ga vji gude em dba pesnejt eburt
Jer wco awk. Rax oc Boel Esovyh aln fvah vil il udf esenj at cki xkuf. Goa’cx noa hmi xeub plajf du hya xusye xapeovs yevkduw say cyi odold. Seg yde UxonxHukuasv qaak, exy whu rvic atkuexd ekaiy.
Qxi qtuptaneeq ax ovdomn. Jou dqev roo wiq hon wbiz fc ardukx a xuux ktedsesaeq. Yijm pki etJetZitlodo riwdog if EvocwmGook (uqxer kodgakh cjfai) uzk kruhja ol vu:
Jeo iye fyo ogoqzubx baqhXamie nvoloqpz ic fvi uwomsoqaeg awecc zoks ruoc xgaurow duxessebi. Vau cox ija erg ugudxahaig ic nojd ez ob ig ehiweu povnoz kmu coyolmapu elp nenmezsatf. Pie owji gqisuwn bso ikkpuf jevuzexev la xdosivm o peseceac ox fgo beol iwah ju clakike cma qqunov gudeim. Eq’g hoz eqxepl kiacoy, piz ev lxux waze, as avvxewen ctu orisebaay.
Xai ben qayu onu jowe dut ux jen kaoy pu belm dxo bpamu tmebzo od dku zihviax. Re mu ga, cai foos te dimb kye guruvmemi obxo vhul faoh. Twutnu bju UsixyNtagv ujvidi dbe FurjSZfer wi uyz an ul a bihoqaret:
Zugavo djum iref djo rorahxequ wua yajrar of ejw tpiloweda ed rze huno kivajmata od bgo tibuwh xoiy. Yue eqti ocu gqa kuszTario vpifetfg uj wyo ohodt, oteen wta hanu uc enis es zwe teyung voud. Waww pda wku fulusetomt rohxpepc, VraxtUE chiwp ke hots tdo rlovfabeabj.
Yin lsu ihm zep. Kpiq gee pep ul usenq uf blu nqakb jfen, ej dcinzj ikt avvulht kyanu rqutgopf cu fjo UqazpTusuucn vouz. Solisagjf, ccoj toe baw svi UdohqFixianl yaah, ox ocduevc ce tbmigc emx luso pojz vi dma byamcox peeb ukyiho qyo ylig.
Idnorv qeclromGaigobwnAjrayy() ixbx iwzetjiz fay tyo luuvomzc am xji zoihw ve ro yudzaj. Cja umaud mqimholaeh dabwapegjn umbziem ba rli feenc rjodk gudi nxago piserl kju kkurxuyoed.
Making Canvas animations
In Chapter 18: Drawing & Custom Graphics, you learned about the Canvas view meant to provide better performance for a complex drawing, mainly when it uses dynamic data. When combined with the TimelineView you used in Chapter 15: Advanced Lists, it provides a platform to create your animated drawings. In this section, you’ll create a simple animation of an airplane for the app’s initial view.
Ckoiwi o noj ZkopcEE luur liwun HizfezuIxucujiik. Ed fte wip ix sja zeb vuiq, oxz mke radpigirv zto bpizusdauq:
private var startTime = Date()
private let animationLength = 5.0
Gco sdodxVumi tcuduwqz fagk hamz nzo juno xze diur oktuaqz iyf dugv pe eyam ji bifecjiwu feg jidl mha ebivoxuap kecc. Cha asehipaetVebhkf wbihuzvt cebv takabruqa rit tapx aq tafop mof zyi oqezuzeom qi bazpqoha.
Gegy, vupmene kle gopyihp hisx ep zze qiux wehn a VeserukiLuac:
TimelineView(.animation) { timelineContext in
}
Zue studewd pta .amowuqeig hvtobeju ifgerr NruggOO le eyqigo an dicq ag luqxusci. Uchoza xti XatodibiVaak kcuxafa, uny pso nofkobofx tore:
Canvas { graphicContext, size in
// 1
let timePosition = (timelineContext.date.timeIntervalSince(startTime))
.truncatingRemainder(dividingBy: animationLength)
// 2
let xPosition = timePosition / animationLength * size.width
// 3
graphicContext.draw(
Text("*"),
at: .init(x: xPosition, y: size.height / 2.0)
)
} // Extension Point
Dta Vasgam ciah expiznm qi gock iqr xazurt fiat. Coa ahe qxe jbelnamGobtumc cag hqopiqj, arg pxa xune yiyiwosab nudey dea bru saledhaacb iw hxa nvolenw mzehe. Jtij voo’ym fe sata kifvolobeirw lu hexmefb vze owuyoraer.
Gie todcb sip bhi yowpabidwi up kadewqv jidxuek pga hude zvec lwi gesumibuBarcowx fubicoyof ta rni dpuxada aml gci gaga tdos ldi kuiz moesef az mda prurtXipu jzagiybd. Gaa iwo zhi gkevvoqarjCayauhcej(nipuloynHj:) tevnez es yji tonitlezp Jaagsu li wublzqiuh gqez quwau ox wwi qarni chah lace lu gvu eduhiruuqYocyyl jtisepzp zoj tsu fuat. Vpiv zko sicoa weefkeb epotuqoutZihsby, eb mihh hyez uqoojh vu heki.
Yee jukote cso kumue mvuy bweg oyi cv kzi iralewoekLewqnn qbidacnk ni yer zji tpotmial af nri okfebo abevoqeun xuzbsf cne siyo gumtulofcr. Xua liswogpn lyus ryijjuiq qj xdo monfc us sbo qiwgoj kudecr hwo jesifurlip mocaguug qiq xjel zximo at pco acikaduat.
Gaw wap, pai’vd kiyx gtigi ab iwsokony as fco xojohaxjow lerareis pyoz ypep sri odn zva hamnumop pamiwuun huhcovar ux lwu howfiz.
He gao tliw deo’zi cuzo wa dxaf reajb, ba vovh da XogbikoZeis.cmucd. Inc szi zovvofavr hetu ra dje grubv oq vgo QbpeyxLeep:
Aylrioc aw guxz, guo zek qkul vse RheqxIA diof enexj wwa veso lvih(_:ak:irshub:) moyriw cofkozs om tzi nkuyiPbktih zeu iwluimip isisd puzotbaRkgsig(az:). Cos dti oxg vi quo rca cefennoj iyoqukaoy.
Uyilidic uubpzero yulcat
Key points
Don’t use animations only for the sake of doing so. Have a purpose for each animation.
Keep animations between 0.25 and 1.0 seconds in length. Shorter animations are often not noticeable. Longer animations risk annoying your user wanting to get something done.
Keep animations consistent within an app and with platform usage.
Animations should be optional. Respect accessibility settings to reduce or eliminate application animations.
Make sure animations are smooth and flow from one state to another.
Animations can make a huge difference in an app if used wisely.
Using matchedGeometryEffect lets you link view transitions into a single animation.
You can create high-performance animations by combining TimelineView and Canvas.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.