CSS 3D filature du texte
j'ai une div avec du texte qui tourne. Comment obtenir la profondeur du texte pour donner un meilleur effet 3d? Pour clarifier, à 90deg
le texte devient 1px
épais parce que nous ne pouvons le voir que de côté - Comment puis-je le faire, par exemple, 10px
épais? De plus, la profondeur appropriée doit être indiquée, c.-à-d. à 0deg
nous ne voyons pas la profondeur; à 45deg
nous voir 5px
de profondeur; à 90deg
nous voyons la pleine 10px
profondeur; etc.
je suis après un CSS seulement solution.
#spinner {
animation-name: spinner;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 3s;
transform-style: preserve-3d;
text-align:center;
}
@keyframes spinner {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(-360deg);
}
}
<p id="spinner">Stop, I'm getting dizzy!</p>
4 réponses
Simple text-shadow
peut faire l'affaire:
body {
perspective: 500px;
}
#spinner {
text-align: center;
animation-name: spin, depth;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 3s;
}
@keyframes spin {
from { transform: rotateY(0deg); }
to { transform: rotateY(-360deg); }
}
@keyframes depth {
0% { text-shadow: 0 0 black; }
25% { text-shadow: 1px 0 black, 2px 0 black, 3px 0 black, 4px 0 black, 5px 0 black; }
50% { text-shadow: 0 0 black; }
75% { text-shadow: -1px 0 black, -2px 0 black, -3px 0 black, -4px 0 black, -5px 0 black; }
100% { text-shadow: 0 0 black; }
}
<p id="spinner">Stop, I'm getting dizzy!</p>
une autre amélioration pourrait être de cloner le texte en utilisant ::before
et ::after
les pseudo-classes:
body {
perspective: 1000px;
}
#spinner {
font-size: 50px;
text-align: center;
animation-name: spin, depth;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 3s;
transform-style: preserve-3d;
position: relative;
}
#spinner::before,
#spinner::after {
content: "Stop, I'm getting dizzy!";
display: block;
position: absolute;
width: 100%;
height: 100%;
top: 0;
transform: rotateY(0.5deg);
transform-origin: 0 50%;
}
#spinner::after {
transform: rotateY(-0.5deg);
transform-origin: 100% 50%;
}
@keyframes spin {
from { transform: rotateY(0deg); }
to { transform: rotateY(-360deg); }
}
@keyframes depth {
0% { text-shadow: 0 0 black; }
25% { text-shadow: 1px 0 black, 2px 0 black, 3px 0 black, 4px 0 black, 5px 0 black, 6px 0 black; }
50% { text-shadow: 0 0 black; }
75% { text-shadow: -1px 0 black, -2px 0 black, -3px 0 black, -4px 0 black, -5px 0 black, -6px 0 black; }
100% { text-shadow: 0 0 black; }
}
<p id="spinner">Stop, I'm getting dizzy!</p>
une solution CSS pure ne semblera pas bonne. Pour un effet vraiment 3D, utilisez JS. Je recommande d'utiliser three.js
, parce qu'il a untextGeometry
fonction incluse.
j'ai écrit un script qui remplace le contenu des éléments avec la classe rotatingText
avec une scène webGL où le texte à l'intérieur de l'élément tourne.
vous pouvez bien sûr faire toutes sortes d'effets cool avec trois.js aussi pour faire votre texte look plus sympa. Voir textGeometry doc pour le formatage du texte. Regardez dans le trois.js docs!--11--> pour plus de détails.
j'ai mis quelques notes dans les commentaires du code.
.rotatingText {
width: 100%;
height: 200px;
}
<!--your rotating text, just give it class rotatingText-->
<div class="rotatingText">Stop, I'm getting dizzy!</div>
<!--three.js library-->
<script src="https://ajax.googleapis.com/ajax/libs/threejs/r69/three.min.js"></script>
<!--the default font for three.js-->
<script src="http://threejs.org/examples/fonts/helvetiker_regular.typeface.js"></script>
<!--the script that converts each .rotatingText element into 3D -->
<script>
function rotateText(container,i){
var t = THREE;
var containerW = container.offsetWidth;
var containerH = container.offsetHeight;
var theText = container.innerHTML; //grab the text from the element...
container.innerHTML = ""; // ...and clear it
var renderer = new t.WebGLRenderer({
alpha: true,
antialiasing: true
});
renderer.setSize(containerW, containerH);
renderer.setClearColor(0x000000, 0);
container.appendChild(renderer.domElement);
var scene = new t.Scene();
var camera = new t.PerspectiveCamera(
75, //vertical field of view
containerW / containerH, //aspect ratio
0.1, //near plane
1000 //far plane
);
scene.add(camera);
camera.position.set(0, 0, 100);
// This is your 3D text:
var geometry = new t.TextGeometry(theText, { //insert the text we grabbed earlier here
size: 10, //your font size
height: 1 //your font depth
});
var material = new t.MeshLambertMaterial({
color: 0x000000 //your font color
});
var text = new t.Mesh(geometry, material); //this is your 3D text object
//I created a pivot object to act as the center point for rotation:
geometry.computeBoundingBox();
var textWidth = geometry.boundingBox.max.x - geometry.boundingBox.min.x;
text.position.set(-0.5 * textWidth, 0, 0);
scene.add(text);
var pivot = new t.Object3D();
pivot.add(text);
scene.add(pivot);
//Then just render your scene and request for new frames
this.render = function() {
pivot.rotation.y += .02; //how much you want your text to rotate per frame
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
}
var rotatingTextElements = document.getElementsByClassName("rotatingText");
for (var i = 0; i < rotatingTextElements.length; i++) {
rotateText(rotatingTextElements[i]);
}
</script>
j'ai ajouté des couches supplémentaires du texte en utilisant :before
et :after
éléments, et j'ai décalé leur axe Y de-3deg et 3deg respectivement. Le résultat est que le texte a maintenant une "sorte de" profondeur. Si j'utilise une chaîne plus courte (par exemple "RPK"), je peux augmenter l'offset à environ 7deg et avoir encore un look OK. Cependant, cela ne donne aux bords extérieurs qu'une "profondeur"supplémentaire.
#spinner {
animation-name: spinner;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 3s;
transform-style: preserve-3d;
text-align:center;
font-size:2em;
}
#spinner:after,
#spinner:before {
content:"Stop, I'm getting dizzy!";
position:absolute;
top:0;
left:0;
width:100%;
text-align:center;
transform: rotateY(2deg);
}
#spinner:before {
transform: rotateY(-2deg);
}
#spinner,
#spinner:after,
#spinner:before {
font-weight:narrow;
}
@keyframes spinner {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(-360deg);
}
}
<p id="spinner">Stop, I'm getting dizzy!</p>
Dans cette version, j'ai changé le rotate
propriété translateZ
. Encore, cet effet semble meilleur avec une corde plus courte.
#spinner {
animation-name: spinner;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 3s;
transform-style: preserve-3d;
text-align: center;
font-size: 2em;
}
#spinner:after,
#spinner:before {
content: "Stop, I'm getting dizzy!";
position: absolute;
top: 0;
left: 0;
width: 100%;
text-align: center;
transform: translateZ(3px);
}
#spinner:before {
transform:translateZ(-3px);
}
@keyframes spinner {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(-360deg);
}
}
<p id="spinner">Stop, I'm getting dizzy!</p>
je ne vais pas accepter cette réponse, car elle ne me donne pas exactement l'effet que je suis après. Je suis sûr que quelqu'un va trouver la méthode idéale :o)
ajouter plusieurs clones de l'élément original, chacun traduit 1px derrière, et puis travailler sur leur couleur pour donner un look 3d n'est pas si mal,
vérifiez le stylo ( testé uniquement sur Chrome)
HTML
<section>
<p >Stop, I'm getting dizzy!</p>
</section>
SCSS
section{
animation-name: spinner;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 4s;
transform-style: preserve-3d;
}
p {
text-align: center;
font-size: 2em;
position:absolute;
width:100%;
letter-spacing: 0.2em;
}
@keyframes spinner {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(-360deg);
}
}
$colors: #000,#111,#222,#333,#444,#555,#666,#777,#888,#999,#aaa,#bbb;
@for $i from 1 through length($colors) {
p:nth-child( #{$i} ){
transform: translateZ(- $i+px);
color: (nth($colors, $i));
}
}
JS
var p = document.querySelector('p');
for(var i = 0 ; i<13 ; i++){
var node = document.createElement('p');
var child = "Stop, I'm getting dizzy!";
child = document.createTextNode(child);
node.appendChild(child);
p.parentNode.appendChild(node);
}
section {
animation-name: spinner;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 4s;
transform-style: preserve-3d;
}
p {
text-align: center;
font-size: 2em;
position: absolute;
width: 100%;
letter-spacing: 0.2em;
}
p:last-child {
-webkit-text-fill-color: silver;
}
@keyframes spinner {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(-360deg);
}
}
p:nth-child(1) {
transform: translateZ(-1px);
color: #000;
}
p:nth-child(2) {
transform: translateZ(-2px);
color: #111;
}
p:nth-child(3) {
transform: translateZ(-3px);
color: #222;
}
p:nth-child(4) {
transform: translateZ(-4px);
color: #333;
}
p:nth-child(5) {
transform: translateZ(-5px);
color: #444;
}
p:nth-child(6) {
transform: translateZ(-6px);
color: #555;
}
p:nth-child(7) {
transform: translateZ(-7px);
color: #666;
}
p:nth-child(8) {
transform: translateZ(-8px);
color: #777;
}
p:nth-child(9) {
transform: translateZ(-9px);
color: #888;
}
p:nth-child(10) {
transform: translateZ(-10px);
color: #999;
}
p:nth-child(11) {
transform: translateZ(-11px);
color: #aaa;
}
p:nth-child(12) {
transform: translateZ(-12px);
color: #bbb;
}
<section>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
<p>Stop, I'm getting dizzy!</p>
</section>