#jquery #css
#jquery — jquery — запрос #css
Вопрос:
Я визуально «сворачиваю» некоторые элементы DOM с помощью jQuery (уменьшая их ширину до 0 пикселей и уменьшая их размер) следующим образом:
$(".slideoutmenu").animate({ width: 0, opacity: 0 }, function() { $(this).hide(); });
Ширина этих элементов может варьироваться, но документ правильно оформлен с помощью CSS без установки конкретной ширины.
Обычно, чтобы повторно отобразить эти элементы, я мог бы просто сделать что-то вроде этого:
$(".slideoutmenu").stop().show().css({ width: '', opacity: 1 });
Тем не менее, я хотел бы анимировать эти элементы в обратном порядке (исчезать и расширяться).
Обычно я бы сделал это с чем-то похожим на это:
$(this).children(".slideoutmenu").stop().show().animate({ width: 250, opacity: 1 });
Итак, это очевидная попытка:
$(this).children(".slideoutmenu").stop().show().animate({ width: "", opacity: 1 });
Но это не работает.
В конечном счете, проблема здесь заключается в фиксированном числе «250» в примере выше. Это не работает, потому что ширина является переменной. Мне нужно объединить результат использования пустой строки в установщике css и «анимировать»… но я не могу понять, как это сделать. Я пытался заменить «250» на «undefined», «null», «-1″, » и я искал в Google … безрезультатно.
Я понимаю, что, вероятно, я могу проделать какую-нибудь хитрость с измерением элемента, скрытого от пользователя, — но я не могу представить, что это не довольно распространенная проблема, — поэтому я надеюсь, что есть «стандартный» способ сделать это, или что он встроен каким-то образом, и я просто не знаю об этом.
Спасибо за чтение.
ПОСЛЕДУЮЩИЕ ДЕЙСТВИЯ:
Основываясь на добром ответе Майкла, я собрал небольшой быстрый и грязный плагин, чтобы я мог выполнить это встроенным способом. (может быть, кто-нибудь сможет расширить идею плагина и сделать ее лучше)
Вот плагин:
(function( $ ){
$.fn.cacheCss = function( prop ) {
return this.each(function() {
var $this = $(this);
if (prop instanceof Array)
{
for (var pname in prop)
{
if ($this.data('cssCache-' prop[pname]) != undefined)
continue;
$this.data('cssCache-' prop[pname], $this.css(prop[pname]));
}
}
else
{
if ($this.data('cssCache-' prop) != undefined)
return $this;
$this.data('cssCache-' prop, $this.css(prop));
}
return $this;
});
};
$.fn.revertCss = function(settings, prop, animated) {
if (settings == null)
settings = {};
return this.each(function() {
var $this = $(this);
if (prop instanceof Array)
{
for (var pname in prop)
{
if ($this.data('cssCache-' prop[pname]) != undefined)
settings[prop[pname]] = $this.data('cssCache-' prop[pname]).replace(/px$/, "");
}
}
else
{
if ($this.data('cssCache-' prop) != undefined)
settings[prop] = $this.data('cssCache-' prop).replace(/px$/, "");
}
if (!animated)
return $this.css(settings);
return $this.animate(settings);
});
};
})( jQuery );
И вот как я смог изменить свой код, чтобы использовать его:
Исходная строка, которая задает свойство css:
$(".slideoutmenu").animate({ width: 0, opacity: 0 }, function() { $(this).hide(); });
было заменено на:
$(".slideoutmenu").cacheCss('width').animate({ width: 0, opacity: 0 }, function() { $(this).hide(); });
Теперь «.cacheCss(‘width’)» кэширует значение свойства css перед выполнением анимации.
И строка, в которой мне пришлось «отменить» эти изменения:
$(this).children(".slideoutmenu").stop().show().animate({ width: 250, opacity: 1 });
было заменено этим:
$(this).children(".slideoutmenu").stop().show().revertCss({ opacity: 1 }, 'width', true);
Теперь «.revertCss (…)» будет использовать кэшированные настройки, чтобы вернуть мое свойство width (анимированное!)
Я также заставил плагин принимать массивы, чтобы вы могли делать это тоже:
.cacheCss(['width', 'height'])
и затем:
.revertCss(null, ['width', 'height'], true)
третий параметр определяет, является ли возврат анимированным или нет.
Если у вас есть другие свойства, которые вы хотите анимировать одновременно (как я сделал с «непрозрачностью» в примере ранее), вы можете передать их в качестве первого параметра точно так же, как вы передали бы объект в функцию .animate().
Я уверен, что заглушку можно было бы ЗНАЧИТЕЛЬНО улучшить, но я подумал, что было бы неплохо в любом случае выбросить ее на улицу.
Кроме того, еще один момент — мне пришлось заменить ненужную букву «px» в конце значений css… опять же, я уверен, что, вероятно, есть лучший способ сделать это, но я просто использовал стандартное регулярное выражение.
Комментарии:
1. Я не понимаю, как удаление атрибута width приведет к повторному отображению элемента?
2. Исправлен пример кода для уточнения… но идея здесь такова: элемент начинается без какой-либо определенной фиксированной ширины. Затем ему присваивается ширина 0, чтобы «сжать» его. Тогда, насколько я знаю, нет простого способа анимировать удаление этой новой фиксированной ширины «0».
3. К вашему сведению: значение width по умолчанию равно ‘auto’, поэтому для повторного отображения элемента вам следует использовать
width: 'auto'
Ответ №1:
Вы могли бы сохранить ширину предварительной анимации элемента, используя данные jQuery:
$(".slideoutmenu").each(function(){
$(this).data('width', $(this).css('width'));
$(this).animate({
width: 0,
opacity: 0
});
});
$(".slideoutmenu").each(function(){
$(this).children(".slideoutmenu").stop().animate({
width: $(this).data('width'),
opacity: 1
});
});
Комментарии:
1. 1 Хороший вопрос и правильный ответ. Так или иначе, вы должны сохранить исходную ширину. К сожалению, даже jQuery не может определить, какими были бы размеры, пока элемент не отображается.
2. Еще раз спасибо. Я превратил эту базовую концепцию в быстрый и грязный плагин и опубликовал ее в вопросе. Спасибо. Приветствия.