Как заставить WebKit перерисовать / перекрасить для распространения изменений стиля? - PullRequest
241 голосов
/ 15 августа 2010

У меня есть тривиальный JavaScript для изменения стиля:

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

Это прекрасно работает с последними версиями FF, Opera и IE, но не работает на последних версиях Chrome и Safari.

Это влияет на двух потомков, которые являются братьями и сестрами.Первый брат обновляется, а второй нет.Дочерний элемент второго элемента также имеет фокус и содержит тег , содержащий указанный выше код в атрибуте onclick .

В Chrome «Инструменты разработчика»”Окно, если я подтолкну (например, уберу галочку и проверим) любой атрибут элемента любой , второй брат обновится до правильного стиля.и программно «подтолкнуть» WebKit на правильные действия?

Ответы [ 26 ]

0 голосов
/ 21 апреля 2016

У меня была проблема с SVG, который исчезал в Chrome для Android, когда ориентация была изменена при определенных обстоятельствах. Приведенный ниже код не воспроизводит его, но является настройкой, которую мы имели.

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>

Спустя полтора дня после того, как тыкал и подталкивал и не был доволен хакерскими решениями, предлагаемыми здесь, я обнаружил, что проблема была вызвана тем фактом, что он, казалось, удерживал элемент в памяти при рисовании нового , Решением было сделать идентификатор linearGradient в SVG уникальным, даже если он использовался только один раз на страницу.

Этого можно достичь разными способами, но для нашего углового приложения мы использовали функцию lodash uniqueId для добавления переменной в область действия:

Угловая директива (JS):

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

Обновления HTML:

Строка 5: <linearGradient ng-attr-id="{{indicatorColourPatternId}}" x1="0" x2="0" y1="0" y2="1">

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

Надеюсь, этот ответ сэкономит кому-то еще несколько дней на то, чтобы разбить их клавиатуру.

0 голосов
/ 20 июня 2012

Это хорошо для JS

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

Но в Jquery, и особенно когда вы можете использовать только $ (document) .ready и не можете связываться с событием .load объекта по какой-либо конкретной причине., сработает следующее.

Вам необходимо получить контейнер OUTER (MOST) объектов / div, а затем удалить все его содержимое в переменную, а затем снова добавить его.Это сделает ВСЕ изменения, сделанные во внешнем контейнере видимыми.

$(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);
}
0 голосов
/ 06 сентября 2012

Я нашел этот метод полезным при работе с переходами

$element[0].style.display = 'table'; 
$element[0].offsetWidth; // force reflow
$element.one($.support.transition.end, function () { 
    $element[0].style.display = 'block'; 
});
0 голосов
/ 12 ноября 2014

Простое решение с помощью jquery:

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

или

element.innerHTML = element.innerHTML;

Был SVG, который не отображался при добавлении в html.

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

Лучшее решение - использовать:

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

, а с jQuery:

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

это отрендеритсяправильно на Chrome.

0 голосов
/ 19 января 2013

хак "display / offsetHeight" не работал в моем случае, по крайней мере, когда он был применен к анимируемому элементу.

У меня было раскрывающееся меню, которое открывалось / закрывалось над содержимым страницы. артефакты оставались в содержимом страницы после закрытия меню (только в браузерах webkit). хак «display / offsetHeight» работал только в том случае, если я применил его к телу, что кажется неприятным.

однако я нашел другое решение:

  1. перед тем, как элемент начинает анимацию, добавьте класс, который определяет "-webkit-backface-visibility: hidden;" на элементе (вы могли бы также использовать встроенный стиль, я думаю)
  2. когда закончите анимацию, удалите класс (или стиль)

это все еще довольно хакерский (он использует свойство CSS3 для принудительного аппаратного рендеринга), но, по крайней мере, он влияет только на рассматриваемый элемент, и работал для меня как в safari, так и в chrome на ПК и Mac.

0 голосов
/ 31 октября 2013

Похоже, это связано с этим: Стиль jQuery не применяется в Safari

Решение, предложенное в первом ответе, хорошо сработало для меня в этих сценариях, а именно: применить и удалитьфиктивный класс к телу после внесения изменений в стиль:

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

Это заставляет сафари перерисовываться.

...