Пост-анимация размытого/искаженного текста на основе 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 ответов:
Как упоминал выше @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; чтобы гарантировать, что рассчитанные ширины включают отступы и границы.
Будьте осторожны при использовании ширины в процентах. Если это относительно размера экрана, любая другая ширина пикселя экрана вызовет это размытие.
Просто исправил это с помощью простого трюка, который я не знаю причину. Здесь вы можете увидеть другое.
Первоначально я стилизовал элемент следующим образом:
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 заботится об округлении значений пикселей до полных чисел
Я надеюсь, что речь идет о центрировании объекта в точном центре экрана. Размытие происходит при преобразовании: 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, приводит к размытию кнопка в вашем примере.
Я бы тоже хотел найти решение этой проблемы, но боюсь, что его нет.
Я использую
will-change
для этих типов задач, он обычно решает проблемы масштабирования или ошибки округления, такие как вид белой линии 1px, разделяющей элементы, например.
will-change: transform;
Подробнее читайте здесь: https://developer.mozilla.org/en-US/docs/Web/CSS/will-change