【问题标题】:Webkit-based blurry/distorted text post-animation via translate3d通过 translate3d 实现基于 Webkit 的模糊/扭曲文本后期动画
【发布时间】:2011-09-18 16:12:29
【问题描述】:

此问题似乎会影响所有基于 WebKit 的浏览器,包括 iPhone。

首先是一些背景。我正在开发的网站使用基于 JavaScript 的“滑块”动画。

我正在使用-webkit-transform: translate3d 为实际动画“供电”。使用此方法时,与基于 JavaScript 的方法相反,一旦内容被动画化,文本就会变得非常模糊。这在 iPhone 上尤为明显。

我看到的一些变通方法是删除相对定位,我这样做了,并为-webkit-font-smoothing: antialiased 添加了一条规则,我也这样做了。两者都没有改变。

唯一我可以在没有模糊文本的情况下使其正常工作的方法是使用常规 JavaScript 制作动画并完全绕过 translate3d。我更喜欢使用translate3d,因为它在支持 WebKit 的设备上的执行速度要快得多,但对于我来说,我无法弄清楚为什么它会以如此糟糕的方式影响文本。

任何建议或解决方案将不胜感激。

【问题讨论】:

标签: javascript css text webkit blurry


【解决方案1】:

如果百分比用于动画,如果我们还考虑它的性能,它仍然可以接受,但是当您不使用translate 动画时,它会有所不同,因为文本总是会模糊。

当使用百分比时,可能会有像0.5px 这样的小数,并且文本模糊的原因。在我的实验中使用translate(0.5px, 0.5px) 会使文本非常模糊,因此您应该避免0.3px <=> 0.7px 之间的小数,而0.2px and 0.8px 仍然可以接受。

我的建议是使用 JavaScript 并将百分比转换为圆角像素来为元素设置动画,如果 translate 用于定位元素,则使用像素而不是百分比。

另一种选择是使用lefttop来设置百分比的初始位置,然后使用transform: translate()像素作为目标位置 并仅使用 transition-property: transform;transform 设置动画

【讨论】:

    【解决方案2】:

    将 Chrome 的缩放比例重置为 100% 对我有用。

    【讨论】:

    • 大声笑,这只会在您放大或缩小并导致元素偏离像素定位的情况下解决。我不认为这里是这种情况
    【解决方案3】:

    Neil Taylor 的解决方案是最好的,但仍有待改进:

    transform: translateX(-50%) translateX(.5px)

    这种方式有两个好处:

    • 它可以在 IE11 等蹩脚的浏览器中运行(不支持 translate 内的 calc)
    • 它只在解析时计算,而不是在浏览器每次评估时计算。

    【讨论】:

    • 你的解决方案是最好的:D
    【解决方案4】:

    将容器中应用了 transform translate 属性的任何元素的垂直边距(margin-top 或 margin-bottom)或高度仅减少 1 个像素。

    【讨论】:

      【解决方案5】:

      在我的案例中找到的解决方案是设置第一个子元素的 height

      【讨论】:

        【解决方案6】:

        我希望这是关于将对象居中到屏幕的确切中心。 变换发生模糊: translate(-50%,-50%);

        所以改为这样做

        position: absolute;
        margin:0;
        top: 50%;
        left: 50%;
        transform: translate(-50%,-50%);
        

        我尝试使用 javascript 将样式注入元素。 (React.js)

        const node = ReactDOM.findDOMNode(this);
        var width = node.offsetWidth;
        var height = node.offsetHeight;
        var windowWidth = window.innerWidth;
        var windowHeight = window.innerHeight;
        
        style={
            left : (windowWidth/2) - (this.state.width/2) + 'px',
            right:  (windowWidth/2) - (this.state.width/2) + 'px',
            top: (windowHeight/2) - (this.state.height/2) + 'px',
            bottom: (windowHeight/2) - (this.state.height/2) + 'px'
        }
        

        通过javascript样式将样式注入元素

        例如。

        export default class Dialog extends React.Component {
            constructor(props) {
                super(props);
                this.state = {
                    width: '0px',
                    height: '0px'
                };
            }
        
            setWidthhandHeight(node){
                if (this.state.width !== node.offsetWidth) {
                    this.setState({
                        width: node.offsetWidth,
                        height: node.offsetHeight
                    });
                }
            }
        
            componentDidMount() {
                this.setWidthhandHeight(node);
            }
        
            render() {
                const windowWidth = window.innerWidth;
                const windowHeight = window.innerHeight;
                return (
                    <dialog className={this.props.className + " dialog"}
                            style={{
                                left : (windowWidth/2) - (this.state.width/2) + 'px',
                                right:  (windowWidth/2) - (this.state.width/2) + 'px',
                                top: (windowHeight/2) - (this.state.height/2) + 'px',
                                bottom: (windowHeight/2) - (this.state.height/2) + 'px'
                            }}>
                        {this.props.title ? (
                            <header><span>{this.props.title}</span></header>
                            )
                            : null
                        }
                        {this.props.children}
                    </dialog>
                );
            }
        }
        

        【讨论】:

          【解决方案7】:

          使用zoom 为我解决了这个问题。

          我刚刚加了zoom: 1.04;

          【讨论】:

            【解决方案8】:

            我在这些类型的问题上使用will-change,它通常解决缩放问题或舍入错误,例如看到分隔元素的 1px 白线。

            will-change: transform;

            在这里阅读更多: https://developer.mozilla.org/en-US/docs/Web/CSS/will-change

            【讨论】:

              【解决方案9】:

              这是最好的解决方案 translateX(calc(-50% + 0.5px))

              【讨论】:

              • 元素重新定位是一种副作用,或者我错过了什么?
              【解决方案10】:

              可能是最简单的解决方案:

              transform: translate(-50%, -50%) scale(2); 
              zoom:.5;
              

              Scale-and-zoom 负责将像素值四舍五入为整数

              【讨论】:

                【解决方案11】:

                您要翻译的元素必须能被偶数的 2 整除。

                重要的是,无论您试图移动一半的元素的宽度和高度都可以被 2 整除,这一点很重要。与响应式图像非常相似,即可以将物体移动 50% 而不会分割像素。

                宽度为:503px,高度为 500px 的 div 会导致模糊,无论你以何种方式移动它或使用 translateX 或 Y 时移动多少。使用变换,它利用 GPU 图形加速器,结果应该是非常清晰、光滑的边缘。设置 box-sizing: border-box; 也可能是一个好主意。确保计算出的宽度包括内边距和边框。

                使用百分比宽度时要小心。如果它是相对于屏幕尺寸的,那么任何其他屏幕像素宽度都会导致这种模糊。

                【讨论】:

                • 我发现 3d 翻译后的图像即使尺寸可以被 2 整除,仍然很模糊。真的很模糊。
                • @QuentinEngles - 在某些情况下,我发现图像是否被翻译。两件事,1. 如果您要缩小图像,请确保宽度和高度都可等分。 IE:100 像素 x 112 像素 如果缩放到 99 像素的宽度,图像看起来会很模糊。因为高度不是整数。 2:使用窗口缩放的高分辨率显示器意味着您还必须考虑该转换。将图像缩放比例保持在 100% 或 50% 以确保安全。
                • 我注意到只要盒子高度是偶数(例如高度:400px),文本的模糊性就会消失。
                【解决方案12】:

                这些答案都不适合我,但使用

                display: inline-table;
                

                成功了

                【讨论】:

                  【解决方案13】:

                  这些似乎都不适合我,但我发现了一个稍微有点脏的解决方案,似乎可以解决问题:

                  top: 49.9%;
                  left: 49.9%;
                  -webkit-transform: translate(-50.1%, -50.1%);
                  transform: translate(-50.1%, -50.1%);
                  

                  【讨论】:

                  • 针对丑陋浏览器的丑陋解决方案,上述方法均无效,但这个可行。对我来说 Chrome/Webkit 是新的 IE,我需要一个又一个愚蠢的解决方法。
                  • 对 Y 轴使用这个技巧只对我有用,而没有其他解决方案有效:translate(-50%, -50%) -> translate(-50%, -50.1%)。有趣的是,稍微增加或减少50.1 也不起作用...
                  • 这对我有用,但每个人都需要尝试一下,就我而言,我必须使用 50.2
                  • 看,这总是取决于你屏幕的总宽度!没有简单的解决方法。如果你调整屏幕大小,你会看到效果发生了变化......
                  • 这不是一个通用的解决方案。当 50% 无效时有效,但在某些情况下,当 50% 看起来还不错时,效果会很差。
                  【解决方案14】:

                  我遇到了与 Ken Avila 的帖子中描述的完全相同的问题:CSS: transform: translate(-50%, -50%) makes texts blurry

                  问题当然是我使用了 transform: translate(-50%, -50%) 这使我居中的内容变得模糊,但仅在 osx 上的 safari 中。

                  变得模糊的不仅仅是文本,而是整个内容,包括图像。 我继续阅读:http://keithclark.co.uk/articles/gpu-text-rendering-in-webkit/ “模糊”是由于元素呈现在非整数边界上。

                  我还发现我可以避免在这篇文章的居中水平部分使用转换转换:https://coderwall.com/p/quutdq/how-to-really-center-an-html-element-via-css-position-absolute-fixed -唯一的缺点是我必须引入一个包装器。

                  我发现使用 transform: translateY(-50%) 并没有产生任何“模糊”,可能是因为我的元素具有设定的高度,因此最终不会在非整数边界上渲染。

                  因此我的解决方案是这样的:

                  .wrapper {
                    position: fixed;
                    left: 50%;
                    top: 50%;
                  }
                  .centered {
                    position: relative;
                    left: -50%;
                    -webkit-transform: translateY(-50%);
                    -ms-transform: translateY(-50%);
                    transform: translateY(-50%);
                  }
                  <div class="wrapper">
                    <div class="centered">
                      Content
                    </div>
                  </div>

                  【讨论】:

                  • 第一篇文章完美地解释了这个问题。关于仅设置 y 因为设置的高度,我设法绕过它。函数 centerTarget(tar){ var y = Math.ceil(tar.height()/2), x = Math.ceil(tar.width()/2); tar.css('transform','translateX(' + x + 'px) translateY(' + y + 'px)'); }
                  • 您的先生是个传奇!我只是花了最后几个小时尝试上帝知道有多少解决方案,直到这才奏效!非常感谢你!!!
                  • 感谢您考虑添加包装器。我想不出任何缺点,而且似乎有效。
                  【解决方案15】:

                  使用 HTML5 doctype 为我解决了这个问题。

                  <!doctype html>
                  <html>
                  <head>
                  <meta charset="UTF-8">
                  

                  【讨论】:

                    【解决方案16】:

                    对于替代解决方案,请尝试:

                    -webkit-text-stroke: 0.35px
                    

                    【讨论】:

                    • 抱歉,没有帮助到我。
                    【解决方案17】:

                    我通过在任何动画发生之前向元素添加translate3d 样式来解决此问题。

                    -webkit-transform: translate3d(0,0,0); 
                    

                    【讨论】:

                    • 这确实修复了我的子像素渲染,但也由于 translate3D 引入了模糊文本。它将其推送到渲染子像素的 GPU,但使其变得模糊。最好通过@neil-taylor 发布的解决方案一起解决问题
                    【解决方案18】:

                    @kizu 这些答案和建议无济于事。对于您的 jsfiddle,您需要添加

                    -webkit-perspective-origin: 50% 50%; -webkit-perspective: 1400px;

                    到要使用 translate3d 的元素的父元素,否则平移 z 轴实际上不会做任何事情。在这种情况下,您将其应用于单击的按钮,我认为您打算将其应用于内容。

                    但无论如何,添加这些以激活 z 轴更改会导致示例中的按钮模糊。

                    我也很想找到解决方案,恐怕没有。

                    【讨论】:

                      【解决方案19】:

                      正如@Robert 上面提到的,有时添加背景会有所帮助,但并非总是如此。

                      因此,对于 Dmitry 添加的示例,您必须做的不仅仅是:除了后台,您必须告诉浏览器显式使用正确的抗锯齿,因此,有一个固定的 Dmitry 示例:http://jsfiddle.net/PtDVF/1/

                      您需要在需要修复抗锯齿的块周围(或为这些块)添加这些样式:

                      background: #FFF; /* Or the actual color of your background/applied image */
                      -webkit-font-smoothing: subpixel-antialiased;
                      

                      【讨论】:

                      • 这可行,但如果我需要透明背景怎么办? background: transparent; 会再次导致字体模糊:-(
                      • 这刚刚节省了我的$$! background: rgba(0,0,0,0);。解决了 iOS 上一个非常讨厌的不需要的模糊
                      • Safari 11/High Sierra end of 2017 仍然受到影响,添加固定 background-color(不是 transparent 或 rgba(0, 0, 0, 0)`)是唯一有帮助的解决方案。跨度>
                      • 我在使用 translateZ 时也遇到了同样的问题,对我来说,当我将 translateX 和 translateY 一起使用而不使用 translateZ 时它起作用了,比如这个变换: translateX(-50%) translateY(-50%) ;也适用于透明背景
                      猜你喜欢
                      • 2011-12-22
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2020-01-08
                      相关资源
                      最近更新 更多