Comment créer des sphères CSS à 3 dimensions?

tl; dr: Je voudrais créer une sphère 3d avec CSS – pas seulement une illusion

Remarque: certains exemples d’extraits de code ne répondent pas. Veuillez utiliser le plein écran.


Avec du CSS pur, vous pouvez créer et animer un cube 3D comme suit:

#cube-wrapper { position: absolute; left: 50%; top: 50%; perspective: 1500px; } .cube { position: relative; transform-style: preserve-3d; animation-name: rotate; animation-duration: 30s; animation-timing-function: linear; animation-iteration-count: infinite; } @keyframes rotate { 0% { transform: rotate3d(0, 0, 0, 0); } 100% { transform: rotate3d(0, 1, 0, 360deg); ; } } .face { position: absolute; width: 200px; height: 200px; border: solid green 3px; } #front_face { transform: translateX(-100px) translateY(-100px) translateZ(100px); background: rgba(255, 0, 0, 0.5); } #back_face { transform: translateX(-100px) translateY(-100px) translateZ(-100px); background: rgba(255, 0, 255, 0.5); } #right_face { transform: translateY(-100px) rotateY(90deg); background: rgba(255, 255, 0, 0.5); } #left_face { transform: translateY(-100px) translateX(-200px) rotateY(90deg); background: rgba(0, 255, 0, 0.5); } #top_face { transform: translateX(-100px) translateY(-200px) rotateX(90deg); background: rgba(0, 255, 255, 0.5); } #bottom_face { transform: translateX(-100px) rotateX(90deg); background: rgba(255, 255, 255, 0.5); } .cube { transform: rotateX(90deg) rotateY(90deg); } 
 

Je veux créer et animer une sphère 3D de la même manière.

Donc, la première idée que je reçois est d’utiliser border-radius et … eh bien … ça ne marche pas.

 #cube-wrapper { position: absolute; left: 50%; top: 50%; perspective: 1500px; } .cube { position: relative; transform-style: preserve-3d; animation-name: rotate; animation-duration: 30s; animation-timing-function: linear; animation-iteration-count: infinite; } @keyframes rotate { 0% { transform: rotate3d(0, 0, 0, 0); } 100% { transform: rotate3d(0, 1, 0, 360deg); ; } } .face { position: absolute; width: 200px; height: 200px; border: solid green 3px; border-radius: 100vw } #front_face { transform: translateX(-100px) translateY(-100px) translateZ(100px); background: rgba(255, 0, 0, 0.5); } #back_face { transform: translateX(-100px) translateY(-100px) translateZ(-100px); background: rgba(255, 0, 255, 0.5); } #right_face { transform: translateY(-100px) rotateY(90deg); background: rgba(255, 255, 0, 0.5); } #left_face { transform: translateY(-100px) translateX(-200px) rotateY(90deg); background: rgba(0, 255, 0, 0.5); } #top_face { transform: translateX(-100px) translateY(-200px) rotateX(90deg); background: rgba(0, 255, 255, 0.5); } #bottom_face { transform: translateX(-100px) rotateX(90deg); background: rgba(255, 255, 255, 0.5); } .cube { transform: rotateX(90deg) rotateY(90deg); } 
 

J’ai donc reconsidéré mon approche et cherché une méthode différente.

J’ai regardé:

  • Implémenter “Pure CSS Sphere” dans le site Web – comment puis-je le faire?
  • Comment créer une sphère en CSS?
  • Afficher une image entourant une sphère avec CSS / Javascript
  • cssanimation.rocks – Sphères CSS
  • MDN – Cercle

Ensuite, j’ai essayé à nouveau … le mieux que j’ai eu était des illusions d’ object 3D trop compliquées .

Comme ça:

 body { overflow: hidden; background: #333; } .wrapper { margin: 1em; animation-duration: 20s; } .planet, .planet:before, .planet:after { height: 300px; width: 300px; border-radius: 100vw; will-change: transform; margin: 0 auto; } .planet { box-shadow: inset 0px 0px 10px 10px rgba(0, 0, 0, 0.4); position: relative; } .wrapper, .planet, .planet:before { animation-name: myrotate; animation-duration: 20s; } .wrapper, .planet, .planet:before, .planet:after { animation-timing-function: linear; animation-iteration-count: infinite; } .planet:before, .planet:after { content: ''; position: absolute; top: 0; left: 0; } .planet:before { box-shadow: inset 20px 20px 100px 00px rgba(0, 0, 0, .5), 0px 0px 5px 3px rgba(0, 0, 0, .1); } .planet:after { filter: saturate(2.5); background: linear-gradient(rgba(0, 0, 0, 1), transparent), url("http://soffr.miximages.com/css/eDYPN.jpg"); opacity: 0.3; box-shadow: inset -20px -20px 14px 2px rgba(0, 0, 0, .2); animation-name: myopacity; animation-duration: 5000000s; } @keyframes myrotate { 0% { transform: rotatez(0deg); } 100% { transform: rotatez(360deg); } } @keyframes myopacity { 0% { background-position: 0px; transform: rotatez(0deg); } 50% { background-position: 100000000px; } 100% { background-position: 0; transform: rotatez(-360deg); } } 
 

Et ça:

 body { background: #131418; } .wrapper { margin: 1em; max-width: 100%; position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); } .planet, .planet:before, .planet:after { height: 500px; width: 500px; max-height: 30vw; max-width: 30vw; border-radius: 100vw; will-change: transform; } .planet { box-shadow: inset 0px 0px 100px 10px rgba(0, 0, 0, .5); position: relative; float: left; margin: 0 2em; } .planet, .planet:before, .planet:after { animation-name: myrotate; animation-duration: 10s; } .wrapper, .planet, .planet:before, .planet:after { animation-timing-function: linear; animation-iteration-count: infinite; } .planet:before, .planet:after { content: ''; position: absolute; top: 0; left: 0; } .planet:before { box-shadow: inset 50px 100px 50px 0 rgba(0, 0, 0, .5), 0 0 50px 3px rgba(0, 0, 0, .25); background-image: -webkit-radial-gradient( top, circle cover, #ffffff 0%, #000000 80%); opacity: .5; } .planet:after { opacity: .3; background-image: -webkit-radial-gradient( bottom, circle, #ffffff 0%, #000000 -200%); box-shadow: inset 0px 0px 100px 50px rgba(0, 0, 0, .5); } @keyframes myrotate { 0% { transform: rotatez(0deg); } 100% { transform: rotatez(-360deg); } } .bg { background: wheat; } 
 

Ce qui est acceptable jusqu’à ce que vous essayiez de les faire pivoter sur l’ axe des x ou sur l’ axe des y comme le cube dans mon premier exemple … voici ce qui se passe: (exemple simplifié)

 .sphere { background: black; width: 300px; height: 300px; border-radius: 100vw; animation: myrotate 10s linear infinite } @keyframes myrotate { 0% { transform: rotate3d(0, 0, 0, 0); } 100% { transform: rotate3d(0, 1, 0, 360deg); } } 
 

Tout ce que vous obtenez est un object 2D plat – qui est considéré comme étant ce que l’élément est


La chose la plus proche que j’ai trouvée est la forme suivante créée dans un tutoriel par Timo Korinth

 @-webkit-keyframes animateWorld { 0% { -webkit-transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); } 50% { -webkit-transform: rotateY(360deg) rotateX(180deg) rotateZ(180deg); } 100% { -webkit-transform: rotateY(720deg) rotateX(360deg) rotateZ(360deg); } } html { background: #FFFFFF; } . world { -webkit-perspective: 1000px; } .cube { margin-left: auto; margin-right: auto; position: relative; width: 200px; height: 200px; -webkit-transform-style: preserve-3d; -webkit-animation-name: animateWorld; -webkit-animation-duration: 10s; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; } .circle { position: absolute; width: 100%; height: 100%; border: 2px dashed #009BC2; border-radius: 50%; opacity: 0.8; background: rgba(255, 255, 255, 0); } .zero { -webkit-transform: rotateX(90deg); } .two { -webkit-transform: rotateY(45deg); } .three { -webkit-transform: rotateY(90deg); } .four { -webkit-transform: rotateY(135deg); } .five { width: 173px; height: 173px; margin: 14px; -webkit-transform: rotateX(90deg) translateZ(50px); } .six { width: 173px; height: 173px; margin: 14px; -webkit-transform: rotateX(90deg) translateZ(-50px); } 
 


Alors voici ma

Question:

Comment créer une sphère sortingdimensionnelle réelle avec du CSS pur? Plus précisément, celui qui est couvert – pas seulement un cadre – et n’implique pas des centaines d’éléments HTML.


Remarques:

  1. Les sphères sortingdimensionnelles ont la hauteur, la largeur et la profondeur – tout comme le cube dans mon premier exemple
  2. Je n’ai pas besoin de physique et aucune interaction avec l’utilisateur n’est nécessaire. Juste une sphère tournante animée.

Ressources additionnelles:

  1. paulrhayes.com – Sphères
  2. 3D (2d illusion) Terre avec animation tournante avec CSS
  3. Sphère CSS interactive

Ssortingctement parlant, toute forme “3D” sur un écran plat est davantage une illusion d’un object 3D. Tout ce que nous voyons est une projection 2D de cette forme sur le plan de l’écran, et notre cerveau fait de son mieux pour deviner quelle forme pourrait donner la projection que nous voyons. Si la projection change, notre cerveau l’interprète comme un object 3D changeant d’orientation, ce qui l’aide à mieux déterminer la forme de cet object.

Cela fonctionne bien avec des objects non symésortingques et des objects fabriqués à partir de polygones (par exemple, des cubes), mais la sphère est un cas très particulier: sa projection sur le plan ne donne toujours qu’un cercle. La sphère statique et la sphère rotative ont la même projection, le même cercle. Même dans la vraie vie, si nous regardons une sphère avec une surface uniforme sans aucune marque (par exemple, une boule de métal polie), il est difficile de déterminer si elle rest immobile ou tourne. Nos yeux ont besoin de quelques conseils, certains détails se déplacent le long de la surface de la sphère en fonction de sa géomésortinge. Plus ces détails se déplacent de la manière que vous attendez des points de la surface sphérique à déplacer, plus la perception de la sphère en rotation est claire.

Et voici la clé du problème en créant une scène CSS qui donnerait une telle perception: pour que cette illusion soit suffisamment forte, nous avons besoin de nombreuses marques qui se déplacent le long des chemins qui se trouvent dans des plans différents. Et la seule façon d’obtenir ceci en CSS est d’avoir chaque marque en tant que boîte CSS distincte (élément ou pseudo-élément). Si notre sphère ne comprend que des marques en mouvement, nous en avons vraiment besoin pour la voir comme une sphère – donc “des centaines d’éléments” dans la plupart des démonstrations que vous avez vues.

Donc, si vous voulez rendre une sphère réaliste avec un nombre raisonnablement réduit d’éléments, vous devrez probablement combiner les effets qui font une “illusion” d’une forme sphérique de base statique (un cercle avec des dégradés radiaux, des ombres intérieures, etc.) avec des éléments relativement petits (pour rendre moins évident qu’ils sont plats), orientés le long de la surface de la sphère avec des transformations 3D et animés – de la même manière que les faces du cube de votre première démo.

Voici ma propre tentative pour mettre cette approche en pratique. J’ai utilisé 20 éléments circulaires orientés à peu près comme les faces de l’ icosaèdre régulier (comme des hexagones blancs sur le ballon de football classique). Je les ai regroupés en deux groupes constituant chacun un hémisphère pour plus de commodité (ce n’était pas nécessaire, mais cela simplifiait le style). Toute la scène 3D comprend la sphère elle-même et le cadre d’arrière-plan (pseudo-élément) qui traverse la sphère près de son centre (un peu plus près pour réduire le “scintillement” des cercles à mesure ) et fait toujours face à l’écran. Donc 24 éléments au total (pas littéralement “des centaines”, au moins :). Pour rendre les cercles plus “bombés” (comme des segments sphériques), j’ai ajouté deux pseudo-éléments à chacun d’eux et les ai légèrement surélevés l’un par rapport à l’autre. Fonctionne mieux dans Chrome et Firefox 57+ (dans Firefox 56 et iOS Safari, il y a encore du scintillement près des bords). Si vous survolez le cercle, vous pouvez voir la scène sans le cadre d’arrière-plan (et aussi sans “scintiller”). Une version légèrement modifiée est également disponible sur Codepen .

 .scene { perspective: 400vmin; transform-style: preserve-3d; position: absolute; width: 80vmin; height: 80vmin; top: 10vmin; left: 10vmin; } .sphere { transform-style: preserve-3d; position: absolute; animation: rotate 20s infinite linear; width: 100%; height: 100%; transform-origin: 50% 50%; top: 0; left: 0; } .scene::before { content: ''; position: absolute; width: 100%; height: 100%; top: 0%; left: 0%; background: radial-gradient(circle farthest-corner at 33% 33%, rgba(240, 240, 220, 0.85) 0%, rgba(30, 30, 40, 0.85) 80%), radial-gradient(circle farthest-corner at 45% 45%, rgba(0, 0, 0, 0) 50%, #000000 80%); border-radius: 50%; transform: translateZ(2vmin); } .scene:hover::before { display: none; } .hemisphere { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform-style: preserve-3d; transform-origin: 50% 50%; transform: rotateX(90deg); } .hemisphere:nth-child(2) { transform: rotateX(-90deg); } .face { position: absolute; width: 40vmin; height: 40vmin; background: radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1) 48%, #ff0000 49%, #ff0000 50%, rgba(0, 0, 0, 0) 51%); transform-style: preserve-3d; transform-origin: 50% 0; top: 50%; left: 20vmin; } .face::before, .face::after { content: ''; position: absolute; border-radius: 50%; box-sizing: border-box; } .face::before { width: 50%; height: 50%; top: 25%; left: 25%; border: 2px solid #333; background: rgba(255, 255, 255, 0.3); transform: translateZ(1.6vmin); } .face::after { width: 20%; height: 20%; top: 40%; left: 40%; background: rgba(0, 0, 0, 0.2); transform: translateZ(2.8vmin); } .face:nth-child(1) { transform: translateZ(-41.6vmin) rotateZ(36deg) translateY(-6.8vmin) rotateX(143deg); } .face:nth-child(2) { transform: translateZ(-41.6vmin) rotateZ(108deg) translateY(-6.8vmin) rotateX(143deg); } .face:nth-child(3) { transform: translateZ(-41.6vmin) rotateZ(180deg) translateY(-6.8vmin) rotateX(143deg); } .face:nth-child(4) { transform: translateZ(-41.6vmin) rotateZ(252deg) translateY(-6.8vmin) rotateX(143deg); } .face:nth-child(5) { transform: translateZ(-41.6vmin) rotateZ(-36deg) translateY(-6.8vmin) rotateX(143deg); } .face:nth-child(6) { transform: translateZ(-26.8vmin) rotateZ(36deg) translateY(-33.2vmin) rotateX(100deg); } .face:nth-child(7) { transform: translateZ(-26.8vmin) rotateZ(108deg) translateY(-33.2vmin) rotateX(100deg); } .face:nth-child(8) { transform: translateZ(-26.8vmin) rotateZ(180deg) translateY(-33.2vmin) rotateX(100deg); } .face:nth-child(9) { transform: translateZ(-26.8vmin) rotateZ(252deg) translateY(-33.2vmin) rotateX(100deg); } .face:nth-child(10) { transform: translateZ(-26.8vmin) rotateZ(-36deg) translateY(-33.2vmin) rotateX(100deg); } .face:nth-child(11) { transform: translateZ(-26.8vmin) rotateZ(36deg) translateY(-33.2vmin) rotateX(100deg); } @keyframes rotate { 0% { transform: rotateZ(25deg) rotateX(20deg) rotateY(0deg); } 50% { transform: rotateZ(-25deg) rotateX(-20deg) rotateY(180deg); } 100% { transform: rotateZ(25deg) rotateX(20deg) rotateY(360deg); } } body { background: #555; overflow: hidden; } 
 

Comment créer une sphère sortingdimensionnelle réelle avec du CSS pur?

Eh bien, comme beaucoup l’ont indiqué dans les réponses et les commentaires, il est tout simplement impossible de créer une seule entité 3D dans un navigateur avec HTML et CSS uniquement à ce stade, mais il est possible de créer une illusion d’object 3D. Voici mon approche pour résoudre le problème.

Pour donner à un œil humain la capacité de voir un object sphérique, il faut que les points de référence suivent. Dans mon cas, ce sont les lignes qui définissent la forme de la sphère. Les lignes sont obtenues en donnant une bordure à 5 éléments de l’axe des axes X et 5 éléments à l’axe des Y. Seules les séries X / Y se voient atsortingbuer une bordure, car cela suffit à fournir une référence suffisante pour créer l’illusion d’une sphère. Les lignes supplémentaires sur l’axe Z sont simplement encombrantes et inutiles. Si toutes les lignes sont désactivées, le tout apparaît comme une sphère “parfaite” (ressemble à un cercle, mais toutes les parties sont en mouvement et sont présentes sur le plan 3D dans le navigateur!).


Ce que j’ai fait:

  1. Création de 15 éléments HTML qui représenteront chacun un cercle divisé en 3 séries de 5

    La raison de tous ces ensembles est que lorsque l’ensemble de l’outil est tourné sur les axes x, y et z, les arrière-plans de chacun des éléments des ensembles x, y et z remplissent les espaces vides les uns pour les autres.

  2. Chaque ensemble de 5 éléments est pivoté sur les axes X, Y et Z respectivement par incréments de 36 degrés. entrer la description de l'image ici
  3. Tous les éléments sont arrondis en utilisant border-radius:50%; 3 jeux de 5 éléments arrondis pour l'axe X Y Z
  4. Définir l’arrière-plan des éléments du cercle sur une couleur unie Ensembles remplis si 5 éléments arrondis
  5. Rassemble les ensembles pour qu’ils se chevauchent
    entrer la description de l'image ici
  6. Couper les lacunes mineures résultant de l’insuffisance d’éléments couvrant les espaces vides entre les cercles x, y et z en utilisant un clip-path: circle(96px at center); sur le récipient, et jeté un effet d’ombre / lumière frais pour sceller le marché
    entrer la description de l'image ici contre entrer la description de l'image ici

    Plus de cercles se traduiront par une sphère moins “nerveuse”, mais comme la performance est accentuée dans la question, un clip rapide de la chose entière semblait être la chose à faire


En guise de conclusion, je voulais exprimer mon appréciation de la question posée, cela m’a vraiment fait réfléchir et ce fut un excellent projet qui m’a permis d’apprendre beaucoup de choses sur les capacités 3D de HTML / CSS.

Merci également à toutes les personnes qui ont passé du temps à ouvrir cette porte et ont trouvé des solutions géniales au problème.

J’espère que les fruits de mes recherches sont utiles. À votre santé!

Ce stylo est également basé sur l’exemple de Timo Korinth.

 * { margin: 0; padding: 0; } /* Rotate Sphere animation */ @-webkit-keyframes animateSphere { 0% { transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); } 50% { transform: rotateY(360deg) rotateX(360deg) rotateZ(0deg); } 100% { transform: rotateY(720deg) rotateX(720deg) rotateZ(0deg); } } html { background: black; } .scene { perspective: 1000px; } .container { margin-top: 5vh; margin-left: auto; margin-right: auto; position: relative; width: 200px; height: 200px; transform-style: preserve-3d; animation-name: animateSphere; animation-duration: 30s; animation-iteration-count: infinite; animation-timing-function: linear; } .border { border: 1px solid white; } .circle { position: absolute; width: 100%; height: 100%; border-radius: 50%; background: rgba(204, 0, 102, 1); } .circle:nth-child(1) { transform: rotate3d(1, 0, 0, 0deg); } .circle:nth-child(2) { transform: rotate3d(1, 0, 0, 36deg); } .circle:nth-child(3) { transform: rotate3d(1, 0, 0, 72deg); } .circle:nth-child(4) { transform: rotate3d(1, 0, 0, 108deg); } .circle:nth-child(5) { transform: rotate3d(1, 0, 0, 144deg); } /* 18! difference to align*/ .circle:nth-child(6) { transform: rotate3d(0, 1, 0, 0deg); } .circle:nth-child(7) { transform: rotate3d(0, 1, 0, 36deg); } /* Upper and Lower circle */ .circle:nth-child(8) { transform: rotate3d(0, 1, 0, 72deg); } .circle:nth-child(9) { transform: rotate3d(0, 1, 0, 108deg); } .circle:nth-child(10) { transform: rotate3d(0, 1, 0, 144deg); } .circle:nth-child(11) { transform: rotate3d(0, 1, 0, 90deg) rotate3d(1, 0, 0, 0deg); } .circle:nth-child(12) { transform: rotate3d(0, 1, 0, 90deg) rotate3d(1, 0, 0, 36deg); } /* Upper and Lower circle */ .circle:nth-child(13) { transform: rotate3d(0, 1, 0, 90deg) rotate3d(1, 0, 0, 72deg); } .circle:nth-child(14) { transform: rotate3d(0, 1, 0, 90deg) rotate3d(1, 0, 0, 108deg); } .circle:nth-child(15) { transform: rotate3d(0, 1, 0, 90deg) rotate3d(1, 0, 0, 144deg); } .shadow { margin: auto; border-radius: 50%; width: 200px; height: 200px; box-shadow: 10px 1px 30px white; } /* Clip the sphere a bit*/ .clip { clip-path: circle(96px at center); } 
 

Comme déjà mentionné ci-dessus, CSS3 ne peut pas vous fournir de vraies formes 3D, mais simplement avec l’illusion. Une bonne illusion de sphère qui utilise des éléments HTML minimum et utilise l’image comme texture peut être réalisée en combinant ce que vous avez fait et en masquant tout avec les ombres CSS.

Une touche intéressante qui rend le masque plus réaliste est l’utilisation du pseudo-élément :after pour créer une étincelle supplémentaire dans un emplacement décalé et une taille plus petite. Un élément clé pour un effet réussi est de se rappeler que différents matériaux reflètent différemment la lumière. Cela signifie que si vous essayez de créer une sphère métallique, l’éclairage créé par l’ box-shadow la box-shadow sera différent de celui de la sphère plastique.

Un autre ajout intéressant est l’utilisation du pseudo-élément :before pour la création d’un effet de reflection. Ajouter une image prédéfinie du monde sur une sphère avec une certaine opacité peut créer un effet très persuasif. remarquez également que le matériau que vous essayez de créer déterminera la quantité d’opacité que vous souhaitez pour la reflection.

Remarquez que j’ai utilisé un prisme octogonal pour avoir l’image derrière la scène afin de la regarder plus en détail lorsque la forme 3D applique sa perspective. Même avec seulement 8 éléments, le résultat est assez réaliste. Des résultats plus réalistes peuvent être obtenus avec plus de polygones et de formes et de mappages de texture plus complexes, mais même sans nécessité de trop d’éléments en raison de l’ajout de l’ombre et de l’étincelle au-dessus de tout.

Enfin, afin de masquer le rest du prisme octogonal et d’afficher uniquement les parties à l’intérieur des bornes de la sphère, j’utilise le clip-path: circle(99px at center); .

 body { width: 100%; height: 100%; background-color: #000; } .cube-wrapper { width: 0; height: 0; top: 100px; left: 100px; position: absolute; perspective-origin: 0 0; perspective: 80px; } .cube-2 { transform: translateZ(-100px) scaleX(1.8); transform-style: preserve-3d; } .cube { top: -100px; position: relative; transform-style: preserve-3d; animation-name: rotate; animation-duration: 10s; animation-timing-function: linear; animation-iteration-count: infinite; } @keyframes rotate { 0% { transform: rotate3d(0 0, 0, 360deg); } 100% { transform: rotate3d(0, 1, 0, 360deg); ; } } .face { position: absolute; background-size: 662.4px 200px; width: 84px; height: 200px; } #face1 { transform: translateX(-41.4px) translateZ(100px); background-position: 0 0; } #face2 { transform: translateX(29.2px) translateZ(70.8px) rotateY(45deg); background-position: -82.8px 0; } #face3 { transform: translateX(58.5px) rotateY(90deg); background-position: -165.6px 0; } #face4 { transform: translateX(29.2px) translateZ(-70.8px) rotateY(135deg); background-position: -248.4px 0; } #face5 { transform: translateX(-41.4px) translateZ(-100px) rotateY(180deg); background-position: -331.2px 0; } #face6 { transform: translateX(-111.4px) translateZ(-70.8px) rotateY(225deg); background-position: -414px 0; } #face7 { transform: translateX(-141.4px) rotateY(270deg); background-position: -496.8px 0; } #face8 { transform: translateX(-111.4px) translateZ(70px) rotateY(315deg); background-position: -579.6px 0; } .circle { position: absolute; width: 200px; height: 200px; border-radius: 50%; } .clip-circle { position: absolute; padding: 0; top: -16px; width: 200px; height: 200px; border-radius: 50%; clip-path: circle(99px at center); } .lighting:after { content: ''; position: absolute; top: 50px; left: 67px; } .reflection:before { content: ''; position: absolute; top: 0px; left: 0px; height: 200px; width: 200px; background-image:url(https://i.stack.imgur.com/ayCw7.png); background-size: 200px 200px; } .earth { position: absolute; left: 20px; } .earth .face{ background-image:url(https://i.stack.imgur.com/fdtNz.jpg); } .earth .clip-circle { transform: rotateX(7deg) rotateZ(15deg); } .earth .lighting { box-shadow: -20px -30px 55px 0 rgba(0, 0, 0, 0.9) inset, -75px -100px 150px 0 rgba(0, 0, 0, 0.4) inset, 75px 100px 200px 0 rgba(255, 255, 255, 0.2) inset, -1px -2px 10px 2px rgba(200, 190, 255, 0.2); } .earth .lighting:after { box-shadow: 0 0 150px 51px rgba(255, 255, 255, 0.2), 0 0 26px 10px rgba(255, 255, 255, 0.2); } .wood { position: absolute; left: 240px; } .wood .face{ background-image:url(https://i.stack.imgur.com/sa5P8.jpg); } .wood .cube-wrapper { transform: rotateZ(45deg); } .wood .lighting { box-shadow: -20px -30px 90px 0 rgba(0, 0, 0, 0.7) inset, -75px -100px 140px 0 rgba(0, 0, 0, 0.6) inset; } .wood .lighting:after { box-shadow: 0 0 42px 15px rgba(255, 255, 255, 0.5); } .wood .reflection:before { opacity: 0.04; } .metal { position: absolute; left: 460px; } .metal .face{ background-image:url(https://i.stack.imgur.com/PGmVN.jpg); } .metal .cube-wrapper { transform: rotateZ(-32deg); } .metal .lighting { box-shadow: -20px -30px 100px 0 rgba(0, 0, 0, 0.9) inset, -75px -100px 107px 0 rgba(0, 0, 0, 0.3) inset, 75px 100px 127px 0 rgba(255, 255, 255, 0.23) inset; } .metal .lighting:after { box-shadow: 0 0 42px 20px rgba(255, 255, 255, 0.7), 0 0 7px 6px rgba(255, 255, 255, 0.9); } .metal .reflection:before { opacity: 0.2; } 
  

Faire une sphère 3D réaliste, sans un certain niveau d’illusion 2D, nécessiterait de nombreux éléments pour avoir un périmètre lisse.

Cependant, j’ai réalisé une version de l’exemple de Timo Korinth avec:

  • Coupure des lignes de quadrillage “dos face”
  • Ombre sphérique approximative en déplaçant un dégradé radial

Peut être pivoté arbitrairement tant que l’animation d’ombrage est recalculée.

Cette page contient quelques-unes des bases de l’implémentation des ombres sphériques avec CSS qui pourraient être utilisées pour cela.

Edit: D’autres réponses sont plus jolies, donc converties en une écanvas de la mort

 .ball { position: absolute; top:0px; left:0px; width: 98vmin; height: 98vmin; margin: 1vmin; transform-style: preserve-3d; transform: rotateX(-5deg); } @keyframes rot{ 0% { transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); } 100% { transform: rotateY(360deg) rotateX(0deg) rotateZ(0deg); } } .layer { position: absolute; top: 0px; left: 0px; width: 98vmin; height: 98vmin; } .moving { transform-style: preserve-3d; transform-origin: 49vmin 49vmin; animation: rot 10s linear infinite; } .gridplane { width: 97vmin; height: 97vmin; border-radius: 50%; border: 0.5vmin dashed rgb(128, 128, 128); } .xline { transform: translateY(1%) rotateX(90deg); } .xline2 { transform: translateY(-1%) rotateX(90deg); } .yline { transform: rotateY(90deg); } .zline { transform: rotateZ(90deg); } .laser { background-color: rgba(0, 0, 0, 0.05); transform: translateX(-27.7128%) translateY(-27.7128%) rotateY(90deg) translateX(-27.7128%) rotateY(-135deg) rotateX(45deg) scale(0.3) translateY(-25%); } .laser2 { background-color: rgba(0, 0, 0, 0.05); transform: translateX(-27.0128%) translateY(-27.0128%) rotateY(90deg) translateX(-27.0128%) rotateY(-135deg) rotateX(45deg) scale(0.2) translateY(-35%); } .clip { border-radius: 50%; overflow:hidden; transform: translateZ(-0vmin); } @keyframes highlightanim { 0.00% {left: -150.00%; top: -178.00% } 12.50% {left: -117.67%; top: -179.64% } 25.00% {left: -97.69%; top: -195.87% } 28.75% {left: -95.00%; top: -207.09% } 32.50% {left: -97.69%; top: -220.70% } 40.00% {left: -117.67%; top: -240.01% } 47.50% {left: -150.00%; top: -247.50% } 55.00% {left: -182.33%; top: -240.01% } 62.50% {left: -202.31%; top: -220.70% } 68.75% {left: -205.00%; top: -207.09% } 75.00% {left: -202.31%; top: -195.87% } 87.50% {left: -182.33%; top: -179.64% } 100.00% {left: -150.00%; top: -178.00% } } .shade { position: relative; top: -150%; left: -150%; width: 400%; height: 400%; background: radial-gradient(at 50% 50%, white, black, grey, black, black); animation: highlightanim 10s linear infinite; } 
 

Non, ce n’est pas possible selon vos critères. Tous les exemples de trucs 3D utilisant uniquement HTML et CSS ont des problèmes de performances, car ce n’est pas son objective.

En ce qui concerne les effets graphiques lourds, HTML et CSS sont vraiment mauvais.

La meilleure façon de créer une vraie sphère 3D consiste à utiliser WebGL, une API JavaScript permettant de créer du contenu 3D.

Jetez un oeil à cela – sonner comme ce dont vous avez besoin et avec des extraits de code que vous pouvez, espérons-le, modifier à votre guise. https://codepen.io/Mamboleoo/post/sphere-css

HTML

 .mommy .daddy - for (var x = 1; x < 300; x++) span 

CSS

 @import "compass"; body{ margin: 0; display: flex; height: 100vh; overflow: hidden; justify-content: center; align-items: center; background:black; } .mommy{ width: 500px; height: 500px; position: relative; perspective: 800px; } .daddy{ width: 500px; height: 500px; transform-style: preserve-3d; animation : rotate 25s infinite linear; } span{ display: inline-block; position: absolute; top:50%; left:50%; perspective: 800px; transform-style: preserve-3d; width: 0; height: 0; &:before{ content:""; width: 4px; height: 4px; display: inline-block; position: absolute; top: calc(50% - 2px); left: calc(50% - 2px); background: currentColor; color: inherit; border-radius: 50%; animation: invertRotate 25s infinite linear, scale 2s infinite linear; box-shadow: 0 0 10px currentColor; } } $amount : 300; @for $i from 1 through $amount { $theta : ($i / $amount)*120; $phi : ($i / $amount) * pi(); $x : 250 * sin($phi) * cos($theta); $y : 250 * sin($phi) * sin($theta); $z : 250 * cos($phi); .mommy span:nth-child(#{$i}){ transform: translate3d($x+px, $y+px, $z+px); color: hsl(($i/$amount)*360,100%,50%); &:before{ animation-delay: 0s, -($i/$amount)*2+s; } } } @keyframes rotate{ to{transform:rotateY(360deg);} } @keyframes invertRotate{ to{transform:rotateY(-360deg);} } @keyframes scale{ 0%, 45%,55%{ box-shadow: 0 0 10px 0px currentColor;} 50%{ box-shadow: 0 0 10px 5px currentColor;} } 

Voici un exemple de sphère / bulle animée, bien que cet exemple soit plus une illusion. Je ne sais pas si tout ce que vous demandez est possible uniquement par le biais de CSS, mais je me trompe peut-être.

 .ball { display: inline-block; width: 100%; height: 100%; border-radius: 100%; position: relative; background: radial-gradient(circle at bottom, #81e8f6, #76deef 10%, #055194 80%, #062745 100%); } .ball:before { content: ""; position: absolute; top: 1%; left: 5%; width: 90%; height: 90%; border-radius: 100%; background: radial-gradient(circle at top, white, rgba(255, 255, 255, 0) 58%); -webkit-filter: blur(5px); filter: blur(5px); z-index: 2; } .ball:after { content: ""; position: absolute; display: none; top: 5%; left: 10%; width: 80%; height: 80%; border-radius: 100%; -webkit-filter: blur(1px); filter: blur(1px); z-index: 2; -webkit-transform: rotateZ(-30deg); transform: rotateZ(-30deg); } .ball .shadow { position: absolute; width: 100%; height: 100%; background: radial-gradient(circle, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%); -webkit-transform: rotateX(90deg) translateZ(-160px); transform: rotateX(90deg) translateZ(-160px); z-index: 1; } .ball.plain { background: black; } .ball.plain:before, .ball.plain:after { display: none; } .ball.bubble { background: radial-gradient(circle at 50% 55%, rgba(240, 245, 255, 0.9), rgba(240, 245, 255, 0.9) 40%, rgba(225, 238, 255, 0.8) 60%, rgba(43, 130, 255, 0.4)); -webkit-animation: bubble-anim 2s ease-out infinite; animation: bubble-anim 2s ease-out infinite; } .ball.bubble:before { -webkit-filter: blur(0); filter: blur(0); height: 80%; width: 40%; background: radial-gradient(circle at 130% 130%, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0) 46%, rgba(255, 255, 255, 0.8) 50%, rgba(255, 255, 255, 0.8) 58%, rgba(255, 255, 255, 0) 60%, rgba(255, 255, 255, 0) 100%); -webkit-transform: translateX(131%) translateY(58%) rotateZ(168deg) rotateX(10deg); transform: translateX(131%) translateY(58%) rotateZ(168deg) rotateX(10deg); } .ball.bubble:after { display: block; background: radial-gradient(circle at 50% 80%, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0) 74%, white 80%, white 84%, rgba(255, 255, 255, 0) 100%); } .stage { width: 300px; height: 300px; display: inline-block; margin: 20px; -webkit-perspective: 1200px; -moz-perspective: 1200px; -ms-perspective: 1200px; -o-perspective: 1200px; perspective: 1200px; -webkit-perspective-origin: 50% 50%; -moz-perspective-origin: 50% 50%; -ms-perspective-origin: 50% 50%; -o-perspective-origin: 50% 50%; perspective-origin: 50% 50%; } body { width: 300px; margin: 20px auto; background: linear-gradient(to bottom, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%); background-repeat: no-repeat; } @-webkit-keyframes bubble-anim { 0% { -webkit-transform: scale(1); transform: scale(1); } 20% { -webkit-transform: scaleY(0.95) scaleX(1.05); transform: scaleY(0.95) scaleX(1.05); } 48% { -webkit-transform: scaleY(1.1) scaleX(0.9); transform: scaleY(1.1) scaleX(0.9); } 68% { -webkit-transform: scaleY(0.98) scaleX(1.02); transform: scaleY(0.98) scaleX(1.02); } 80% { -webkit-transform: scaleY(1.02) scaleX(0.98); transform: scaleY(1.02) scaleX(0.98); } 97%, 100% { -webkit-transform: scale(1); transform: scale(1); } } @keyframes bubble-anim { 0% { -webkit-transform: scale(1); transform: scale(1); } 20% { -webkit-transform: scaleY(0.95) scaleX(1.05); transform: scaleY(0.95) scaleX(1.05); } 48% { -webkit-transform: scaleY(1.1) scaleX(0.9); transform: scaleY(1.1) scaleX(0.9); } 68% { -webkit-transform: scaleY(0.98) scaleX(1.02); transform: scaleY(0.98) scaleX(1.02); } 80% { -webkit-transform: scaleY(1.02) scaleX(0.98); transform: scaleY(1.02) scaleX(0.98); } 97%, 100% { -webkit-transform: scale(1); transform: scale(1); } }