Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Последовательное выполнение анимаций TweenLite (http://www.flasher.ru/forum/showthread.php?t=190173)

botbot 21.12.2012 15:40

Последовательное выполнение анимаций TweenLite
 
Помогите разобраться, я запутался. Мне нужна очередь, в которую можно класть разные TweenLite, чтобы они выполнялись:некоторые последовательно, некоторые одновременно (пачкой, как будо это один экземпляр TweenLite в очереди, они добавляются одномоментно). После завершения анимации эти TweenLite должны удаляться из очереди.
Т.е. это очередь она одна, глобальная. А добавление экземпляров TweenLite в неё происходит на всём протяжении работы флешки. И вот, если очередь пустая - экземпляр должен сразу запускаться. Если в очереди есть ещё элементы - должен ждать. прока они все выполнятся, а потом выполняться. Я попробовал TimelineLite append() и appendMultiple() (как раз для пачек). Но там, если одна анимация уже прошла и через какое-то время добавляешь вторую - она не запускается.

GBee 21.12.2012 16:00

Так создавайте каждый раз новый таймлайн для пачки. инсерт - распараллеливает, аппенд добавляет в конец анимации.

botbot 21.12.2012 16:10

Нет, мне нужна одна общая очередь. Вообще зря я про пачки написал, они уже другая история.
Сначала мне надо разобраться с одиночными элементами. Вот пример:
Код AS3:

package 
{
        import com.greensock.TimelineLite;
        import com.greensock.TweenLite;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.utils.setTimeout;
 
        /**
        * ...
        * @author Dmitry Minaev
        */

        public class Main extends Sprite
        {
                private var _line: TimelineLite = new TimelineLite();
                private var s: Sprite = new Sprite();
                public function Main():void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                        // рисуем точку, которую будем двигать по таймлайну
                        s.graphics.beginFill(0);
                        s.graphics.drawCircle(0, 0, 3);
                        s.x = 100;
                        s.y = 200;
                        addChild(s);
                        // иммитируем работу очереди
                        // первое действие происходит сразу - точка передигается правее
                        _line.append( new TweenLite(s, 1, { x: 130 } ) );
                        // второе действие происходит когда-то потом, неизвестно когда, эмулируем его задержкой
                        setTimeout(_secondMove, 3000);
                }
                // двигаем точку левее. Вот этот код не срабатывает
                private function _secondMove(): void {
                        _line.append(new TweenLite(s, 1, { x: 80 } ) );
                }
        }
}


GBee 21.12.2012 16:13

ну play() повторно позвать надо, наверно.

botbot 21.12.2012 16:17

Да, вроде заработало, спасибо.

Добавлено через 34 минуты
Всё равно работает неправильно.
Если задать ощутимый промежуток, например
Код AS3:

setTimeout(_secondMove, 8000);

Будет мгновенное перемещение. Это видимо как-то связано с длиной самого таймлайна. Продолжаем копать).

expl 21.12.2012 16:56

Если нужно просто последовательно - я бы в конвеер Потапенко загнал.
А уж если бы потребовалось, чтобы промежутки анимаций накладывались друг на друга и как-то сложнее реагировали - тогда бы уже подключал мозг или внимательнее вчитывался в доки по твину.

botbot 21.12.2012 17:02

Нужно последовательное воспроизведение пачек. В пачке - 1 и более твинов.
Что за конвейер Потапенко? Гугл выводит только левые ссылки, можно ссылку на библиотеку?

GBee 21.12.2012 17:02

Кстати да у эффектов есть параметр задержки и инсертить можно на определенное время.

botbot 21.12.2012 17:22

Пробовал инсерт
Код AS3:

                        var time: Number = _line.duration > _line.currentTime ? _line.duration : _line.currentTime;
                        _line.insert( new TweenLite(s, 2, { x: 130 } ), time );
                        _line.play();

Не работает.

expl 21.12.2012 17:30

Цитата:

Что за конвейер Потапенко? Гугл выводит только левые ссылки, можно ссылку на библиотеку?
Ды да. Надо было сразу ссылку кинуть - из гугла оригинал исчез пару лет назад.

http://www.flasher.ru/forum/blog.php?b=528
(там внизу zip-архив)

Как-то так будет выглядеть:
Код AS3:

_conveyor = new Conveyor();
// Цепочка твинов:
_conveyor.add(tweenTo, [.5, { x: 130 }]);
_conveyor.add(tweenTo, [.5, { x: 140 }]);
_conveyor.add(tweenTo, [1.5, { x: 150 }]);
_conveyor.play();
 
private void tweenTo(duration:Number, vars:Object)
{
    _conveyor.stop();// Тормознули
    vars.onComplete = onTweenComplete;
    TweenLite.to(duration, vars);
}
private void onTweenComplete()
{
    _conveyor.play();// Пошёл следующий твин
}


botbot 22.12.2012 15:52

Вложений: 1
Неа, не работает. То ли в конвейере есть ошибка, то ли я его не так приспособил.
В результате написал своё, которое работает.
Ради спортивного интереса, прилагаю свой рабочий вариант и тот же самый вариант с конвейером. Можешь попробовать его оживить, мн было бы интересно посмотреть.
Там в архиве TweenQueue - вариант с конвейером, TweenQueue2 - работающиё вариант без конвейера. В Main у поля _q достаточно менять тип с TweenQueue2 на TweenQueue для смены теста.

expl 22.12.2012 17:59

Да не, багов то в конвеере нет.
(тесты, конечно хороши для демонстрации багов, а не их отсутствия, но загнать багу в полторы сотни строк, покрытых на 100% всё же сложно)
Есть ньюансы самой логики конвеера.
Впринципе, Ваша реализация в данном случае не сложнее применения конвеера, но, всё-таки, рабочий код:
Код AS3:

package  
{
        import com.greensock.data.TweenLiteVars;
        import com.greensock.TweenLite;
        import com.potapenko.remake.Conveyor;
        import flash.events.Event;
        /**
        * ...
        * @author Dima
        */

        public class TweenQueue
        {
                private var _conv: Conveyor = new Conveyor();
                private var _isPlaying:Boolean = false;
 
                public function TweenQueue() {
                        _conv.addEventListener(Event.COMPLETE, onConvComplete);
                }
 
                private function onConvComplete(event:Event):void {
                        _isPlaying = false;
                }
 
                public function add(target: Object, duration: Number, tween: Object): void {
                        addMany(Vector.<Object>([target]), Vector.<Number>([duration]), Vector.<Object>([tween]));
                }
 
                public function addMany(targets: Vector.<Object>, durations: Vector.<Number>, vars: Vector.<Object>): void {
                        _conv.add(startTweenSet, new TweenSet(targets, durations, vars));
                        if (!_isPlaying) {
                                // Вот эти вот фокусы с проверками, не дошёл ли до конца конвеер и можно ли вызвать play
                                // в боевом коде у нас загнаны внуть конвеера в новую функцию launch()
                                // а выставление _isPlaying = false - в конец функции play()
                                // Для заранее запрограммированных действий оно не надо было, а для очереди оказалось важно
                                _conv.play();
                                _isPlaying = true;
                        }
                }
 
                private function startTweenSet(ts:TweenSet):void {
                        _conv.stop();// Начало асинхронного блока
                        ts.play(resume);
                }
 
                public function resume(): void {
                        _conv.play();// Конец асинхронного блока
                }
        }
}

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

Я так понял - задача - сделать список с плавно разъезжающимися элементами?
Так для этого не нужно очередей.
Просто при добавлении/удалении элемента каждому оставшемуся назначаем твин в точку, в которой он должен быть - 50 объектов - 50 одновременных твинов - ничего страшного.
(при этом плюём с высокой колокольни двигался ли он до этого или нет - TweenLite автоматом прерывает передыдущий твин для объекта, на который вешается следующий)
Всё!
Ну если не считать, что надо применить некоторые хитрости, чтобы одновременное движение и исчезание под этим элементом другого - не выглядело криво (например, у меня они исчезали скейлом в 0 и при уменьшении сдвигались в сторону, но можно и таки ввести ожидание конца исчезновения или ещё что)

botbot 22.12.2012 18:46

Ага, вот тоже думал что надо эвент на окончание конвейера как-то использовать, но уже столько перепробовал до этого, что плюнул).
Цитата:

Сообщение от expl (Сообщение 1111264)
Я так понял - задача - сделать список с плавно разъезжающимися элементами?
Так для этого не нужно очередей.
Просто при добавлении/удалении элемента каждому оставшемуся назначаем твин в точку, в которой он должен быть - 50 объектов - 50 одновременных твинов - ничего страшного.
(при этом плюём с высокой колокольни двигался ли он до этого или нет - TweenLite автоматом прерывает передыдущий твин для объекта, на который вешается следующий)

Неподходит, т.к. есть ещё анимация "всплывания" элемента (которая в тесте как _insert), она отличается от анимации сдвигания элементов вместе. Первая длится две секунды и использует изменение альфы, вторая идет секунду и альфу не трогает. Прерывание первой анимации будет выглядеть некрасиво, да ещё придётся альфу проверять. Так что - только очередь, к сожалению.

Psijic 10.06.2014 19:03

Короче, вот в чем смысл: как они переделали это - nextTween, autoPlay?
Код AS3:

 
var t2Tween:GTween = new GTween(glowFilterPoint, TIMER, {strength: MAX_STRENGTH}, {autoPlay: false, nextTween: t3Tween});
var t1Tween:GTween = new GTween(glowFilterPoint, TIMER, {strength: MIN_STRENGTH}, {nextTween: t2Tween});



Часовой пояс GMT +4, время: 15:02.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.