Webkit на основе размытого / искаженного текста пост-анимация через translate3d

эта проблема затрагивает все браузеры на основе WebKit, включая iPhone.

первую очередь. Сайт, над которым я работаю, использует анимацию слайдера на основе JavaScript, которая в основном идентична этой: http://www.assistly.com/product-tour/#/easy-setup

единственная разница в том, что я использую -webkit-transform: translate3d для "питания" фактической анимации. При использовании этого метода, в отличие от метода на основе JavaScript, текст становится размытым один раз контент был анимирован. Это особенно заметно на iPhone.

несколько обходных путей, которые я видел, должны были удалить относительное позиционирование, что я и сделал, и добавить правило для -webkit-font-smoothing: antialiased, что я тоже сделал. Ни изменения ни малейшей разницы.

на только способ, которым я мог бы сделать эту работу правильно без размытого текста, - использовать обычный JavaScript для анимации и обойти translate3d в целом. Я бы предпочел использовать translate3d потому что он выполняет много быстрее на устройствах с поддержкой WebKit, но я не могу понять, почему это влияет на текст таким плохим образом.

любые предложения или решения были бы весьма признательны.

16 ответов


Как упоминалось выше @Robert, иногда добавление фона помогает, Но не всегда.

Итак, для примера Дмитрий добавил, что это не единственное, что вы должны сделать: за исключением фона, вы должны сказать браузеру явно использовать правильное сглаживание, поэтому есть пример фиксированного Дмитрия:http://jsfiddle.net/PtDVF/1/

вам нужно добавить эти стили вокруг (или для) блоков, где вам нужно исправить сглаживание:

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

ни один из них, похоже, не сработал для меня, но я нашел немного грязное решение, которое, казалось, сделало трюк:

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

я исправил эту проблему путем добавления translate3d style к элементу перед любой анимацией происходит.

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

у меня была точно такая же проблема, описанная в сообщении Кена Авилы:CSS: transform: translate (-50%, -50%) делает тексты размытыми

проблема заключалась в том, что я использовал transform: translate(-50%, -50%), что сделало мой центрированный контент размытым, но только в safari на osx.

размывается не только текст, но и весь контент, включая изображения. Я читаю дальше.: http://keithclark.co.uk/articles/gpu-text-rendering-in-webkit/ что "размытость" обусловлена тем, что элемент отображается на нецелочисленной границе.

Я также обнаружил, что могу избежать использования transform translate в горизонтальной части моего центрирования с этого поста: https://coderwall.com/p/quutdq/how-to-really-center-an-html-element-via-css-position-absolute-fixed


элементы, которые вы переводите, должны быть делимы на два с четными числами.

важно, чтобы любой элемент, который вы пытаетесь сдвинуть наполовину, делился на два для ширины и высоты. Очень похоже на отзывчивые изображения, когда вещи можно перемещать на 50% без разделения пикселей.

div с шириной: 503px и высотой 500px вызовет размытие, независимо от того, каким образом вы его перемещаете или на сколько при использовании translateX или Y. используя transform, он использует графический ускоритель GPU, который должен привести к очень четким, гладким краям. Также может быть хорошей идеей установить box-sizing: border-box; чтобы обеспечить расчетную ширину, включая заполнение и границы.

будьте осторожны при использовании процентах ширины. Если это относительно размера экрана, любая другая ширина пикселя экрана вызовет это размытие.


Это лучшее решение translateX(calc(-50% + 0.5px))


ни один из этих ответов не работал для меня, но с помощью

display: inline-table;

получилось


просто получил это исправлено простым трюком, который я не знаю причины. Здесь вы можете увидеть другое.

Первоначально я стилизовал элемент следующим образом:

top: 50%;
left: 50%;
transform: translate(-50%, -50%);

что приводит к размытому тексту... После случайной пробной версии я помещаю стиль в стиль класса и заставляю процессор CSS принимать этот стиль вместо стиля элемента (поскольку я использую компоненты React, стили, установленные React, станут стилем элемента)

это то, что я делавший.

.class-name {
    top: 50% !important;
    left: 50% !important;
    transform: translate(-50%, -50%) !important;
}

Я действительно хочу знать, почему перемещение этого стиля из стиля элемента в стиль класса исправит это. Есть идеи?


наверное самое простое решение:

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

масштабирование и масштабирование заботится о округлении значений пикселей до полных чисел


используя zoom решил это за меня.

Я только что добавил zoom: 1.04;


Я надеюсь, что речь идет о центрировании объекта в точный центр экрана. Размытие происходит с transform: translate(-50%,-50%);

Так вместо этого делает

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

Я попытался ввести стиль в элемент с помощью javascript. (Реагировать.в 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'
}

inject style в элемент по javascript style

например.

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

У меня также была такая же проблема, когда я использовал translateZ, я решил ее, используя translateX и translateY вместе и не используя translateZ, как это

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

работает с прозрачным фоном, а также


@kizu Эти ответы и предложения не помогут. Для вашего jsfiddle вам нужно добавить

- webkit-перспектива-происхождение: 50% 50%; - webkit-перспектива: 1400px;

родительскому элементу элемента, на котором вы хотите использовать translate3d, в противном случае перевод оси z фактически ничего не делает. В этом случае вы применяете его к кнопке, которую нажимаете, я думаю, вы хотели применить его к контенту.

но в любом случае, добавление тех, чтобы активировать изменение оси z вызывает размытие кнопки в вашем примере.

Я хотел бы найти решение и для этого, боюсь, что его нет.


для альтернативного решения попробуйте:

-webkit-text-stroke: 0.35px

Я использую will-change в этих типах проблем он обычно решает проблемы масштабирования или ошибки округления, например, видеть белую линию 1px, разделяющую элементы.

will-change: transform;

подробнее здесь: https://developer.mozilla.org/en-US/docs/Web/CSS/will-change


использование HTML5 doctype решило проблему для меня.

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