Wie kann ich WebKit zwingen, neu zu zeichnen / neu zu zeichnen, um Stiländerungen zu verbreiten?

247

Ich habe ein triviales JavaScript, um eine Stiländerung zu bewirken:

sel = document.getElementById('my_id');
sel.className = sel.className.replace(/item-[1-9]-selected/,'item-1-selected');
return false;

Dies funktioniert gut mit den neuesten Versionen von FF, Opera und IE, schlägt jedoch mit den neuesten Versionen von Chrome und Safari fehl.

Es betrifft zwei Nachkommen, die zufällig Geschwister sind. Das erste Geschwister-Update, das zweite nicht. Ein untergeordnetes Element des zweiten Elements hat ebenfalls den Fokus und enthält das <a> -Tag, das den obigen Code in einem onclick- Attribut enthält.

Im Chrome „Developer Tools“ Fenster wenn ich Schubs (zB uncheck & check) jedes Attribut von jedem Element, die zweite Geschwister - Updates auf den richtigen Stil.

Gibt es eine Problemumgehung, um WebKit einfach und programmgesteuert dazu zu bringen, das Richtige zu tun?

Danorton
quelle
Ich glaube, ich habe dieses Problem unter Android 4.2.2 (Samsung I9500), wenn ich meine Canvas-App in ein WebView einbinde. Lächerlich!
Josh
3
what-forces-layout.md ein sehr guter
Leseplatz

Antworten:

312

Ich fand einige komplizierte Vorschläge und viele einfache, die nicht funktionierten, aber ein Kommentar von Vasil Dinkov zu einem von ihnen bot eine einfache Lösung, um ein Neuzeichnen / Neulackieren zu erzwingen, das einwandfrei funktioniert:

sel.style.display='none';
sel.offsetHeight; // no need to store this anywhere, the reference is enough
sel.style.display='';

Ich lasse jemanden kommentieren, wenn es für andere Stile als "Block" funktioniert.

Danke, Vasil!

Danorton
quelle
32
Um zu vermeiden , flackernde Sie versuchen können 'inline-block', 'table'oder 'run-in'statt 'none', aber dies kann Nebenwirkungen haben. Auch ein Timeout von 0 löst einen Reflow aus, genau wie das Abfragen offsetHeight:sel.style.display = 'run-in'; setTimeout(function () { sel.style.display = 'block'; }, 0);
user123444555621
15
Diese Antwort ist auch 2 Jahre später noch nützlich. Ich habe es nur verwendet, um ein Nur-Chrome-Problem zu beheben, bei dem CSS-Box-Schatten auf dem Bildschirm blieben, nachdem die Größe des Browsers auf bestimmte Weise geändert wurde. Vielen Dank!
Rkulla
5
@danorton Du hast 2010 geantwortet. Es ist 2013 und der Fehler ist immer noch da. Vielen Dank. Weiß übrigens jemand, ob beim Webkit-Tracker ein Problem registriert ist?
RaphaelDDL
13
PS.: Für mich hat die obige Lösung nicht mehr funktioniert. Stattdessen habe ich dies verwendet (jQuery): sel.hide (). Show (0); Quelle: stackoverflow.com/questions/8840580/…
ProblemsOfSumit
7
Alles, was Sie tun müssen, ist eine Größeneigenschaft zu lesen, Sie müssen sie nicht hin und her ändern.
Andrew Bullock
93

Wir sind kürzlich darauf gestoßen und haben festgestellt, dass das Heraufstufen des betroffenen Elements auf eine zusammengesetzte Ebene mit translateZ in CSS das Problem behoben hat, ohne dass zusätzliches JavaScript erforderlich war.

.willnotrender { 
   transform: translateZ(0); 
}

Da diese Malprobleme hauptsächlich in Webkit / Blink auftreten und dieses Update hauptsächlich auf Webkit / Blink abzielt, ist es in einigen Fällen vorzuziehen. Zumal die akzeptierte Antwort mit ziemlicher Sicherheit einen Reflow und ein Repaint verursacht , nicht nur ein Repaint.

Webkit und Blink haben hart an der Renderleistung gearbeitet, und diese Art von Störungen sind der unglückliche Nebeneffekt von Optimierungen, die darauf abzielen, unnötige Flüsse und Farben zu reduzieren. CSS wird sich ändern oder eine andere nachfolgende Spezifikation wird höchstwahrscheinlich die zukünftige Lösung sein.

Es gibt andere Möglichkeiten, eine Verbundschicht zu erzielen, dies ist jedoch die häufigste.

mehr
quelle
1
Arbeitete für mich bei der Verwendung von Winkelkarussell !
Gustavohenke
1
Es wurde mein Problem
Timo
1
Funktioniert auch für Cordova-Projekte!
Quispie
1
Arbeitete für mich für eine Webkit-Line-Clamp, die nicht aktualisiert wurde
Adam Marshall
1
Arbeitete für mich auf dem iPad (6.0) mit -webkit-transform: translate (-50%, -50%).
Lain
51

Die Danorton-Lösung hat bei mir nicht funktioniert. Ich hatte einige wirklich seltsame Probleme, bei denen das Webkit einige Elemente überhaupt nicht zeichnete. wo der Text in den Eingaben erst bei Unschärfe aktualisiert wurde; Das Ändern des Klassennamens würde nicht zu einem erneuten Zeichnen führen.

Ich habe versehentlich festgestellt, dass meine Lösung darin bestand, dem Body nach dem Skript ein leeres Stilelement hinzuzufügen.

<body>
...
<script>doSomethingThatWebkitWillMessUp();</script>
<style></style>
...

Das hat es behoben. Wie komisch ist das? Hoffe das ist hilfreich für jemanden.

Gerben
quelle
3
Ich würde 1.000.000 Mal upvoten, wenn ich könnte. Dies ist der einzige Weg, wie ich Chrom dazu bringen kann, einen dummen Div neu zu streichen, den ich herumgeschleppt habe. Übrigens müssen Sie kein Stilelement hinzufügen (zumindest habe ich es nicht getan), jedes Element wird funktionieren. Ich habe ein Div erstellt und ihm eine ID gegeben, damit ich das Element bei jedem Schritt löschen und dann hinzufügen kann, um das DOM nicht mit nutzlosen Tags zu füllen.
hobberwickey
6
Ich habe dies nur gemischt mit Pumbaa80s Kommentar zu einer anderen Antwort verwendet. Das var div = $('<div>').appendTo(element); setTimeout(function(){ div.remove(); }, 0);
Update
33
Diese einzelne Zeile funktioniert hervorragend für mich! $('<style></style>').appendTo($(document.body)).remove();
pdelanauze
1
@pdelanauze Antwort funktioniert perfekt. Ich habe ein Redraw-Problem sing css3 übersetzen und in ios transformieren.
Marcel Falliere
11
Wissen Sie nur, dass dies ein Neulackieren der gesamten Seite erzwingt, während Sie die meiste Zeit nur einen bestimmten Abschnitt der Seite neu streichen möchten ...
Ryan Wheale
33

Da der Display + Offset-Trigger bei mir nicht funktioniert hat, habe ich hier eine Lösung gefunden:

http://mir.aculo.us/2009/09/25/force-redraw-dom-technique-for-webkit-based-browsers/

dh

element.style.webkitTransform = 'scale(1)';
EricG
quelle
3
Ich habe dies in einem Hack verwendet, den ich versucht habe, aber stattdessen habe scale(1)ich es sich selbst zugewiesen als element.style.webkitTransform = element.style.webkitTransform. Der Grund dafür war, dass das Einstellen auf das erstere die Seite für absolutely positionierte Elemente leicht verzerrte !
bPratik
Dies funktionierte für mich und hatte keine Probleme beim Flackern oder Zurücksetzen der Bildlaufposition, die die displayLösung hatte.
Davidtbernal
Ich hatte eine Cordova-App mit viel dynamischem SVG. Funktionierte überall einwandfrei, außer in iOS7, wo die SVG-Elemente beim Start nicht angezeigt wurden. Ein einfaches $ ('body') [0] .style.webkitTransform = 'scale (1)' wurde hinzugefügt. zum Initialisierungscode und das Problem ist verschwunden!
Herc
Dies funktioniert derzeit nicht auf der neuesten Version von Safari und iOS.
Setholopolus
@ Setholopolus welche Versoin (s) wäre das?
EricG
23

Ich hatte das gleiche Problem. Danortons 'Toggling Display'-Fix funktionierte für mich, als er zur Schrittfunktion meiner Animation hinzugefügt wurde, aber ich war besorgt über die Leistung und suchte nach anderen Optionen.

Unter meinen Umständen befand sich das Element, das nicht neu gestrichen wurde, innerhalb eines absoluten Positionselements, das zu diesem Zeitpunkt keinen Z-Index hatte. Durch Hinzufügen eines Z-Index zu diesem Element wurde das Verhalten von Chrome geändert, und das Neulackieren erfolgte wie erwartet -> Animationen wurden reibungslos.

Ich bezweifle, dass dies ein Allheilmittel ist. Ich kann mir vorstellen, dass es davon abhängt, warum Chrome das Element nicht neu gezeichnet hat, aber ich poste diese spezielle Lösung hier in der Hilfe, die jemand hofft.

Prost, Rob

tl; dr >> Versuchen Sie, dem Element oder einem übergeordneten Element einen Z-Index hinzuzufügen.

Rob Murphy
quelle
8
Brillant. Das ist großartig und hat das Problem für mich behoben. Ein +++ würde wieder Z-Index.
Trisweb
Hat in meiner Situation mit Bildlaufleisten und Transformationen nicht funktioniert.
Ricky Boyce
16

Folgendes funktioniert. Es muss nur einmal in reinem CSS eingestellt werden. Und es funktioniert zuverlässiger als eine JS-Funktion. Die Leistung scheint davon nicht betroffen zu sein.

@-webkit-keyframes androidBugfix {from { padding: 0; } to { padding: 0; }}
body { -webkit-animation: androidBugfix infinite 1s; }
Sweeds
quelle
Sieht so aus, als würde es auch bei mir funktionieren. Verwendet dies, um ein Rendering-Problem mit Mobile Safari zu beheben
Chris
Dies behebt mein Problem und zwingt die Safari zum Relayout. Allerdings habe ich zoomstatt Polsterung verwendet:@-webkit-keyframes safariBugFix {from { zoom: 100%; } to { zoom: 99.99999%; }}
Ahmed Musallam
13

Aus irgendeinem Grund konnte ich Danortons Antwort nicht auf die Arbeit bringen, ich konnte sehen, was es tun sollte, also habe ich es ein wenig angepasst:

$('#foo').css('display', 'none').height();
$('#foo').css('display', 'block');

und es hat bei mir funktioniert.

sowasred2012
quelle
7
Ich habe alles darüber versucht, aber nur dieser hat für mich funktioniert. WTF Webkit! Das ist keine Informatik! Das ist schwarze Magie!
Charlie Martin
7

Ich bin hierher gekommen, weil ich nach dem Ändern des CSS Bildlaufleisten in Chrome neu zeichnen musste.

Wenn jemand das gleiche Problem hat, habe ich es durch Aufrufen dieser Funktion gelöst:

//Hack to force scroll redraw
function scrollReDraw() {
    $('body').css('overflow', 'hidden').height();
    $('body').css('overflow', 'auto');
}

Diese Methode ist nicht die beste Lösung, funktioniert jedoch möglicherweise mit allem. Das Ausblenden und Anzeigen des Elements, das neu gezeichnet werden muss, kann jedes Problem lösen.

Hier ist die Geige, wo ich sie benutzt habe: http://jsfiddle.net/promatik/wZwJz/18/

António Almeida
quelle
1
Toll! Ich habe auch versucht, die Bildlaufleisten zu animieren, und das habe ich gebraucht! Übrigens besser Überlauf verwenden: Overlay für animierte Bildlaufleisten
ekalchev
6

Ich bin heute darauf gestoßen : Element.redraw () für prototype.js

Verwenden von:

Element.addMethods({
  redraw: function(element){
    element = $(element);
    var n = document.createTextNode(' ');
    element.appendChild(n);
    (function(){n.parentNode.removeChild(n)}).defer();
    return element;
  }
});

Manchmal ist mir jedoch aufgefallen, dass Sie redraw () für das problematische Element direkt aufrufen müssen. Manchmal löst das Neuzeichnen des übergeordneten Elements das Problem des Kindes nicht.

Guter Artikel über die Art und Weise, wie Browser Elemente rendern: Rendern: Repaint, Reflow / Relayout, Restyle

Adam Eberlin
quelle
1
appendChildist eine DOM-Methode, keine jQuery-Methode.
ChrisW
4

Ich hatte dieses Problem mit einer Anzahl von Divs, die in ein anderes Div position: absoluteeingefügt wurden. Die eingefügten Divs hatten kein Positionsattribut. Als ich das geändert habe, hat position:relativees gut funktioniert. (war wirklich schwer, das Problem zu lokalisieren)

In meinem Fall wurden die Elemente von Angular mit eingefügt ng-repeat.

JustGoscha
quelle
1
Vielen Dank! Dies funktionierte auch für mein Problem und ist viel leichter als viele der oben genannten Javascript-Lösungen.
Dsyko
4

Ich kann nicht glauben, dass dies 2014 immer noch ein Problem ist. Ich hatte gerade dieses Problem, als ich beim Scrollen ein Beschriftungsfeld mit fester Position unten links auf der Seite aktualisierte. Die Beschriftung würde sich auf dem Bildschirm nach oben bewegen. Nachdem ich alles oben ohne Erfolg ausprobiert hatte, bemerkte ich, dass viele Dinge entweder langsam waren oder Probleme verursachten, weil sehr kurze DOM-Relayouts usw. erstellt wurden, was ein etwas unnatürliches Gefühl beim Scrollen usw. verursachte.

pointer-events: noneAm Ende machte ich eine feste Position, div in voller Größe mit und wendete Danortons Antwort auf dieses Element an, was eine Neuzeichnung auf dem gesamten Bildschirm zu erzwingen scheint, ohne das DOM zu stören.

HTML:

<div id="redraw-fix"></div>

CSS:

div#redraw-fix {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 25;
    pointer-events: none;
    display: block;
}

JS:

sel = document.getElementById('redraw-fix');
sel.style.display='none';
sel.offsetHeight; // no need to store this anywhere, the reference is enough
sel.style.display='block';
Waffel
quelle
Ich kann Ihnen nicht genug für Ihre Problemumgehung danken, die die einzige ist, die für mich funktioniert hat. Ja, es ist 2017 und das Problem bleibt bestehen. Mein Problem hing mit einer RTL-Sprachseite zusammen, die leer war, wenn sie auf Android-Mobilgeräten manuell aktualisiert wurde. Die z-indexund pointer-eventsRegeln sind hier überflüssig.
Amin Mozafari
Ich habe schon einmal Danortons Fix verwendet, hatte aber wirklich Probleme mit dem Aufblitzen des Inhalts von der Einstellung der Anzeige auf keine. Ihre Lösung hat für mich ohne Content Flash hervorragend funktioniert!
Justin Noel
3

Nicht, dass diese Frage eine andere Antwort braucht, aber ich fand, dass das einfache Ändern der Farbe durch ein einzelnes Bit ein Neulackieren in meiner speziellen Situation erzwang.

//Assuming black is the starting color, we tweak it by a single bit
elem.style.color = '#000001';

//Change back to black
setTimeout(function() {
    elem.style.color = '#000000';
}, 0);

Es hat sich setTimeoutals kritisch erwiesen, die zweite Stiländerung außerhalb der aktuellen Ereignisschleife zu verschieben.

TMan
quelle
1
Das Setzen eines Timeouts von 0 erwies sich für mich in einer anderen, aber ähnlichen Situation als nützlich. Das Neuzeichnen fand nicht statt, bevor die unauffällige Validierung des Bildschirms den Bildschirm einfrierte, während ein großes Formular analysiert wurde. Ich dachte, ich würde einen Kommentar abgeben, falls sich jemand da draußen in der gleichen Situation befindet. Die anderen Lösungen funktionierten in diesem Szenario nicht.
k29
2

Die einzige Lösung, die für mich funktioniert, ähnelt der Antwort von sowasred2012:

$('body').css('display', 'table').height();
$('body').css('display', 'block');

Ich habe viele Problemblöcke auf der Seite, daher ändere ich die displayEigenschaft des Stammelements. Und ich benutze display: table;stattdessen display: none;, weil noneder Bildlaufversatz zurückgesetzt wird.

Ilya Sviridenko
quelle
1

Da jeder seine eigenen Probleme und Lösungen zu haben scheint, dachte ich mir, ich würde etwas hinzufügen, das für mich funktioniert. Unter Android 4.1 mit aktuellem Chrome wurde versucht, eine Leinwand innerhalb eines Divs mit Überlauf zu ziehen: Ausgeblendet konnte ich kein Neuzeichnen erhalten, es sei denn, ich habe dem übergeordneten Div ein Element hinzugefügt (wo es keinen Schaden anrichten würde).

var parelt = document.getElementById("parentid");
var remElt = document.getElementById("removeMe");
var addElt = document.createElement("div");
addElt.innerHTML = " "; // Won't work if empty
addElt.id="removeMe";
if (remElt) {
    parelt.replaceChild(addElt, remElt);
} else {
    parelt.appendChild(addElt);
}

Kein Bildschirmflimmern oder echtes Update und Aufräumen nach mir. Keine globalen oder klassenbezogenen Variablen, nur Einheimische. Scheint auf Mobile Safari / iPad oder Desktop-Browsern nichts zu schaden.

Eric Ruck
quelle
1

Ich arbeite an einer ionischen HTML5-App. Auf einigen Bildschirmen habe ich absoluteein Element positioniert. Beim Scrollen nach oben oder unten auf iOS-Geräten (iPhone 4,5,6, 6+) hatte ich einen Repaint-Fehler.

Versuchte viele Lösungen, von denen keine funktionierte, außer diese löste mein Problem.

Ich habe CSS-Klasse .fixRepaintfür diese absoluten Positionselemente verwendet

.fixRepaint{
    transform: translateZ(0);
}

Dies hat mein Problem behoben, es kann jemandem helfen

Anjum ....
quelle
1
Opss einige, wie ich das nicht gesehen habe. @morewry Danke für den Hinweis
Anjum ....
1

Ich benutze die transform: translateZ(0);Methode, aber in einigen Fällen ist es nicht ausreichend.

Ich bin kein Fan des Hinzufügens und Entfernens einer Klasse, also habe ich versucht, einen Weg zu finden, dies zu lösen, und am Ende einen neuen Hack gefunden, der gut funktioniert:

@keyframes redraw{
    0% {opacity: 1;}
    100% {opacity: .99;}
}

// ios redraw fix
animation: redraw 1s linear infinite;
Guillaume Gautier
quelle
0

Dies ist in Ordnung für JS

sel.style.display='none';
sel.offsetHeight; // no need to store this anywhere, the reference is enough
sel.style.display='block';

In Jquery und insbesondere dann, wenn Sie nur $ (document) .ready verwenden und aus einem bestimmten Grund nicht an das .load-Ereignis eines Objekts binden können, funktioniert Folgendes.

Sie müssen den OUTER (MOST) -Container der Objekte / Divs abrufen, den gesamten Inhalt in eine Variable entfernen und ihn dann erneut hinzufügen. Dadurch werden ALLE im Außencontainer vorgenommenen Änderungen sichtbar.

$(document).ready(function(){
    applyStyling(object);
    var node = $("div#body div.centerContainer form div.centerHorizontal").parent().parent();
    var content = node.html();
    node.html("");
    node.html(content);
}
WiR3D
quelle
0

Ich habe festgestellt, dass diese Methode bei der Arbeit mit Übergängen hilfreich ist

$element[0].style.display = 'table'; 
$element[0].offsetWidth; // force reflow
$element.one($.support.transition.end, function () { 
    $element[0].style.display = 'block'; 
});
jschr
quelle
0

Der Hack "display / offsetHeight" hat in meinem Fall nicht funktioniert, zumindest wenn er auf das zu animierende Element angewendet wurde.

Ich hatte ein Dropdown-Menü, das über dem Seiteninhalt geöffnet / geschlossen wurde. Die Artefakte wurden nach dem Schließen des Menüs auf dem Seiteninhalt belassen (nur in Webkit-Browsern). Der "display / offsetHeight" -Hack hat nur funktioniert, wenn ich ihn auf den Körper angewendet habe, was böse erscheint.

Ich habe jedoch eine andere Lösung gefunden:

  1. Fügen Sie vor dem Animieren des Elements eine Klasse hinzu, die "-webkit-backface-sichtbarkeit: versteckt" definiert. auf dem Element (Sie könnten auch Inline-Stil verwenden, würde ich vermuten)
  2. Wenn die Animation abgeschlossen ist, entfernen Sie die Klasse (oder den Stil).

Dies ist immer noch ziemlich hackig (es verwendet eine CSS3-Eigenschaft, um das Hardware-Rendering zu erzwingen), aber zumindest betrifft es nur das betreffende Element und hat für mich sowohl auf Safari als auch auf Chrome auf PC und Mac funktioniert.

Tedtedson
quelle
0

Dies scheint damit verbunden zu sein: tun jQuery-Stil wird in Safari nicht angewendet

Die in der ersten Antwort vorgeschlagene Lösung hat in diesen Szenarien für mich gut funktioniert: Anwenden und Entfernen einer Dummy-Klasse auf den Körper, nachdem die Stiländerungen vorgenommen wurden:

$('body').addClass('dummyclass').removeClass('dummyclass');

Dies zwingt die Safari zum Neuzeichnen.

Steve
quelle
Damit dies in Chrome funktioniert, musste ich hinzufügen: $ ('body'). AddClass ('dummyclass'). Delay (0) .removeClass ('dummyclass');
mbokil
0

Die obigen Vorschläge haben bei mir nicht funktioniert. aber das unten tut.

Möchten Sie den Text im Anker dynamisch ändern? Das Wort "Suche". Erstellt ein inneres Tag "font" mit einem ID-Attribut. Verwaltete den Inhalt mit Javascript (unten)

Suche

Skriptinhalt:

    var searchText = "Search";
    var editSearchText = "Edit Search";
    var currentSearchText = searchText;

    function doSearch() {
        if (currentSearchText == searchText) {
            $('#pSearch').panel('close');
            currentSearchText = editSearchText;
        } else if (currentSearchText == editSearchText) {
            $('#pSearch').panel('open');
            currentSearchText = searchText;
        }
        $('#searchtxt').text(currentSearchText);
    }
Ganesh
quelle
0

Ich hatte ein Problem mit einem SVG, das unter Chrome für Android verschwand, als die Ausrichtung unter bestimmten Umständen geändert wurde. Der folgende Code gibt es nicht wieder, aber es ist das Setup, das wir hatten.

body {
  font-family: tahoma, sans-serif;
  font-size: 12px;
  margin: 10px;
}
article {
  display: flex;
}
aside {
  flex: 0 1 10px;
  margin-right: 10px;
  min-width: 10px;
  position: relative;
}
svg {
  bottom: 0;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}
.backgroundStop1 {
  stop-color: #5bb79e;
}
.backgroundStop2 {
  stop-color: #ddcb3f;
}
.backgroundStop3 {
  stop-color: #cf6b19;
}
<article>
  <aside>
    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="100%" width="100%">
      <defs>
        <linearGradient id="IndicatorColourPattern" x1="0" x2="0" y1="0" y2="1">
          <stop class="backgroundStop1" offset="0%"></stop>
          <stop class="backgroundStop2" offset="50%"></stop>
          <stop class="backgroundStop3" offset="100%"></stop>
        </linearGradient>
      </defs>
      <rect x="0" y="0" rx="5" ry="5" width="100%" height="100%" fill="url(#IndicatorColourPattern)"></rect>
    </svg>
  </aside>
  <section>
    <p>Donec et eros nibh. Nullam porta, elit ut sagittis pulvinar, lacus augue lobortis mauris, sed sollicitudin elit orci non massa. Proin condimentum in nibh sed vestibulum. Donec accumsan fringilla est, porttitor vestibulum dolor ornare id. Sed elementum
      urna sollicitudin commodo ultricies. Curabitur tristique orci et ligula interdum, eu condimentum metus eleifend. Nam libero augue, pharetra at maximus in, pellentesque imperdiet orci.</p>
    <p>Fusce commodo ullamcorper ullamcorper. Etiam eget pellentesque quam, id sodales erat. Vestibulum risus magna, efficitur sed nisl et, rutrum consectetur odio. Sed at lorem non ligula consequat tempus vel nec risus.</p>
  </section>
</article>

Tag und einen halben Tag nach dem Stochern und Stupsen und nicht glücklich mit dem Hacky ich angebotenen Lösungen , stellte ich fest, dass das Problem durch die Tatsache verursacht wurde, dass das Element beim Zeichnen eines neuen in Erinnerung zu bleiben schien. Die Lösung bestand darin, die ID des linearGradient in der SVG eindeutig zu machen, obwohl sie immer nur einmal pro Seite verwendet wurde.

Dies kann auf viele verschiedene Arten erreicht werden, aber für unsere Winkel-App haben wir die Funktion lodash uniqueId verwendet, um dem Bereich eine Variable hinzuzufügen:

Winkelrichtlinie (JS):

scope.indicatorColourPatternId = _.uniqueId('IndicatorColourPattern');

HTML-Updates:

Zeile 5: <linearGradient ng-attr-id="{{indicatorColourPatternId}}" x1="0" x2="0" y1="0" y2="1">

Zeile 11: <rect x="0" y="0" rx="5" ry="5" width="100%" height="100%" ng-attr-fill="url(#{{indicatorColourPatternId}})"/>

Ich hoffe, diese Antwort erspart jemand anderem Tage, um seine Tastatur zu zerschlagen.

Jamie Barker
quelle
0

Ich würde eine weniger hackige und formellere Methode empfehlen, um einen Reflow zu erzwingen: Verwenden Sie forceDOMReflowJS . In Ihrem Fall würde Ihr Code wie folgt aussehen.

sel = document.getElementById('my_id');
forceReflowJS( sel );
return false;
Jack Giffin
quelle
0

Ich habe festgestellt, dass das Hinzufügen eines Inhaltsstils zum Element das Neulackieren erzwang. Dies sollte jedes Mal ein anderer Wert sein, wenn Sie möchten, dass es neu gezeichnet wird, und muss sich nicht auf einem Pseudoelement befinden.

.selector {
    content: '1'
}
Steve
quelle
0

Ich habe versucht, mehr zu antworten, aber es funktioniert nicht für mich. Ich hatte Probleme, die gleiche Clientbreite mit Safari im Vergleich zu anderen Browsern zu haben, und dieser Code löste das Problem:

var get_safe_value = function(elm,callback){
    var sty = elm.style
    sty.transform = "translateZ(1px)";
    var ret = callback(elm)//you can get here the value you want
    sty.transform = "";
    return ret
}
// for safari to have the good clientWidth
var $fBody = document.body //the element you need to fix
var clientW = get_safe_value($fBody,function(elm){return $fBody.clientWidth})

Es ist wirklich seltsam, denn wenn ich erneut versuche, die clientWidth nach get_safe_value zu erhalten, erhalte ich mit safari einen schlechten Wert, der Getter muss dazwischen liegen sty.transform = "translateZ(1px)"; und liegensty.transform = "";

Die andere Lösung, die definitiv funktioniert, ist

var $fBody = document.body //the element you need to fix
$fBody.style.display = 'none';
var temp = $.body.offsetHeight;
$fBody.style.display = ""
temp = $.body.offsetHeight;

var clientW = $fBody.clientWidth

Das Problem ist, dass Sie den Fokus verlieren und den Status scrollen.

Bormat
quelle
0

Dadurch wird das Neulackieren erzwungen, während Flackern, Basteln vorhandener Elemente und Layoutprobleme vermieden werden ...

function forceRepaint() {
    requestAnimationFrame(()=>{
      const e=document.createElement('DIV');
      e.style='position:fixed;top:0;left:0;bottom:0;right:0;background:#80808001;\
               pointer-events:none;z-index:9999999';
      document.body.appendChild(e);
      requestAnimationFrame(()=>e.remove());  
    });
}
user2026189
quelle
-1

Eine einfache Lösung mit jquery:

$el.html($el.html());

oder

element.innerHTML = element.innerHTML;

Hatte eine SVG, die nicht angezeigt wurde, als sie dem HTML hinzugefügt wurde.

Dies kann hinzugefügt werden, nachdem die SVG-Elemente auf dem Bildschirm angezeigt werden.

Bessere Lösung ist zu verwenden:

document.createElementNS('http://www.w3.org/2000/svg', 'svg');

und mit jQuery:

$(svgDiv).append($(document.createElementNS('http://www.w3.org/2000/svg', 'g'));

Dies wird in Chrome korrekt gerendert.

Yaron Shamir
quelle
Das Problem bei diesem Ansatz besteht darin, dass Sie alle Ereignishandler verlieren, die Sie für das Objekt oder seine Nachkommen registriert haben.
Haqa