【问题标题】:CSS only 3D spinning textCSS only 3D 旋转文本
【发布时间】:2015-06-16 16:06:43
【问题描述】:

我有一个带有一些文本旋转的 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>

【问题讨论】:

  • 啊!它向哪个方向旋转?我的大脑无法下定决心。 XD
  • 嗨,这就是你的意思the-art-of-web.com/css/3d-transforms,而文字是 90 度,厚度应该是这样显示的吗?

标签: css css-animations


【解决方案1】:

简单的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>

【讨论】:

  • 从(RUN CODE SNIPPET)我们可以看到它下面的滚动条被激活了。旋转应该在固定的 div 中(最大宽度,最小宽度,宽度)以避免它。
【解决方案2】:

纯 CSS 解决方案看起来并不好。要获得真正的 3D 效果,请使用 JS。我推荐使用three.js,因为它包含一个相当易于使用的textGeometry 函数。

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

你当然可以用three.js做各种很酷的效果,也可以让你的文字look nicer。有关文本格式,请参阅 textGeometry doc。查看three.js docs了解更多详情。

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

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

【讨论】:

  • 我知道 three.js,但我只追求 CSS 解决方案。
【解决方案3】:

添加原始元素的多个克隆,每个都在后面平移 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>

【讨论】:

  • 虽然这个效果看起来比纯 css 解决方案更好,但我仅限于纯 css。
  • @RichardParnaby-King JS 和 SCSS 部分只是程序化的;最终输出只是 HTML 和 CSS
  • 你正在使用 JS 创建 13 个p 标签。我无法添加更多 HTML 元素,并且仅限于 CSS(无 JS)。
【解决方案4】:

我使用: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);
  }
}
&lt;p id="spinner"&gt;Stop, I'm getting dizzy!&lt;/p&gt;

在这个版本中,我将rotate 属性更改为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);
  }
}
&lt;p id="spinner"&gt;Stop, I'm getting dizzy!&lt;/p&gt;

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

【讨论】:

    【解决方案5】:

    我也想要 CSS 驱动的旋转文本,尽管我的方法不同。我会添加它以防它帮助其他人:

    @keyframes spin {
      from {
        transform: rotateY(0deg) rotateX(0deg);
      }
      to {
        transform: rotateY(360deg) rotateX(360deg);
      }
    }
    
    #shared-loader {
      box-sizing: border-box;
      font-family: sans-serif;
      width: 200px;
      height: 200px;
      margin: 0;
      perspective: 400px;
      transform: scale(0.2);
    }
        
    .cube {
      width: 200px;
      height: 200px;
      position: relative;
      transform-style: preserve-3d;
      transform: translateZ(-100px);
      transition: transform 2s;
      animation: spin 6s linear infinite;
    }
    
    .cube-face {
      position: absolute;
      width: 200px;
      height: 200px;
      border: 2px solid #fff;
      line-height: 200px;
      font-size: 80px;
      font-weight: bold;
      color: white;
      text-align: center;
      background: #de662c;
    }
    
    .cube-face-front  { transform: rotateY(  0deg) translateZ(100px); }
    .cube-face-right  { transform: rotateY( 90deg) translateZ(100px); }
    .cube-face-back   { transform: rotateY(180deg) translateZ(100px); }
    .cube-face-left   { transform: rotateY(-90deg) translateZ(100px); }
    .cube-face-top    { transform: rotateX( 90deg) translateZ(100px); }
    .cube-face-bottom { transform: rotateX(-90deg) translateZ(100px); }
    <div id="shared-loader">
      <div class="cube">
        <div class="cube-face cube-face-front">Y</div>
        <div class="cube-face cube-face-back">Y</div>
        <div class="cube-face cube-face-right">Y</div>
        <div class="cube-face cube-face-left">Y</div>
        <div class="cube-face cube-face-top">Y</div>
        <div class="cube-face cube-face-bottom">Y</div>
      </div>
    </div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-11
      • 2020-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-21
      相关资源
      最近更新 更多