Пост-анимация размытого/искаженного текста на основе 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-enabled устройства, но я ни за что на свете не могу понять, почему это так плохо влияет на текст.

Любые предложения или решения будут высоко оценены.

16 42

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 к элементу до появления анимации.

-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 - единственным минусом было то, что мне пришлось ввести обертку.

Я обнаружил, что использование 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>

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

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

Div с шириной: 503px и высотой 500px вызовет размытие, независимо от того, в какую сторону вы его перемещаете или на сколько при использовании translateX или Y. используя transform, он использует графический ускоритель GPU, который должен привести к очень четким, гладким краям. Также может быть хорошей идеей установить размер коробки: 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;

Scale-and-zoom заботится об округлении значений пикселей до полных чисел

С помощью zoom решил ее для меня.

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

Я надеюсь, что речь идет о центрировании объекта в точном центре экрана. Размытие происходит при преобразовании: 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'
}

Вставить стиль в элемент с помощью 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">