web-dev-qa-db-fra.com

Post-animation de texte flou/déformé basée sur Webkit via translate3d

Ce problème semble affecter tous les navigateurs WebKit, y compris l'iPhone. 

D'abord un peu de fond. Le site sur lequel je travaille utilise une animation "curseur" basée sur JavaScript.

J'utilise -webkit-transform: translate3d pour "activer" l'animation réelle. Lorsque vous utilisez cette méthode, par opposition à une méthode basée sur JavaScript, le texte devient flou une fois que le contenu a été animé. Ceci est particulièrement visible sur l'iPhone.

Quelques solutions de contournement que j'ai vues étaient de supprimer un positionnement relatif, ce que j'ai fait, et d'ajouter une règle pour -webkit-font-smoothing: antialiased, ce que j'ai également fait. Aucun changement n'a fait la moindre différence.

Pour que only fonctionne correctement, sans texte flou, il fallait utiliser du JavaScript standard pour l'animation et contourner le translate3d. Je préférerais utiliser translate3d car il accélère beaucoup plus sur les périphériques compatibles WebKit, mais je ne peux pas comprendre pourquoi il affecte le texte de manière aussi médiocre.

Toute suggestion ou solution serait grandement appréciée.

46
Mike

Aucune de ces solutions ne semble avoir fonctionné pour moi, mais j'ai trouvé une solution légèrement sale qui semblait faire l'affaire:

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

J'ai eu exactement le même problème que dans l'article de Ken Avila: CSS: transformer: translate (-50%, -50%) rend les textes flous

Le problème était bien sûr que j’ai utilisé transform: translate (-50%, -50%), ce qui a rendu mon contenu centré flou, mais uniquement lors d’un safari sur osx.

Ce n'est pas seulement le texte qui devient flou, mais tout le contenu, y compris les images ... J'ai lu sur: http://keithclark.co.uk/articles/gpu-text-rendering-in-webkit/ que le "flou" est dû au fait que l'élément est rendu sur une limite non entière.

J'ai aussi découvert que je pouvais éviter d'utiliser transform translate sur la partie horizontale de mon centrage à partir de cet article: https://coderwall.com/p/quutdq/how-to-really-center-an-html-element-via -css-position-absolute-fixed -Le seul inconvénient est que je devais introduire un wrapper.

J'ai découvert que l'utilisation de transform: translateY (-50%) ne créait pas de "flou", peut-être parce que mon élément a une hauteur définie et ne finit donc pas par s'afficher sur une limite non entière.

Ma solution a donc fini comme ça:

.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>

17
Njaal Gjerde

J'ai résolu ce problème en ajoutant un style translate3d à l'élément avant toute animation.

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

Les éléments que vous traduisez doivent être divisibles par deux avec des nombres pairs.

Il est important que tout élément que vous essayez de déplacer de moitié soit divisible par deux pour sa largeur et sa hauteur. Très similaire aux images sensibles, lorsque les choses peuvent être déplacées de 50% sans fractionner les pixels.

Une div avec une largeur de 503px et une hauteur de 500px provoquera un flou, peu importe la façon dont vous le déplacez ou son ampleur lorsque vous utilisez translateX ou Y. En utilisant transform, il utilise un accélérateur graphique GPU qui donne un résultat très net et lisse bords. Il peut également être judicieux de définir la taille de la boîte: border-box; pour assurer que les largeurs calculées incluent le rembourrage et les bordures.

Faites attention lorsque vous utilisez des largeurs en pourcentage. Si elle est relative à la taille de l'écran, toute autre largeur de pixel de l'écran provoquera ce flou.

12
factorypolaris

C'est la meilleure solution translateX(calc(-50% + 0.5px))

4
Neil Taylor

Probablement la solution la plus simple:

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

Scale-and-Zoom veille à arrondir les valeurs de pixels en nombres entiers 

2
Šarūnas Sirotka

Aucune de ces réponses n'a fonctionné pour moi, mais en utilisant

display: inline-table;

a fait le tour

1
user3251328

J'espère qu'il s'agit de centrer l'objet au centre exact de l'écran . Le flou survient lors de la transformation: translate (-50%, - 50%);

alors au lieu de faire 

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

J'ai essayé d'injecter du style dans l'élément en utilisant 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'
}

injecter le style dans l'élément par le style javascript

Par exemple.

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

.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>

J'ai également eu le même problème lorsque j'ai utilisé translateZ, il a été résolu lorsque j'ai utilisé translateX et translateY ensemble et non translateZ, comme ceci

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

fonctionne avec un fond transparent aussi, je ne sais pas pourquoi mais a travaillé pour moi au moins

0
Pushpender

Utiliser zoom l'a résolu pour moi.

Je viens d'ajouter zoom: 1.04;

0
Black

La solution trouvée dans mon cas définissait une valeur height du premier élément enfant

0
DependencyHell