Hvordan bygge en Semi-Circle Donut Chart med CSS

Selv om HTML5 Canvas og SVG kan være mer elegante løsninger for å bygge diagrammer, lærer vi i denne opplæringen hvordan vi bygger vårt eget doughnutdiagram med ingenting annet enn vanlig CSS.

For å få en ide om hva vi skal skape, ta en titt på den innebygde CodePen-demoen nedenfor:

HTML Markup

Vi starter med noen veldig grunnleggende oppslag; en vanlig uordnet liste med a span element i hver av listepostene: 

  • CSS
  • HTML
  • PHP
  • Python

Legge til stiler i listen

Med markeringen klar, bruker vi først noen grunnleggende stiler til den uordnede listen:

.kart-ferdigheter posisjon: relativ; bredde: 350px; høyde: 175px; 

Da skal vi gi hver en en ::etter og a ::før pseudo-element, og stil dem:

.diagram ferdigheter :: før, .chart-ferdigheter :: etter posisjon: absolutt;  .chart-ferdigheter :: før innhold: "; bredde: arv, høyde: arv, grense: 45px solid rgba (211,211,211, .3); grensebunn: ingen; grense øverst til venstre: 175px; grense øverste ferdigheter: venstre: 50%; bunn: 10px; transform: translateX (-50%); skriftstørrelse: 1,1m; font-weight: bold; color: cadetblue;

Vær oppmerksom på stilene for ::før pseudo-element. Dette gir oss vår halvsirkel.

Pseudo-elementer

Så langt gir ovennevnte regler oss dette resultatet:

Legge til stiler i listepostene

La oss nå diskutere stylingen av listepostene.

posisjonering 

Med hensyn til listepostposisjonen gjør vi følgende:

  • Plasser dem rett under foreldrene sine og
  • gi dem passende stiler for å opprette en omvendt halvcirkel.

Videre er et par ting verdt å merke seg her:

  • Listen elementer er helt posisjonert, og dermed kan vi sette deres z-indeks eiendom.
  • Vi endrer standardinnstillingen forvandle-opprinnelse eiendomsverdi (dvs.. transformasjons-opprinnelse: 50% 50%) i listepostene. Spesielt setter vi transformasjons-opprinnelse: 50% 0. På denne måten, når vi animerer (roterer) elementene, blir senterets øverste hjørne rotasjonscentrumet.

Her er de tilknyttede CSS-stilene:

.diagram ferdigheter li posisjon: absolutt; topp: 100%; venstre: 0; bredde: arv; høyde: arv; grense: 45px solid; border-top: none; Bensin-venstre-radius: 175px; grense bunn-høyre-radius: 175px; transformasjons-opprinnelse: 50% 0;  .chart-ferdigheter li: nth-child (1) z-indeks: 4; border-farge: grønn;  .chart-skills li: nth-child (2) z-indeks: 3; border-farge: firebrick;  .chart-ferdigheter li: nth-child (3) z-indeks: 2; border-farge: steelblue;  .chart-ferdigheter li: nth-child (4) z-index: 1; border-farge: oransje; 

Ta en titt på hva vi har bygget så langt i neste visualisering:

spenner og listeposter

For øyeblikket er det eneste listen elementet som er synlig, den grønne (som har z-indeks: 4;) de andre er under den.

animasjoner

Før vi dekker trinnene for å animere våre listeelementer, la vi merke til ønsket prosentandel for hvert element (dvs.: hvor mye av doughnut hver vil dekke). Vurder følgende tabell:

Språk Prosentdel
CSS 12
HTML 32
PHP 34
Python 22

Deretter beregner vi hvor mange grader vi må animere (rotere) hver av elementene. For å finne ut nøyaktig antall grader for hvert element, multipliserer vi prosentandelen med 180 ° (ikke 360 ​​° fordi vi bruker en halvsirkel donut diagram):

Språk Prosentdel
Antall grader
CSS 12 12/100 * 180 = 21,6
HTML 32
32/100 * 180 = 57,6
PHP 34 34/100 * 180 = 61.2
Python 22 22/100 * 180 = 39,6

På dette tidspunktet er vi klare til å sette opp animasjonene. Først definerer vi noen animasjonsstiler som deles over alle elementer, ved å legge til noen regler for .kart-ferdigheter li:

 animasjons-fyll-modus: fremover; animasjon-varighet: .4s; animasjon-timing-funksjon: lineær; 

Deretter definerer vi de unike animasjonsstilene:

.diagram ferdigheter li: nth-barn (1) z-indeks: 4; border-farge: grønn; animasjonsnavn: roter-en;  .chart-skills li: nth-child (2) z-indeks: 3; border-farge: firebrick; animasjonsnavn: roter-to; animasjonsforsinkelse: .4s;  .chart-ferdigheter li: nth-child (3) z-indeks: 2; border-farge: steelblue; animasjonsnavn: roter-tre; animasjonsforsinkelse: .8s;  .chart-ferdigheter li: nth-child (4) z-index: 1; border-farge: oransje; animasjonsnavn: roter-fire; animasjonsforsinkelse: 1.2s; 

Legg merke til at vi legger til en forsinkelse for alle elementer bortsett fra den første. På denne måten oppretter vi fine sekvensielle animasjoner. For eksempel når animasjonen til det første elementet avsluttes, vises det andre elementet og så videre. 

Det neste trinnet er å spesifisere de faktiske animasjonene:

@keyframes rotere-en 100% transform: roter (21.6deg); / ** * 12% => 21.6deg * / @keyframes rotere-to 0% transform: roter (21.6deg);  100% transform: roter (79.2deg); / ** * 32% => 57.6deg * 57.6 + 21.6 => 79.2deg * / @keyframes rotere-tre 0% transform: roter (79.2deg);  100% transform: roter (140.4deg); / ** * 34% => 61.2deg * 61.2 + 79.2 => 140.4deg * / @keyframes rotere-fire 0% transform: roter (140.4deg);  100% transform: roter (180deg); / ** * 22% => 39.6deg * 140.4 + 39.6 => 180deg * /

Før vi går videre, ser vi kort hvordan animasjonene fungerer:

Det første elementet går fra transformere: ingen til transformere: roter (21.6deg).

Det andre elementet går fra transformere: roter (21.6deg)  (starter fra den endelige posisjonen til det første elementet) til transformer: roter (79.2deg) (57.6deg + 21.6deg). 

Det tredje elementet går fra transformer: roter (79.2deg)  (starter fra den endelige plasseringen til det andre elementet) til transformer: roter (140.4deg) (61.2deg + 79.2deg).

Det fjerde elementet går fra transformer: roter (140.4deg)  (starter fra den endelige plasseringen til det tredje elementet) til transformer: roter (180deg) (140.4deg + 39.6deg).

Gjemme seg!

Sist men ikke minst, for å skjule nederste halvdel av diagrammet, må vi legge til følgende regler:

.kart-ferdigheter / * eksisterende regler ... * / overløp: skjult;  .chart-skills li / * eksisterende regler ... * / transform-style: preserve-3d; backface-synlighet: skjult; 

De overløp: skjult eiendomsverdi sikrer at bare den første halvcirkelen (den som er opprettet med ::før pseudo-element) er synlig. Ta gjerne bort den egenskapen hvis du vil teste startposisjonen til listepostene. 

De transform-stil: preserve-3d og backface-synlighet: skjult Egenskaper hindrer flimrende effekter som kan oppstå i forskjellige nettlesere på grunn av animasjoner. Hvis dette problemet fortsatt finnes i nettleseren din, kan du også prøve disse løsningene.

Diagrammet er nesten klart! Alt som gjenstår er å stile kartetikettene, som vi skal gjøre i neste avsnitt.

Her er CodePen-demoen som viser det nåværende utseendet på diagrammet vårt:

Legge til stiler på etikettene

I denne delen skal vi stile kartetikettene.

posisjonering

Med hensyn til deres stilling gjør vi følgende:

  • Gi dem posisjon: absolutt og bruk topp og venstre egenskaper for å sette sin ønskede posisjon.
  • Bruk negative verdier for å rotere dem. Selvfølgelig er disse ikke tilfeldige verdier. Faktisk blir disse hentet fra den siste rammen av deres overordnede element. For eksempel inkluderer den siste rammen til den andre listeposten transformer: roter (79.2deg), og dermed den tilhørende etiketten vil ha transformer: roter (-79.2deg).

Nedenfor er de tilsvarende CSS-stilene:

.kart-ferdigheter span posisjon: absolutt; skriftstørrelse: .85rem;  .chart-ferdigheter li: nth-child (1) span top: 5px; igjen: 10px; transformere: roter (-21.6deg);  .chart-ferdigheter li: nth-child (2) span top: 20px; igjen: 10px; transformer: roter (-79.2deg);  .chart-ferdigheter li: nth-child (3) span top: 18px; igjen: 10px; transformer: roter (-140.4deg);  .chart-ferdigheter li: nth-child (4) span top: 10px; igjen: 10px; transformere: roter (-180deg); 

animasjoner

Nå som vi har plassert etikettene, er det på tide å animere dem. To ting er verdt å nevne her:

  • Som standard er alle etiketter gjemt og blir synlige ettersom deres overordnede element blir animert. 
  • På samme måte som foreldrematerialene bruker vi animasjon-forsinkelse eiendom for å lage sekvensielle animasjoner. I tillegg legger vi til backface-synlighet: skjult eiendomsverdi for å sikre at det ikke er noen flimrende effekter på grunn av animasjoner.

CSS-reglene som omhandler animasjonen av diagrametikettene er vist nedenfor:

.kart-ferdigheter span backface-synlighet: skjult; animasjon: fade-in .4s lineær fremover;  .chart-ferdigheter li: nth-child (2) span animasjon-forsinkelse: .4s;  .chart-ferdigheter li: nth-child (3) span animasjon-forsinkelse: .8s;  .chart-ferdigheter li: nth-child (4) span animasjon-forsinkelse: 1.2s;  @keyframes fade-in 0%, 90% opacity: 0;  100% opacity: 1; 

Her er det endelige diagrammet:

Nettleserstøtte og problemer

Generelt fungerer demoen bra i alle nettlesere. Jeg vil bare diskutere to små problemer som er relatert til border-radius eiendom.

Først, hvis vi skulle gi forskjellige farger til elementene våre, kan diagrammet se slik ut: 

Legg merke til for eksempel øverste og nederste hjørner av det tredje elementet. Det er to røde linjer som kommer fra grensefargen til det fjerde elementet. Vi kan se disse linjene fordi det fjerde elementet har en mørkere kantfarge i forhold til den tredje. Selv om dette er et lite problem, er det godt å være klar over det for å velge passende farger for dine egne diagrammer.

For det andre, i Safari vises diagrammet som følger:

Se på de små hullene som vises i andre og tredje elementer. Hvis du vet noe om dette problemet, gi oss beskjed i kommentarene nedenfor!

Konklusjon

I denne opplæringen gikk vi gjennom prosessen med å lage et halvcirkel-donutdiagram med rent CSS. Igjen, som nevnt i introduksjonen, er det potensielt kraftigere løsninger (for eksempel HTML5 Canvas og SVG) der ute for å skape slike ting. Men hvis du vil bygge noe enkelt og lett, og nyt en utfordring, er CSS veien å gå!