CSS只有3D旋转文字

时间:2015-06-16 16:06:43

标签: css css-animations

我有一个带有文字旋转的div。如何获得文本深度以提供更好的3D效果?为了澄清,在90deg,文字变得1px厚,因为我们只能从侧面看到它 - 我该如何制作它,例如,10px厚?此外,应显示适当的深度 - 即在0deg我们看不到深度;在45deg我们看到5px的深度;在90deg,我们看到了10px个完整的深度;等

我正在使用仅限CSS的解决方案。



#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>
&#13;
&#13;
&#13;

4 个答案:

答案 0 :(得分:26)

简单text-shadow可以解决问题:

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>

另一项改进可能是使用::before::after伪类克隆文本:

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>

答案 1 :(得分:5)

纯CSS解决方案看起来不太好。要获得真正的3D效果,请使用JS。我建议使用using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { DataTable dt = new DataTable(); dt.Columns.Add("Col1", typeof(string)); dt.Columns.Add("Col2", typeof(string)); dt.Columns.Add("Col3", typeof(string)); dt.Rows.Add(new object[] {"AAA","BBB","DEF"}); dt.Rows.Add(new object[] {"AAA","BBB","QEW"}); dt.Rows.Add(new object[] {"RRR","WWW","123"}); dt.Rows.Add(new object[] {"RRR","WWW","321"}); dt.Rows.Add(new object[] {"XXX","WWW","421"}); var results = dt.AsEnumerable() .GroupBy(x => new {col1 = x.Field<string>("Col1"), col2 = x.Field<string>("Col2") }) .Select(x => new { col1 = x.FirstOrDefault().Field<string>("Col1"), col2 = x.FirstOrDefault().Field<string>("Col2"), col3 = string.Join("",x.Select(y => y.Field<string>("Col3")).ToArray()) }) .ToList(); } } } ​ ,因为它包含一个相当简单易用的three.js功能。

我编写了一个脚本,用类textGeometry替换元素的内容,其中包含一个webGL场景,其中元素内的文本正在旋转。

你当然可以用three.js做各种很酷的效果来制作你的文字look nicer。有关文本格式,请参阅textGeometry doc。请查看three.js docs以获取更多详细信息。

我在代码的注释中添加了一些注释。

&#13;
&#13;
rotatingText
&#13;
.rotatingText {
  width: 100%;
  height: 200px;
}
&#13;
&#13;
&#13;

答案 2 :(得分:2)

我使用:before:after元素添加了额外的文本图层,并且我将Y轴分别偏移-3deg和3deg。结果是文本现在具有“某种”深度。如果我使用较短的字符串(例如“RPK”),我可以将偏移量增加到大约7度,并且看起来还不错。但是,这只会给外边缘增加一个“深度”。

#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>

在此版本中,我更改了rotate的{​​{1}}属性。同样,使用较短的字符串,这种效果会更好。

translateZ
#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);
  }
}

我不会接受这个作为答案,因为它没有给我我所追求的确切效果。我相信那里有人会找到完美的方法:o)

答案 3 :(得分:2)

添加原始元素的多个克隆,每个克隆后面翻译1px,然后处理它们的颜色以给出3d外观并不是那么糟糕,

check the Pen (仅在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>