【问题标题】:Css jittery text translateCss 抖动文本翻译
【发布时间】:2021-01-25 23:19:27
【问题描述】:

[解决方案]
解决方案是使用will-change CSS 属性来强制 GPU 渲染:

will-change: transform;

[原始问题]
我一直在互联网上进行大量挖掘,但没有找到解决一个看似相当简单的问题的解决方案,即翻译包含文本的持有人,并使该文本顺利移动。

这是一个问题的例子,你可以看到文字是一步一步地跟随它的持有者,而不是顺利:

我还做了一个小codepen来现场看效果:

https://codepen.io/Durss/pen/ExgBzVJ?editors=1111

var angle = 0;
var radius = 100;
function renderFrame() {
        requestAnimationFrame(renderFrame);
    var cx = document.documentElement.clientWidth / 2;
    var cy = document.documentElement.clientHeight / 2;
    var div = document.getElementById("text");
    var px = cx + Math.cos(angle) * radius;
    var py = cy + Math.sin(angle) * radius;
    angle += .001;
    div.style.transform = "translate3d("+px+"px, "+py+"px, 0)";
}

renderFrame();
body {
  background-color:black;
  width:100%;
  height:100%;
}

#text {
  position:absolute;
  left:0;
  top:0;
  border: 2px solid white;
  background-color: #2f9da7;
  padding: 10px;
  border-radius:20px;
  color: white;
  font-weight: bold;
}
<div id="text">blah blah</div>

基本上,问题在于支架在亚像素级别移动,但无论我尝试什么,文本位置似乎都是圆形的。 我使用 translate3d() 所以它使用 GPU 渲染来修复持有人的位移而不是它的文本内容。

div.style.transform = "translate3d("+px+"px, "+py+"px, 0)";

我到处都看到了以下对我不起作用的 CSS“解决方案”:

text-rendering: geometricPrecision;
-webkit-font-smoothing: antialiased;
transform-style: preserve-3d;
backface-visibility: hidden;
-webkit-font-smoothing:none;

我过去多次遇到这个问题但总是放弃修复它,我认为是时候寻求帮助作为最后一颗子弹了!

感谢您阅读我!

【问题讨论】:

  • 问题是时间元素实际上是文本。浏览器正试图通过使其尽可能清晰地落入亚像素来为您优化它。好的!但你不希望那样。您是否尝试过在 SVG 元素中使用文本?也许浏览器不会优化 SVG。 (对不起,如果我自己没有尝试过)
  • 好主意,但它不会改变任何东西:/ codepen.io/Durss/pen/BaLXLEQ
  • 顺便说一句;一种解决方案是在画布中呈现文本并将该画布显示在支架中。作为位图的画布可能有利于亚像素渲染,但是......来吧......现在是 2021 年,我希望我能避免这样的混乱^^'

标签: javascript css transform jitter translate3d


【解决方案1】:

CSS 过渡有助于使亚像素动画更流畅。

transition: all 0.001s linear;

它在 chrome 上运行良好,但在 firefox 上似乎不太有效。 这篇文章可能会有所帮助: Firefox CSS Animation Smoothing (sub-pixel smoothing)

【讨论】:

    【解决方案2】:

    作为一种解决方法,您可以Math.round px 值。这将防止文本自行抖动(使包含 div 的整体抖动)。

    var angle = 0;
    var radius = 100;
    function renderFrame() {
            requestAnimationFrame(renderFrame);
        var cx = document.documentElement.clientWidth / 2;
        var cy = document.documentElement.clientHeight / 2;
        var div = document.getElementById("text");
        var px = Math.round(cx + Math.cos(angle) * radius);
        var py = Math.round(cy + Math.sin(angle) * radius);
        angle += .001;
        div.style.transform = "translate3d("+px+"px, "+py+"px, 0)";
    }
    
    renderFrame();
    body {
      background-color:black;
      width:100%;
      height:100%;
    }
    
    #text {
      position:absolute;
      left:0;
      top:0;
      border: 2px solid white;
      background-color: #2f9da7;
      padding: 10px;
      border-radius:20px;
      color: white;
      font-weight: bold;
    }
    <div id="text">blah blah</div>

    【讨论】:

    • 四舍五入确实会使持有人及其文本同步移动,但整个持有人会抖动,而不仅仅是对我来说更糟糕的文本:/
    【解决方案3】:
    will-change: contents;
    

    解决了我自己在进行变换旋转时的抖动文本问题。这告诉浏览器一个元素的内容会改变,因此不应该被缓存。

    这必须在转换之前立即应用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-28
      • 2011-04-07
      • 2013-08-07
      • 1970-01-01
      • 2012-12-10
      • 1970-01-01
      • 2018-03-28
      • 1970-01-01
      相关资源
      最近更新 更多