En introduksjon til kvarts 2D

Hva er kvarts 2D?

Quartz 2D er Apples 2D tegne-motor, en viktig del av Core Graphics-rammeverket. Du kan ofte se Quartz 2D referert til som Core Graphics eller bare CG.

Kvarts 2D bruker "malermodellen". I malermodellen bruker hver etterfølgende tegning operasjon et lag med "maling" til et utgangskunst "lerret", ofte kalt en side. Tenk på dette som en kunstner som arbeider på et maleri. Hvis kunstneren skulle male hele lerretblått og deretter male noen skyer på lerretet, så ville skyene dekke det blå under dem. Når noe er "malt" på lerretet, kan det ikke endres, men ved å legge til mer maling på toppen av det.

Alle tegninger i kvarts 2D er gjort gjennom en grafikk kontekst av typen CGContextRef. Med en referanse til en grafikk-kontekst kan du bruke Quartz 2D-funksjonene til å tegne til konteksten, utføre operasjoner, for eksempel å oversette konteksten og endre grafiske tilstandsparametere, for eksempel linjebredde og fyllfarge. Kvarts 2D er en C-basert API, som sådan vil du påberope C-funksjonene som passerer i konteksten som en parameter.

For å tegne til skjermen på iOS, må du underklasse a UIView og overstyr det drawRect (_ :)metode. Det er inne i dette drawRect (_ :) Metode som du vil gjøre noen egendefinert tegning. Du burde aldri Ring drawRect (_ :) Metoden direkte i koden din. Hvis du trenger å oppdatere skjermen med nye tegningskommandoer, bør du ringe metodene setNeedsDisplay () eller setNeedsDisplayInRect (_ :).

Når du bruker Quartz 2D på iOS, koordinerer du (0,0) er øverst til venstre på skjermen. X-koordinaten øker når du beveger deg rett og y-koordinaten øker mens du beveger deg ned.

Gjennom hele denne opplæringen kan det være lurt å konsultere Quartz 2D programmeringsveiledningen. Formålet med denne opplæringen er å komme i gang med Quartz 2D. Det er mye som ikke vil bli dekket og fullt ut sette pris på alt Quartz 2D har å tilby. Jeg foreslår at du leser programmeringsveiledningen.

Med denne korte introduksjonen ut av veien, la oss begynne å bruke Quartz 2D.

1. Forbereder en UIView for tegning

Forutsatt at du har et prosjekt åpent og klar til å begynne å jobbe med Quartz 2D, er trinnene du må ta, ganske enkle. Du må opprette en klasse som er en underklasse av UIView, Legg til en utsikt fra Objekt-biblioteket til prosjektet ditt i Interface Builder, og sett visningen til klassen UIView underklasse du opprettet. La oss gå gjennom dette trinnvis.

Trinn 1: Subclassing UIView

Gå til Fil > Ny > Fil… . Under iOS seksjon, velg Kilde og velg deretter Cocoa Touch Class som mal.

På skjermen som følger, gi klassen ditt navn, sørg for at det er en UIView underklasse, og sett språket til Fort. trykk neste og velg hvor du skal lagre den nye klassen din.

Hvis du ser kilden til den nyopprettede klassen din, vil du se drawRect (_ :) metode. Det er for øyeblikket kommentert, men vi vil endre det om noen få øyeblikk.

importer UIKit klasse DrawLineView: UIView / * // Bare overstyr drawRect: hvis du utfører egendefinert tegning. // En tom implementering påvirker ytelsen under animasjon negativt. overstyr func drawRect (rect: CGRect) // Tegningskode * /

Trinn 2: Legge til en visning og sette inn klassen

Åpne prosjektets storyboard og åpne Objektbibliotek til høyre. I søkefeltet nederst, skriv inn "UIView"å filtrere ut objekter vi ikke er interessert i.

Dra a UIView forekomst på visningsregulatoren. Med visningen valgt, åpner du Identitetsinspektør til høyre og endre Klasse til hva du kalt underklassen.

En hvilken som helst kode du legger til i drawRect (_ :) Metoden vil bli tegnet når UIView underklasse er instantiated. Visningen konfigurerer automatisk tegnemiljøet slik at du kan begynne å tegne umiddelbart. Visningen konfigurerer CGContextRef nevnt i begynnelsen av denne leksjonen og det er inne i drawRect (_ :) metode som du vil få en referanse til det.

2. Startprosjekt

For å komme i gang raskt har jeg gitt et startprosjekt som har alle visningene allerede koblet opp og klar til bruk. De UIView Underklasser er oppkalt etter tegningskommandoen vi skal utforske. For eksempel, når vi lærer om tegningslinjer, blir den tilsvarende klassen navngitt DrawLinesView.

Du kan laste ned startprosjektet fra GitHub. Vi vil komme i gang med koding i neste trinn.

3. Skaffe et referanse til grafikk-konteksten

Før du kan tegne, må du få en referanse til grafikk konteksten. Dette oppnås som følger.

la kontekst = UIGraphicsGetCurrentContext ()

Dette returnerer en ugjennomsiktig type, CGContextRef, og du vil passere dette kontekst inn i C-funksjonene for å gjøre den egendefinerte tegningen. Nå som vi vet hvordan vi får referanse til grafikk konteksten, kan vi begynne å utforske tegningskommandoene.

4. Tegne en linje

Hvis du har lastet ned startbildeprosjektet, åpner du DrawLineView.swift og legg til følgende i drawRect (_ :) metode.

overstyr func drawRect (kontekst, 0, 0) CGContextAddLineToPoint (kontekst, 200, 200) CGContextStrokePath (kontekst)

Vi får først en henvisning til tegningskonteksten som diskutert tidligere. Fordi dette er noe vi vil gjøre for hvert eksempel, vil jeg ikke nevne dette i de kommende eksemplene.

De CGContextSetStrokeColorWithColor (_: _ :) funksjonen setter fargen som linjen vil bli tegnet eller strøket på. Parametrene vi sender inn er grafikk konteksten og den nye slagfargen.

Hvis du tenker på grafikk konteksten som lerret av en maler, så CGContextMoveToPoint (_: _: _ :) funksjonen flytter penselen til et bestemt punkt på lerretet hvorfra man kan begynne eller fortsette å tegne. Tenk deg å tegne på et stykke papir, løfte hånden og flytte til en annen del av papiret og fortsetter å tegne. I hovedsak er det denne metoden oppnår. Vi passerer i grafikk konteksten og en x og y koordinat for å starte tegningen fra.

De CGContextAddLineToPoint (_: _: _ :) Funksjonen tar som parametere grafikk konteksten, x-verdien for slutten av linjesegmentet og y-verdien for slutten av linjesegmentet. Etter at du har lagt til linjesegmentet, blir det nåværende punktet satt til endepunktet for linjesegmentet. Vi startet tegningsoperasjonen på (0,0), etter denne tegning er markøren eller pensel på (200 200).

Til slutt, for å gjøre selve tegningen må du ringe CGContextStrokePath (_ :) Funksjonen passerer i grafikk konteksten.Denne funksjonen trekker bare en linje langs banen vi angav.

Bygg og kjør prøveprosjektet for å se effekten.

5. Tegne en rektangel

Åpen DrawRectangleView.swift og legg til følgende i drawRect (_ :) metode. Du bør være kjent med de to første linjene nå.

overstyr func drawRect (rect: CGRect) la kontekst = UIGraphicsGetCurrentContext () CGContextSetStrokeColorWithColor (kontekst, UIColor.redColor () .CGColor) la rektangel = CGRectMake (50,50, frame.size.width-100, frame.size.height- 100) CGContextAddRect (kontekst, rektangel) CGContextStrokePath (kontekst)

De CGRectMake (_: _: _: _ :) funksjon er en del av CGGeometry og gir en enkel måte å lage en CGRect struktur. Som navnet tilsier, CGRect  er en struktur som inneholder plasseringen og dimensjonene til et rektangel. EN CGRect har to felt, opprinnelse og størrelse, hvilket område CGPoint og a CGSize henholdsvis. Hvis du ikke er kjent med disse datatyper, må du lese en rask lesning i CGGeometry-referansen.

Vi lager en konstant, rektangel, bruker CGRectMake (_: _: _: _ :) funksjon og ring på CGContextAddRect (_: _ :) funksjon, som tar som parametere grafikk konteksten og a CGRect. Til slutt, vi ringer CGContextStrokePath (sammenheng) å tegne rektangelet.

Bygg og kjør prosjektet for å se rektangelet trukket til skjermen.

6. Tegne en sirkel

Åpen DrawCircleView.swift og oppdatere drawRect (_ :) metode som følger.

overstyr func drawRect (rect: CGRect) la kontekst = UIGraphicsGetCurrentContext () CGContextSetStrokeColorWithColor (kontekst, UIColor.redColor () .CGColor) la rektangel = CGRectMake (50,50, frame.size.width-100, frame.size.height- 100) CGContextAddEllipseInRect (kontekst, rektangel) CGContextStrokePath (kontekst) 

Du lurer kanskje på hvorfor vi ringer CGRectMake (_: _: _: _ :) når vi tegner en sirkel? Rektangelet er det området sirkelen må passe inn i. I koden ovenfor lager vi en sirkel ved å bruke en firkant. Hvis du vil tegne en oval eller ellipse, må du gjøre rektanglet mer rektangulært i form.

Vi kaller da CGContextAddEllipseInRect (_: _ :) funksjon, som tar som parametere grafikk konteksten og rektangelet som å tegne ellipsen. Sirkelen er tegnet ved å ringe CGContextStrokePath (_ :), passerer i grafikk konteksten.

7. Tegne en bue

Åpen DrawArcView.swift og legg til følgende kode inne i drawRect (_ :) metode.

overstyr func drawRect (rect: CGRect) la sammenheng = UIGraphicsGetCurrentContext () CGContextSetStrokeColorWithColor (kontekst, UIColor.redColor () .CGColor) CGContextAddArc (kontekst, 100,100,50,3.14,0,1) CGContextStrokePath (kontekst) 

De CGContextAddArc (_: _: _: _: _: _: _ :) funksjonen tar ganske mange parametere:

  • grafikk konteksten
  • x-verdien for buenes midtpunkt
  • y-verdien for buenes midtpunkt
  • bueens radius
  • vinkelen til startpunktet for buen, målt i radianer fra den positive x-aksen
  • vinkelen til sluttpunktet til buen, målt i radianer fra den positive x-aksen
  • en verdi på 1 å opprette en klokkebue eller en verdi på 0 å opprette en moturs-bue

8. Tegne en sti

Hvis du vil tegne mer komplekse figurer, lager du en bane og strekker den. Ta en titt på drawRect (_ :) metode i DrawPathView.swift.

overstyr func drawRect (rect: CGRect) la sammenheng = UIGraphicsGetCurrentContext () CGContextSetStrokeColorWithColor (kontekst, UIColor.redColor () .CGColor) CGContextMoveToPoint (kontekst, 25, 150) CGContextAddLineToPoint (kontekst, 175, 150) CGContextAddLineToPoint (kontekst, 100, 50 ) CGContextAddLineToPoint (kontekst, 25, 150) CGContextStrokePath (kontekst) 

I drawRect (_ :) metode, vi kaller CGContextAddLineToPoint (_: _: _ :) et antall ganger for å lage en trekant. Merk at trekanten ikke er fylt, bare strekk. I neste trinn vil vi se hvordan du fyller trekanten med farge.

9. Fyll ut en sti

Åpen FillPathView.swift og oppdatere drawRect (_ :) metode som vist nedenfor.

overstyr func drawRect (kontekst, 175, 150) CGContextAddLineToPoint (kontekst, 100, 50) CGContextAddLineToPoint (kontekst, 25, 150) CGContextSetFillColorWithColor (kontekst, 25, 150) CGContextAddLineToPoint (kontekst, , UIColor.redColor () .CGColor) CGContextFillPath (kontekst)

I det forrige trinnet strøk vi en sti, men du kan også fylle en sti med en bestemt farge. I det ovennevnte drawRect (_ :) Metode, vi begynner med å lage en bane for samme trekant som i forrige eksempel. Denne gangen setter vi en fyllfarge ved hjelp av CGContextSetFillColorWithColor (_: _ :) funksjon og samtale CGContextFillPath (_ :) heller enn CGContextStrokePath (_ :).

10. Fylling av en ellipse

Bortsett fra fyllingsbaner, kan du også fylle ellipser og rektangler. I dette eksemplet vil vi fylle en ellipse. Å fylle et rektangel er imidlertid veldig lik. Dokumentasjon vil fortelle deg hvordan det er gjort. Oppdater drawRect (_ :) metode i FillEllipseView.swift som vist under.

overstyr func drawRect (rekt: CGRect) la sammenheng = UIGraphicsGetCurrentContext () CGContextSetLineWidth (kontekst, 8.0) CGContextSetStrokeColorWithColor (kontekst, UIColor.redColor () .CGColor) la rektangel = CGRectMake (50,50, frame.size.width-100, frame.size.height-100) CGContextAddEllipseInRect (kontekst, rektangel) CGContextStrokePath (kontekst) CGContextSetFillColorWithColor (kontekst, UIColor.greenColor () .CGColor) CGContextFillEllipseInRect (kontekst, rektangel) 

Mesteparten av denne koden skal være kjent nå. Vi bruker en ny funksjon, CGContextSetLineWidth (_: _ :), å angi linjebredden og vi ringer CGContextFillEllipseInRect (_: _ :) å fylle ellipsen. Denne funksjonen tar som parametere grafikk konteksten og rektangelet for å fylle ellipsen.

11. Legge til linjer

De CGContextAddLines (_: _: _ :) funksjonen er en nyttig funksjon når du har en rekke sammenhengende rettlinjesegmenter du ønsker å tegne. Her gjenskaper vi trekanten fra tidligere i eksemplene, ved hjelp av CGContextAddLines (_: _: _ :) funksjon. Legg til følgende kode til AddLinesView.swift.

overstyr func drawRect (rekt: CGRect) la sammenheng = UIGraphicsGetCurrentContext () CGContextSetStrokeColorWithColor (kontekst, UIColor.redColor () .CGColor) la linjer = [CGPointMake (25,150), CGPointMake (175,150), CGPointMake (100,50), CGPointMake 25.150)] CGContextAddLines (kontekst, linjer, 4) CGContextStrokePath (kontekst)

De CGContextAddLines (_: _: _ :) Funksjonen tar som parametere grafikk konteksten, en rekke verdier som angir start- og sluttpunktene i linjesegmentene for å tegne som CGPoint strukturer og antall elementer i gruppen. Merk at det første punktet i arrayet angir startpunktet.

12. Tegne en gradient

Med Quartz 2D er det enkelt å tegne gradienter. Både lineære og radiale gradienter støttes. I dette eksemplet vil vi tegne en lineær gradient. Dokumentasjonen vil hjelpe deg hvis du er interessert i å tegne radiale gradienter. Legg til følgende til DrawGradientView.swift.

 overstyr func drawRect (rect: CGRect) la kontekst = UIGraphicsGetCurrentContext () la colorspace = CGColorSpaceCreateDeviceRGB () la farger = [UIColor.redColor () .CGColor, UIColor.blueColor () .CGColor] la steder: [CGFloat] = [0,0 , 0,5] la gradient = CGGradientCreateWithColors (colorpace, colors, locations) la startPoint = CGPointMake (0,0) la endPoint = CGPointMake (200,200) CGContextDrawLinearGradient (kontekst, gradient, startPoint, endPoint, 0) 

De CGContextDrawLinearGradient (_: _: _: _: _ :) funksjonen tar som parametere:

  • grafikk konteksten
  • en CGGradient struktur
  • et startpunkt
  • et sluttpunkt
  • alternativflagger som angir om fyllingen er utvidet utover start- eller sluttpunktet

EN CGGradient struktur definerer en jevn overgang mellom farger over et område. Den har en fargeplate, to eller flere farger, og et sted for hver farge. Konstantene farge rom, farger, og steder I eksemplet ovenfor representerer disse delene som utgjør CGGradient.

For å tegne graden kalles vi CGContextDrawLinearGradient (_: _: _: _: _ :) funksjon, passerer i grafikk konteksten, CGGradient, start og slutt verdier, og 0 for å indikere at fyllingen skal strekke seg utover startstedet.

13. Tegne en skygge

En skygge er et bilde som er tegnet under, og kompensert fra, et grafikkobjekt, slik at skyggen etterligner effekten av en lyskilde kastet på grafikkobjektet. - Quartz 2D Programmeringsveiledning

 Det er to funksjoner du kan bruke til å tegne skygger, CGContextSetShadow (_: _: _ :) og CGContextSetShadowWithColor (_: _: _: _ :). Når du bruker CGContextSetShadow (_: _: _ :), Alle trukket tegninger er skygget med en svart farge med 1/3 alpha. De CGContextSetShadowWithColor (_: _: _: _: funksjonen lar deg angi en farge for skyggen.

La oss se hvordan dette fungerer i praksis. Legg til følgende til SetShadowWithColor.swift.

overstyr func drawRect (rekt: CGRect) la sammenheng = UIGraphicsGetCurrentContext () CGContextSaveGState (kontekst) la shadowOffset = CGSizeMake (-15,20) CGContextSetShadowWithColor (kontekst, shadowOffset, 3, UIColor.greenColor () .CGColor) CGContextSetStrokeColorWithColor (kontekst, UIColor .redColor () .CGColor) la rektangel = CGRectMake (50,50, frame.size.width-100, frame.size.height-100) CGContextAddRect (kontekst, rektangel) CGContextStrokePath (kontekst) CGContextRestoreGState (kontekst) 

Når du tegner skygger, bør du lagre tilstanden til grafikk konteksten, foreta nødvendige endringer, og deretter gjenopprette grafikkstatus. Vi ringer CGContextSaveGState (_ :) For å lagre den nåværende tilstanden for grafikk konteksten, angi en forskyvning for skyggen, shadowOffset, og ring til CGContextSetShadowWithColor (_: _: _: _ :) funksjon. Disse funksjonene tar som parametre:

  • grafikk konteksten
  • offset for skyggen
  • sløret beløp
  • fargen på skyggen

Resten av koden skal være kjent for deg. Til slutt gjenoppretter vi grafikk konteksten ved å ringe CGContextRestoreGState (_ :), passerer i grafikk konteksten.

14. Tegne et godt ansikt

Jeg trodde det ville vært morsomt å avslutte denne opplæringen ved å tegne et enkelt lykkelig ansikt ved å bruke det vi har lært gjennom denne opplæringen. Legg til følgende til DrawHappyFaceView.swift.

overstyr func drawRect (rect: CGRect) la kontekst = UIGraphicsGetCurrentContext () la ansiktet = CGRectMake (50,50, frame.size.width-100, frame.size.height-100) CGContextAddEllipseInRect (kontekst, ansikt) CGContextSetFillColorWithColor (kontekst, UIColor.yellowColor () .CGColor) CGContextFillEllipseInRect (kontekst, ansikt) la leftEye = CGRectMake (75,75,10,10) CGContextSetFillColorWithColor (kontekst, UIColor.blackColor () .CGColor) CGContextFillEllipseInRect (kontekst, leftEye) la rightEye = CGRectMake 115,75,10,10) CGContextFillEllipseInRect (kontekst, rightEye) CGContextSetLineWidth (kontekst, 3.0) CGContextAddArc (kontekst, 100,100,30,3,14,0,1) CGContextStrokePath (kontekst) 

Gjennomføringen av drawRect (_ :) Metoden skal være fornuftig nå, og du bør ha et godt ansikt trukket til skjermen.

Konklusjon

Dette bringer denne opplæringen til en slutt. Du bør nå ha en grunnleggende forståelse av hvordan du utfører tilpasset tegning ved hjelp av Quartz 2D tegningsmotoren. Jeg håper du har lært noe nyttig ved å lese denne opplæringen.