2014-11-18 12 views
7

Sto provando a creare una barra di navigazione 3D utilizzando puro CSS con trasformazioni, transizioni e prospettiva.3D Navbar che ruota

Ecco il mio codice:

.navbar-fixed-bottom { 
 
\t background: transparent; 
 
\t } 
 
\t 
 
\t .navbar-perspective { 
 
\t width: 100%; 
 
\t height: 100%; 
 
\t position: relative; 
 
\t -webkit-perspective: 1100px; 
 
\t -moz-perspective: 1100px; 
 
\t perspective: 1100px; 
 
\t -webkit-perspective-origin: 50% 0; 
 
\t -moz-perspective-origin: 50% 0; 
 
\t perspective-origin: 50% 0; 
 
\t } 
 
\t 
 
\t .navbar-perspective > div { 
 
\t margin: 0 auto; 
 
\t position: relative; 
 
\t text-align: justify; 
 
\t -webkit-backface-visibility: hidden; 
 
\t -moz-backface-visibility: hidden; 
 
\t backface-visibility: hidden; 
 
\t -webkit-transition: all 0.5s; 
 
\t -moz-transition: all 0.5s; 
 
\t transition: all 0.5s; 
 
\t height: 50px; 
 
\t font-size:20px; 
 
\t } 
 
\t 
 
\t .navbar-primary { 
 
\t background-color: #cccccc; 
 
\t z-index: 2; 
 
\t -webkit-transform-origin: 0% 100%; 
 
\t -moz-transform-origin: 0% 100%; 
 
\t transform-origin: 0% 100%; 
 
\t } 
 
\t 
 
\t .navbar .navbar-secondary, 
 
\t .navbar .navbar-tertiary { 
 
\t background-color: #bfbfbf; 
 
\t width: 100%; 
 
\t -webkit-transform-origin: 0% 0%; 
 
\t -moz-transform-origin: 0% 0%; 
 
\t transform-origin: 0% 0%; 
 
\t z-index: 1; 
 
\t -webkit-transform: rotateX(-90deg); 
 
\t -moz-transform: rotateX(-90deg); 
 
\t transform: rotateX(-90deg); 
 
\t -webkit-transition: top 0.5s; 
 
\t -moz-transition: top 0.5s; 
 
\t transition: top 0.5s; 
 
\t position: absolute; 
 
\t top: 0; 
 
\t } 
 
\t 
 
\t .navbar .navbar-tertiary { 
 
\t background-color: #b3b3b3; 
 
\t } 
 
\t 
 
\t .navbar-rotate-primary { 
 
\t height: 50px; 
 
\t } 
 
\t 
 
\t .navbar-rotate-primary .navbar-primary { 
 
\t -webkit-transform: translateY(0%) rotateX(0deg); 
 
\t -moz-transform: translateY(0%) rotateX(0deg); 
 
\t transform: translateY(0%) rotateX(0deg); 
 
\t } 
 
\t 
 
\t .navbar-rotate-primary .navbar-secondary, 
 
\t .navbar-rotate-primary .navbar-tertiary { 
 
\t top: 100%; 
 
\t -webkit-transition: -webkit-transform 0.5s; 
 
\t -moz-transition: -moz-transform 0.5s; 
 
\t transition: transform 0.5s; 
 
\t -webkit-transform: rotateX(-90deg); 
 
\t -moz-transform: rotateX(-90deg); 
 
\t transform: rotateX(-90deg); 
 
\t } 
 
\t 
 
\t .navbar-rotate-secondary, 
 
\t .navbar-rotate-tertiary { 
 
\t height: 50px; 
 
\t } 
 
\t 
 
\t .navbar-rotate-secondary .navbar-primary, 
 
\t .navbar-rotate-tertiary .navbar-primary { 
 
\t -webkit-transform: translateY(-100%) rotateX(90deg); 
 
\t -moz-transform: translateY(-100%) rotateX(90deg); 
 
\t transform: translateY(-100%) rotateX(90deg); 
 
\t } 
 
\t 
 
\t .navbar-rotate-secondary .navbar-secondary, 
 
\t .navbar-rotate-tertiary .navbar-secondary { 
 
\t top: 100%; 
 
\t -webkit-transition: -webkit-transform 0.5s; 
 
\t -moz-transition: -moz-transform 0.5s; 
 
\t transition: transform 0.5s; 
 
\t -webkit-transform: rotateX(0deg) translateY(-100%); 
 
\t -moz-transform: rotateX(0deg) translateY(-100%); 
 
\t transform: rotateX(0deg) translateY(-100%); 
 
\t } 
 
\t 
 
\t .navbar-rotate-secondary-fallback .navbar-primary, 
 
\t .navbar-rotate-tertiary-fallback .navbar-primary { 
 
\t display: none; 
 
\t } 
 
\t 
 
\t .navbar-rotate-tertiary .navbar-secondary { 
 
\t -webkit-transform: translateY(-100%) rotateX(90deg); 
 
\t -moz-transform: translateY(-100%) rotateX(90deg); 
 
\t transform: translateY(-100%) rotateX(90deg); 
 
\t } 
 
\t 
 
\t .navbar-rotate-tertiary .navbar-tertiary { 
 
\t top: 100%; 
 
\t -webkit-transition: -webkit-transform 0.5s; 
 
\t -moz-transition: -moz-transform 0.5s; 
 
\t transition: transform 0.5s; 
 
\t -webkit-transform: rotateX(0deg) translateY(-100%); 
 
\t -moz-transform: rotateX(0deg) translateY(-100%); 
 
\t transform: rotateX(0deg) translateY(-100%); 
 
\t }
<html> 
 

 
<head> 
 

 
\t <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 

 
</head> 
 

 
<body> 
 

 
\t <nav id="navigation-bottom" class="navbar navbar-fixed-bottom"> 
 
\t \t <div class="navbar-perspective"> 
 
\t \t \t <div class="navbar-primary"> 
 
\t \t \t \t <a href="javascript:void(0);" onclick="$('#navigation-bottom').attr('class','navbar navbar-fixed-bottom navbar-rotate-secondary')">Rotate To Face 2</a> 
 
\t \t \t </div> 
 
\t \t \t <div class="navbar-secondary"> 
 
\t \t \t \t <a href="javascript:void(0);" onclick="$('#navigation-bottom').attr('class','navbar navbar-fixed-bottom navbar-rotate-tertiary')">Rotate To Face 3</a> 
 
\t \t \t </div> 
 
\t \t \t <div class="navbar-tertiary"> 
 
\t \t \t \t <a href="javascript:void(0);" onclick="$('#navigation-bottom').attr('class','navbar navbar-fixed-bottom navbar-rotate-primary')">Rotate Back To Face 1</a> 
 
\t \t \t </div> 
 
\t \t </div> 
 
\t </nav> 
 

 
</body> 
 

 
</html>

ho i primi due facce per ruotare correttamente utilizzando un effetto 3D, ma la terza faccia non sembra giusto. Noterai mentre ruoti dalla seconda alla terza che la parte superiore non ruota correttamente e sembra piatta.

Qualsiasi aiuto è molto apprezzato.

+0

Ecco un JSFiddle: http://jsfiddle.net/wcb6kerq/ – Armin

risposta

-1

Prima di tutto, grazie a tutti quelli che hanno commentato e risposto a questa domanda, soprattutto Josh!

Josh, il tuo esempio funziona perfettamente per i browser che supportano preserve-3d. L'aggiornamento che hai postato senza preserve-3d appare piatto su IE quindi non è stato ancora perfezionato per tutti i browser.

Dopo tre giorni di mal di testa, ho capito il problema. L'origine dei lati non veniva impostata correttamente. I lati devono ruotare attorno a un punto che si trova a metà dell'asse Z.

Una volta che ho aggiornato l'origine:

transform-origin: 25px 25px -25px; 

Una volta che questo è stato corretto, tutto quello che dovete fare è aggiornare la rotazione dell'oggetto. Non è necessario utilizzare alcuna trasformazione delle coordinate X, Y, Z.

Ecco il violino e la soluzione per una barra di navigazione 3D che ruota e funziona per tutti i browser incluso IE10 +.

http://jsfiddle.net/tx0emcxe/

+0

Josh, il tuo esempio su IE non ha prospettive. È come guardare un oggetto 3D dalla parte anteriore. Quando i lati ruotano, i lati non si muovono verso il centro, apparendo così piatti. – Armin

+1

@misterManSam - Sei assolutamente corretto in questo e sono ben consapevole. Tuttavia, mi sento un po 'seccato per il comportamento e l'insistenza del richiedente che la mia risposta è stata in qualche modo incompleta, anche nella sua risposta accettata. Non preoccupato per la ricompensa che viene premiata tanto. Nell'interesse di non essere favorevole alla comunità qui, ho rimosso i miei commenti. Punto preso. –

7

Fiddle with a flipping box

Questo è molto diverso da dove si è partiti, ma permettetemi di posto la mia CSS e ti mostri il violino, e poi Io modificare in una spiegazione più lunga di come e perché funziona:

 

HTML

<section class="container"> 
    <nav id="nav-box" class="show-front"> 
     <div class="front"> 
      <a href="#">Show Bottom</a> 
     </div> 
     <div class="bottom"> 
      <a href="#">Show Back</a></div> 
     <div class="back"> 
      <a href="#">Show Top</a></div> 
     <div class="top"> 
      <a href="#">Show Front</a></div> 
    </nav> 
</section> 

 

CSS

.container { 
    position: relative; 
    perspective: 1000px; 
    transform: scale(0.95); 
} 

#nav-box { 
    width: 100%; 
    height: 50px; 
    position: absolute; 
    transform-origin: center center; 
    transform-style: preserve-3d; 
    transition: transform 0.5s; 
} 

#nav-box div { 
    width: 100%; 
    height: 50px; 
    display: block; 
    position: absolute; 
    transition: background-color 0.5s; 
} 

#nav-box .front { transform: rotateX( 0deg) translateZ(25px); background-color: #ccc; } 
#nav-box .back { transform: rotateX(180deg) translateZ(25px); background-color: #ccc; } 
#nav-box .top { transform: rotateX( 90deg) translateZ(25px); background-color: #ccc; } 
#nav-box .bottom { transform: rotateX(-90deg) translateZ(25px); background-color: #ccc; } 

#nav-box.show-front { transform: rotateY( 0deg); } 
#nav-box.show-front .bottom { background-color: #a0a0a0; } 
#nav-box.show-front .top { background-color: #e0e0e0; } 
#nav-box.show-back { transform: rotateX(-180deg); } 
#nav-box.show-back .bottom { background-color: #e0e0e0; } 
#nav-box.show-back .top { background-color: #a0a0a0; } 
#nav-box.show-top { transform: rotateX( -90deg); } 
#nav-box.show-top .front { background-color: #a0a0a0; } 
#nav-box.show-top .back { background-color: #e0e0e0; } 
#nav-box.show-bottom { transform: rotateX( 90deg); } 
#nav-box.show-bottom .front { background-color: #e0e0e0; } 
#nav-box.show-bottom .back { background-color: #a0a0a0; } 

 

Spiegazione del codice HTML/CSS

Impostazione nostra casella

Hai iniziato a pensare a questo modo sbagliato, ho odio dire Ti sei avvicinato a questo come "Come posso trattare questi quattro lati come una scatola" anziché "Come posso creare una scatola in CSS?"

Quindi impariamo come creare una scatola.

In primo luogo, stabiliamo un contenitore box. Poiché si tratta di una casella di navigazione, chiamiamola nav-box. Tutte le trasformazioni che applichiamo (salvo per l'ombreggiatura, che avremo in seguito) saranno eseguite sul nostro nav-box.

Le regole sul nostro nav-box determineranno come si comporta come un oggetto. Ne discutiamo due in particolare: transform-origin e transform-style

transform-origin predefinito al centro, ma volevo chiamarlo qui. Questo in pratica dirà la nostra casella: Ehi, abbiamo bisogno che tu ruoti attorno al tuo centro assoluto. Se lo impostiamo come transform-origin: center bottom' it would look like the box is spinning around its bottom edge. centro in alto` e ruoterebbe attorno al suo bordo superiore. Non penso che sia quello che vuoi, però.

transform-style deve essere impostato su preserve-3d. Ciò che fa è istruire il browser a non agitarsi con gli elementi con transform al di sotto di esso.Altre opzioni includono flat che indica al browser di ignorare le rotazioni al di sotto di esso. Il motivo per cui vogliamo impostare preserve-3d sul nostro nav-box qui è quello di garantire che il transforms che abbiamo applicato ai lati della scatola siano stati mantenuti quando abbiamo transform il genitore. Roba ordinata, eh?

Impostazione nostri lati

Stiamo impostando i nostri lati come figli del nostro nav-box e proprio posizionandoli nell'ordine in cui essi dovrebbero essere nel usando rotateX:

  • 0 rotazione per il anteriore
  • 180deg per il retro
  • -90deg per il fondo
  • 90deg per la parte superiore

potremmo anche impostare un lato destro e sinistro a destra ora con .left { transform: rotateY(-90deg); } .right { rotateY(90deg); }. Si noti che abbiamo utilizzato l'asse Y per questi due esempi.

In secondo luogo, abbiamo impostato un valore translateZ di 25px. Quindi cosa diavolo sta facendo? Sta dicendo alle nostre scatole che devono spostare 25px dal centro del genitore rispetto alle rispettive rotazioni. Perché abbiamo scelto 25px? Perché è esattamente la metà dell'altezza di ciascuna delle nostre scatole. Ciò significa che si riempirà bene con i lati su entrambi i lati.

E poi la parte divertente:

Abbiamo ombra le caselle in base alla loro posizione e ciò che è di fronte allo schermo. I colori di sfondo sono relativi a quale lato della scatola stiamo mostrando con show-front, show-back, ecc. Il lato sul fondo diventa più scuro, il lato in alto diventa più chiaro. Mi è piaciuto, non è assolutamente necessario per svolgere questo compito, ma lo rende un po 'più realistico.

Spero che questo aiuti!

 


Aggiornamento per IE

Fiddle Example

Quindi, non c'è molto carina su questo una volta che otteniamo attraverso il fissaggio per IE, ma qui è. Tutto ciò che sta facendo preserve-3d consiste nell'applicare le trasformazioni per te quando ruotiamo un contenitore, invece di appiattirle. Se non possiamo usare preserve-3d, dobbiamo calcolare in base alla quantità di rotazione totale.

Questa soluzione lo fa. Non voglio entrare come in profondità su questo, piuttosto che per evidenziare quanto più JavaScript questo richiede, e per evidenziare la classe .rewind:

#nav-box.rewind div { 
    backface-visibility: hidden; 
} 

Perché dobbiamo riavvolgere manualmente questa soluzione, faremo impedire che il riordino dello z-index venga applicato nei momenti sbagliati. È qui che entra in gioco backface-visibility.

Example showing depth in IE

Another example without the need for the rewind class

speranza che risolve IE per voi.

+0

Grazie per la risposta, ma questo non funziona su IE perché si sta utilizzando la proprietà preserve3d. Il trucco è NON usare quella proprietà. – Armin

+0

@Armin - Controlla la modifica. Ti ho dato una correzione valida per IE. –

+0

Meglio, funziona per IE ma la prospettiva è piatta. – Armin