Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Общие вопросы > Анимация открытия формы


Автор: artsb 14.11.2008, 11:15
Приветствую всех!

Хочу сделать анимацию открытия формы. Использую такой код:
Код

function strpos( haystack, needle, offset){
    var i = (haystack+'').indexOf( needle, offset ); 
    return i===-1 ? false : i;
}

function OpenForm(btn, ids, form)
{
var h = document.getElementById(ids).offsetHeight;
var fh = document.getElementById(form).offsetHeight;
if(strpos(btn.innerHTML, 'Открыть', 0))
{
    document.getElementById(ids).style.borderWidth = "1px";
    for(c=h;c<=fh;c++)
    {
        setTimeout(ids+".style.height='"+c+"px';",4*c);
    }
    btn.innerHTML = '↑ Закрыть форму';
}
else
{
    for(c=h;c>=0;c--)
    {
        setTimeout(ids+".style.height='"+c+"px';if("+c+"==1) document.getElementById('"+ids+"').style.borderWidth = '0px';",4*(fh-c));
    }
    btn.innerHTML = '↓ Открыть форму';
}
}

Страница выглядит так:
Код

<div class="openform" onclick="OpenForm(this, 'divform', 'frm');">
    ↓ Открыть форму
</div>
<div id="divform">
    <!-- Форма -->
</div>

Эта конструкция работает везде, кроме FF (у меня 2.0.0.11). Почему?
И как можно сделать, чтобы если форма ещё не открылась(закрылась) и нажать "Закрыть(Открыть) форму", она сразу же закрывалась(открывалась)? А то сейчас, она сначала откроется(закроется) до конца, а только потом закрывается(открывается).
Ещё, я видел такой код:
Код

setTimeout(ids.id+".style.height='"+c,4*c);

и он работал!
А когда я не указваю единицу измерения мой код не работает. И что за ids.id? У меня оно равно undefined.

Автор: artsb 14.11.2008, 16:44
Вот так, вроде бы, добился результата, о котором спрашивал во втором вопросе:
Код

var tm = new Array(document.getElementById('frm').offsetHeight);
function strpos( haystack, needle, offset){
    var i = (haystack+'').indexOf( needle, offset ); 
    return i===-1 ? false : i;
}
function OpenForm(btn, ids, form)
{
var h = document.getElementById(ids).offsetHeight;
var fh = document.getElementById(form).offsetHeight;
if(strpos(btn.innerHTML, 'Открыть', 0))
{
    if(tm[fh]) for(i=h;i<=fh;i++) clearTimeout(tm[i]);
    document.getElementById(ids).style.borderWidth = "1px";
    for(c=h;c<=fh;c++)
    {
        tm[c] = setTimeout(ids+".style.height='"+c+"px';",2*c);
    }
    btn.innerHTML = '↑ Закрыть форму';
}
else
{
    if(tm[fh]) for(i=h;i<=fh;i++) clearTimeout(tm[i]);
    for(c=h;c>=0;c--)
    {
        tm[fh-c] = setTimeout(ids+".style.height='"+c+"px';if("+c+"<=1) document.getElementById('"+ids+"').style.borderWidth = '0px';",2*(fh-c));
    }
    btn.innerHTML = '↓ Открыть форму';
}
}

Конечно, код кривоват. Если есть более хороший способ - опишите плиз.

Автор: ksnk 14.11.2008, 16:59
Вот, как-то тут на форуме сочинял функцию анимирования...
Код

<script type="text/javascript">
function animate(e,param){
    animate.stop(e, param);
    if(!param) return;
    if(typeof(param)=='number')
        param={_to:param};
    if(!param._from) param._from=parseInt(e.style.height);
    e.animate_to=param._to;
    var
      i = 20,  // 20 <<< вот тут - частота смены кадров.
      disp=(param._from-param._to)/i; 

    e._interval=setInterval(function(){
        try{
            e.style.height=(param._from-=disp)+'px';
        } catch(ee){;}
        if(!i--) animate.stop(e, param);
    },1000/i) // <<< вот тут она - секунда
}
animate.stop=function(e,param){
    if(e. _interval){ // прекращаем анимацию этого объекта.
       e.style.height=e.animate_to+'px';  
       clearInterval(e._interval);
       e._interval=null; 
       if(param.callback) param.callback();
    }
}
</script>
<div oncontextmenu="animate(this,200);return false;" onclick="animate(this,20);" style="height:100px; background:blue;">&nbsp;</div>
<div oncontextmenu="animate(this,200);return false;" onclick="animate(this,20);" style="height:100px; background:red;">&nbsp;</div>
<div oncontextmenu="animate(this,200);return false;" onclick="animate(this,20);" style="height:100px; background:green;">&nbsp;</div>
<div oncontextmenu="animate(this,200);return false;" onclick="animate(this,20);" style="height:100px; background:gray;">&nbsp;</div>
<div oncontextmenu="animate(this,200);return false;" onclick="animate(this,20);" style="height:100px; background:yellow;">&nbsp;</div>

Тестовый стендец, конечно, гюковат. В Опере oncontextmenu не работает, однако проверить функцию позволяет...


Автор: artsb 14.11.2008, 19:37
Спасибо. Попробую.

А вы не знаете, почему мой код в ff не работает?

Автор: ksnk 14.11.2008, 19:54
Вообще-то в том коде уже были правильные поползновения smile Только нужно быть более последовательным и везде поменять 
setTimeout(ids+".style.height='"+c+"px';",2*c) на 
setTimeout("document.getElementById('"+ids+"').style.height='"+c+"px';",2*c)

Автор: artsb 14.11.2008, 23:03
А зачем менять? Ведь и так работает. Или это нужно для ff?

Автор: ksnk 14.11.2008, 23:11
Цитата

 Или это нужно для ff? 

для FF, для Оперы, для Хрома... Для бОльшего соответствия рекомендациям w3c smile

Автор: artsb 14.11.2008, 23:17
Спасибо. Действительно, ff стал понимать.

Вы будете смеяться, но...
Решил переписать скрипт так, чтобы форма именно выезжала сверху вниз (до этого, она просто становилась видисой сверху вниз). Также для этого изменил стиль таблицы position: relative; В цикле меняю положение таблицы, чтобы её нижний край всё время совпадал с нижним краем раскрывающегося div'а.
Код

function OpenForm(btn)
{
var h = document.getElementById('divform').offsetHeight;
var fh = document.getElementById('frm').offsetHeight;
var st = "document.getElementById('divform').style.";
var pos = "document.getElementById('frm').style.top=";
document.getElementById('frm').style.top = "'-"+fh+"px'";

if(strpos(btn.innerHTML, 'Открыть', 0))
{
    if(tm[fh]) for(i=h;i<=fh;i++) clearTimeout(tm[i]);
    document.getElementById('divform').style.borderWidth = "1px";
    for(c=h;c<=fh;c++)
    {
        tm[c] = setTimeout(st+"height='"+c+"px'; "+pos+"'-"+(fh-c)+"px';",2*c);
    }
    btn.innerHTML = '↑ Закрыть форму';
}
else
{
    if(tm[fh]) for(i=h;i<=fh;i++) clearTimeout(tm[i]);
    for(c=h;c>=0;c--)
    {
        tm[fh-c] = setTimeout(st+"height='"+c+"px';if("+c+"<=1) "+st+"borderWidth = '0px'; "+pos+"'-"+(fh-c)+"px';",2*(fh-c));
    }
    btn.innerHTML = '↓ Открыть форму';
}
}

В IE (у меня IE6) не работате smile
И нет консоли, чтобы узнать в какую сторону рыть...
Даже не знаю, может он не понимает relative?

Автор: artsb 15.11.2008, 01:02
Уже разобрался. smile
Код

function OpenForm(btn)
{
var h = document.getElementById('divform').offsetHeight;
var fh = document.getElementById('frm').offsetHeight;
var st = "document.getElementById('divform').style.";
var pos = "document.getElementById('frm').style.top=";
document.getElementById('frm').style.top = '-'+fh+'px';

if(strpos(btn.innerHTML, 'Открыть', 0))
{
    if(tm[fh]) for(i=h;i<=fh;i++) clearTimeout(tm[i]);
    document.getElementById('divform').style.borderWidth = "1px";
    for(c=h;c<=fh;c++)
    {
        tm[c] = setTimeout(st+"height='"+c+"px'; "+pos+"'-"+(fh-c)+"px';",2*c);
    }
    btn.innerHTML = '↑ Закрыть форму';
}
else
{
    if(tm[fh]) for(i=h;i<=fh;i++) clearTimeout(tm[i]);
    for(c=h;c>=0;c--)
    {
        tm[fh-c] = setTimeout(st+"height='"+c+"px'; "+pos+"'-"+(fh-c)+"px'; if("+c+"<=1) "+st+"borderWidth = '0px';",2*(fh-c));
    }
    btn.innerHTML = '↓ Открыть форму';
}
}

Оказывается IE не понимал вот эту строчку:
Код

document.getElementById('frm').style.top = "'-"+fh+"px'";

А именно "'-"+fh+"px'"
Записал так: '-'+fh+'px' и всё заработало.
Единственное, при закрытии формы в IE появляется жёлтый треугольник на панели состояния, значит есть ошибка. В консоли ff написано:
Цитата

Ошибка при анализе значения свойства 'top'. Потерянное объявление.

Что можно сделать?

Автор: Michael.de 15.11.2008, 06:09
artsb, настоятельно советую не работать с объектами как с текстом (это надругательство над ООП smile): замените 5 и 6 строки на:
Код

var st = document.getElementById('divform').style;// это теперь стало св-вом style элемента с id=divform
var pos = document.getElementById('frm').style.top;// а это - style.top эл. с id=frm
ну и соотв. исправить код там, где они дальше используются...

Цитата(artsb @  15.11.2008,  01:02 Найти цитируемый пост)
Оказывается IE не понимал вот эту строчку:
Код
document.getElementById('frm').style.top = "'-"+fh+"px'";
Присоединяюсь к... IE, я её тоже не понимаю smile
В 7 строке Вы конечно же хотите написать -fh+'px'; , да? (а злосчастный 'px' я вообще определил бы сверху глобально как (напр.) var e='px'; --> e - 1byte, 'px' - аж 4.  Соотв.: -fh+e;)

Автор: artsb 15.11.2008, 10:35
Цитата

Присоединяюсь к... IE, я её тоже не понимаю

smile
Цитата

да?

Я хотел получить это: '-555px'
Спасибо за советы.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)