基于Webkit的模糊/失真文本后期动画通过translate3d

时间:2011-06-20 12:46:44

标签: javascript css text webkit blurry

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

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

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

我看到的一些解决方法是删除我所做的相对定位,并添加-webkit-font-smoothing: antialiased的规则,我也做了。这两种变化都没有丝毫差异。

方式我可以正常工作而不会出现模糊文本,因为它会使用常规JavaScript来制作动画并完全绕过translate3d。我更喜欢使用translate3d,因为它在支持WebKit的设备上执行很多更快,但对于我的生活,我无法弄清楚为什么它会以如此糟糕的方式影响文本

非常感谢任何建议或解决方案。

20 个答案:

答案 0 :(得分:21)

这些似乎都没有对我有用,但我发现了一个稍微肮脏的解决方案似乎可以解决这个问题:

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

答案 1 :(得分:19)

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

因此,对于示例,Dmitry补充说,这不是您必须做的唯一事情:除了背景之外,您必须告诉浏览器明确使用正确的抗锯齿,因此,有一个固定的Dmitry示例:{{3} }

您需要在需要修复消除锯齿功能的块周围添加这些样式:

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

答案 2 :(得分:17)

我遇到了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%)并没有创建任何" bluryness",可能是因为我的元素有一个设置的高度,因此不会最终渲染到非整数边界。

因此,我的解决方案就像这样:



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

答案 3 :(得分:16)

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

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

答案 4 :(得分:12)

您要翻译的元素必须可以被两个偶数整除。

我很重要的是,无论你想要移动一半的元素,它的宽度和高度都可被2整除。非常类似于响应式图像,当事物可以移动50%而不分割像素。

宽度为:503px且高度为500px的div将导致模糊,无论您移动它的方式或使用translateX或Y时使用多少。使用转换,它使用GPU图形加速器,这应该是非常清爽,光滑的边缘。设置box-sizing可能也是个好主意:border-box;确保计算出的宽度包括填充和边框。

使用百分比宽度时要小心。如果它与屏幕尺寸相关,则其他屏幕像素宽度将导致此模糊。

答案 5 :(得分:4)

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

答案 6 :(得分:2)

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

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

缩放和缩放负责将像素值四舍五入为全数

答案 7 :(得分:1)

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

display: inline-table;

做了这个伎俩

答案 8 :(得分:0)

如果该百分比用于动画制作,即使我们也认为它的性能仍然可以接受,但是当您不使用translate进行动画制作时,它会有所不同,因为文本总是模糊不清。

使用百分比时,可能会有分数0.5px文字模糊的原因。在我的实验中,使用translate(0.5px, 0.5px)会使文本非常模糊,因此应避免在0.3px <=> 0.7px仍可接受的情况下在0.2px and 0.8px之间使用小数。

我的建议是使用JavaScript,然后将百分比转换为用于像素化的圆形像素,如果使用translate定位元素,则使用像素而不是百分比。

另一种选择是使用lefttop来设置具有百分比的初始位置,然后将transform: translate() >像素作为目标位置,并仅使用transform

transition-property: transform;设置动画

答案 9 :(得分:0)

将Chrome的缩放比例重置为100%对我来说很有效。

答案 10 :(得分:0)

尼尔·泰勒(Neil Taylor)的解决方案是最好的,但仍可以改进:

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

这种方式有2个优点:

  • 它可以在诸如IE11这样的糟糕浏览器中使用(不支持内部转换中的calc)
  • 它仅在解析时进行计算,而不是在浏览器每次评估时进行计算。

答案 11 :(得分:0)

将容器中应用了转换转换属性的任何元素的垂直边距(margin-top或margin-bottom)或高度减小一个像素。

答案 12 :(得分:0)

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

答案 13 :(得分:0)

.row{
        height: 100vh;
        background-color:black;
      }
      .align-center{
        left:50%;
        top:50%;
        background-color:green;
      }
      
      .translate3d{
        transform: translate3d(-50%,-50%,0);
      }
      .translateXY{
        transform: translateX(-50%) translateY(-50%);
      }
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row">
      <div class="col">
        <h1 class="text-center position-absolute align-center text-white translate3d font-weight-bold">BLURRED</h1>
      </div>
      <div class="col">
        <h1 class=" text-center position-absolute align-center text-white font-weight-bold translateXY  ">CLEAR</h1>
      </div>

当我使用translateZ时,我也遇到了同样的问题,当我同时使用translateX和translateY而不是translateZ时,问题得到解决

transform: translateX(-50%) translateY(-50%);

也具有透明背景,不知道为什么,但至少对我有用

答案 14 :(得分:0)

我希望这是将对象居中到屏幕的准确中心。 转换会发生模糊: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>
        );
    }
}

答案 15 :(得分:0)

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

我刚刚添加了zoom: 1.04;

答案 16 :(得分:-1)

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

will-change: transform;

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

答案 17 :(得分:-1)

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

-webkit-text-stroke: 0.35px

答案 18 :(得分:-1)

@kizu 这些答案和建议没有帮助。对于你的jsfiddle你需要添加

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

到你想要使用translate3d的元素的父元素,否则翻译z轴实际上并没有做任何事情。在这种情况下,您将它应用于您单击的按钮,我认为您打算将其应用于内容。

但无论如何,添加激活z轴变化会导致模糊到示例中的按钮。

我很想找到解决方案,我担心没有。

答案 19 :(得分:-6)

使用HTML5 doctype解决了我的问题。

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