jQuery

индекс
283,92

Анимация в Internet Explorer

Не первый раз сталкиваюсь с этой проблемой, но обычно выручали различные «костыли». Сейчас решил разобраться. Суть в следующем: если в анимации начальное и конечное значение в процентах и разных знаков, объект будет «дёргаться».

Пример:
<style type="text/css">
 #div-1 { position: absolute; width: 100px; height: 100px; background: grey; border: 1px solid black; top: 50%; margin-left: 50%; }
</style>

<script type="text/javascript">
 $(function(){
  $('#link-1').click(function(e){
   e.preventDefault();
   $('#div-1').animate({ left: '25%' });
  });
  $('#link-2').click(function(e){
   e.preventDefault();
   $('#div-1').animate({ left: '-25%' });
  });
 });
</script>

<div id="div-1" style="left: -25%;"></div>
<a href="#" id="link-1">Animate to 25%</a>
<a href="#" id="link-2">Animate to -25%</a>


Дело в том, что, если значение задано в процентах, оно пересчитывается в пикселях. Во всех современных браузерах для этого используется метод document.defaultView.getComputedStyle(), но в IE его конечно же нет. Для него используется метод, описанный здесь:
      // If we're not dealing with a regular pixel number
      // but a number that has a weird ending, we need to convert it to pixels
      if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
        // Remember the original values
        var left = style.left, rsLeft = elem.runtimeStyle.left;

        // Put in the new values to get a computed value out
        elem.runtimeStyle.left = elem.currentStyle.left;
        style.left = ret || 0;
        ret = style.pixelLeft + "px";

        // Revert the changed values
        style.left = left;
        elem.runtimeStyle.left = rsLeft;
      }


Но, как видно из регулярных выражений, пересчет идет только для положительных чисел. Таким образом, если значения разного знака, одно пересчитывается, другое – нет. Отсюда такой «скачок».

Исправить это можно, заменив 829 строку в исходном файле следующей:
   if ( !/^\-?\d+(px)?$/i.test( ret ) && /^\-?\d/.test( ret ) ) {


Результат

* Source code was highlighted with Source Code Highlighter.
+42
17 сентября 2009, 13:25
45

комментарии (25)

+2
kastigar #
Похвально, что решились побороть эту проблему!
Ну или как минимум выяснить в чем причина!
+18
fog #
Так может попробовать пропихнуть этот «патч» в jQuery?
+8
y0ga #
Вчера отписался в трекер, пока тишина.
+6
aubt #
Не совсем в тему, но все же, с анимацией в IE есть еще одна проблема:

Если анимировать с использованием прозрачности элемент, содержащий текст и при этом у пользователя включен ClearType, то по окончании анимации (на самом деле, в процессе тоже, но это не так заметно) текст становится «грубым», т.е. таким, каким он был бы без ClearType. Проблема заключается в том, что jQuery «забывает» удалить атрибут «filter» по окончании анимации (проблема filter:opacity + transparent png в IE хорошо известна).

Решается прмерно следующим образом (с учетом того, что пользовательскую callback-функцию, если она есть, тоже нужно выполнить):

function cleartypeFix() {
if (typeof this.style != 'object')
return;

if (typeof this.style.removeAttribute != 'object') // почему тут не 'function' я объяснить не могу, но работает во всех версиях только так
return;

this.style.removeAttribute(«filter»);
}

$.fn._animate = $.fn.animate;

$.fn.animate = function() {
var args = $.makeArray(arguments);

if (typeof arguments[arguments.length — 1] == 'function') {
var baseCallback = args.pop();

var callback = function() {
baseCallback();
cleartypeFix.apply(this);
}

args.push(callback);
} else
args.push(cleartypeFix);

return $.fn._animate.apply(this, args);
}
0
aubt #
> transparent png
ой… это не к тому совсем.
–18
homm #
Вы молодец, что разобрались и написали репорт. Дальше я конечно не прав, и все такое, но что это делает на хабре? Я почему-то не видел здесь статей людей которые делают действительно большие изменения, а вы просто исправили небольшой баг.
«Вчера отписался пока тишина» конечно шикарно, на все изменения команда видимо должна реагировать максимум через 5 минут.
–11
homm #
Да, забыл совсем. Пиписька на аваторке — это мерзко.
–4
homm #
Удивительно, большенство не согласно даже с этим утверждением :)
Если я не прав, то что это по вашему:
image
0
y0ga #
Статуя Давида, не иначе :)
–5
homm #
Капитан очевидность говорит, что это пиписька от статуи Давида. Это мерзко.
+3
bvu #
Да ладно вам к аватаркам придераться, что не запрещено то разрешено =), вы молодец что такой культурный, но это не повод для споров, статья о другом.

p.s. за Микеланджело обидно… получается человек занимался мерзостью
0
kastigar #
А почему бы нет?
Как минимум эта статья показывает, что нужно копать и разбираться.
Я никогда не понимал людей, которые воспринимают такие вещи (некорректное поведение программы/библиотеки) как должное. Человек не поленился, и в итоге повысил себе экспириенс и улучшил jQuery. Отличный пример некоторым программистам.
–3
homm #
Мне почему-то кажется, что это первый багфикс автора в каком-то проекте. Мне, как человеку сделавшему пару-тройку, кажется, что писать об этом дико. Я могу представить чувства людей, которые на дню их делают по 5 штук. Ну и вы можете представить что будет, если о каждом таком исправлении будет топик.
0
y0ga #
Дело в том, что этот баг давно не давал мне покоя в различных проектах. И если бы мне кто то показал решение раньше, я был бы очень признателен. Поэтому, думаю, данный пост поможет тем, кто с сталкивался с проблемой ранее и, как и я, не находил ответа.
0
bvu #
Этот фикс средствами этого поста дошел до интересующихся быстрее чем будет исправлен разработчиками библиотеки, поэтому кому интересна эта статья думаю вам благодарны.
+1
DnV #
Вы сделали пару-тройку багфиксов для jQuery? Тогда респект. С удовольствием бы почитал о них на хабре.
Что? Не для jQuery? Для самописной CMS? Ну тогда вы правильно делаете, что не пишете об этом :)
+3
hTLK #
Я на Хабр как раз за такими статьями и хожу. Вы ещё спросите, что это делает на главной? :)
–2
1st1 #
ханжа detected.
+1
flair #
Долбанный IE.
–2
aleksandro #
Да ладно вам, идеальных вещей нету.
+2
bvu #
Это своеобразная традиция уже =), так надо =))
+1
flair #
Да. aleksandro, не понимаешь чтоли, так надо ;)
0
darked #
сегодня столкнулся с проблемой IE8 выпадает в дебагер скриптов от такой строчки:
$("#someid").animate({ width:«20px»}, 1000);
Ругается на неправильый параметр… может я что не так написал?
Пока переписал на такое:
$("#someid").css(«width», «20px»);
0
3ds #
Может быть сам jq еще не загрузился?
0
darked #
Да нет, сомневаюсь. Другие браузеры пережёвывают только в путь.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.