Статьи

Создайте микросайт слайдера с помощью GreenSock Timeline Lite

В этом уроке я расскажу вам о создании простого слайдера, который будет прокручивать персональный микросайт. Мы будем использовать класс GreenSock Timeline Lite и продемонстрируем, насколько простым он может сделать ваш рабочий процесс анимации Flash.


Давайте посмотрим на конечный результат, к которому мы будем стремиться:


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

Некоторые из этих изменений относятся к худшему, например потеря поддержки .php webservice во Flash ide, но большинство из них к лучшему, например, советы по оптимизации. Время от времени кто-то создает класс, который революционизирует наш взгляд на Flash.

Как Papervision3d для 3d или box2d для физики, теперь есть Timeline для анимации. Этот простой пакет в конечном итоге изменит способ структурирования анимации ActionScript, позволяя создавать бесконечное количество виртуальных временных шкал полностью динамически, предоставляя вам полный контроль над анимацией. Если это не так, вы можете просто добавить любую нужную вам функцию в качестве плагина.


Это самая сложная часть всего урока.

Просто зайдите на http://blog.greensock.com/timelinemax и загрузите копию платформы анимации GreenSock для AS3. Это zip-файл, сохраните его на жестком диске, экспортируйте все в папку и скопируйте папку «com» ​​в корень того места, где вы планируете использовать класс. Все это очень хорошо задокументировано (как вы можете видеть в папке с документами), и у вас даже есть визуализатор легкости.


Помимо папки com, я создал Main.as, который будет служить классом документа, и TimelineMicrosite.fla для рисования пользовательского интерфейса. Я также скопировал badge made-with-tweenmax-108×54.gif из папки значков, которая находится в zip-файле, который мы скачали ранее.


Я не собираюсь концентрироваться на том, как создать пользовательский интерфейс, так как это полностью зависит от вас. Однако я дам вам указания, которым я следовал при создании этого микросайта.

Начните с создания пяти слоев и назовите их: фон, слайды, навигация, игрок и нижний колонтитул.


Фоновый слой содержит простой градиент, больше ничего. Слой слайдов содержит несколько видеороликов. Каждый мувиклип является областью микросайта. В этом случае это home_mc, about_mc, works_mc и contacts_mc. Каждый из них имеет вложенные мувиклипы с именами экземпляров.


Слой навигации имеет мувиклип navigation_mc, внутри которого есть selection_mc. Его структура такая, как показано на рисунке ниже.

Нижний колонтитул — всего лишь импорт значка tweenmax. Вот полное дерево:


Вы все знаете, как это делается правильно? В случае, если вы забыли вот скелет для класса основного документа:

1
2
3
4
5
6
7
8
9
package {
 
    public class Main extends MovieClip{
         
        public function Main():void {
 
        }
    }
}

Если вы используете fdt, flash builder, eclipse с flex sdk или flash development, вы, вероятно, импортируете их автоматически, но если вы используете Flash ide для кодирования, то, кроме моего сочувствия, вам также потребуется импортировать:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
package {
 
    import flash.display.MovieClip;
    import flash.events.MouseEvent;
    import flash.geom.Rectangle;
    import com.greensock.TweenLite;
    import com.greensock.TimelineMax;
    import com.greensock.events.TweenEvent;
    import com.greensock.easing.Linear;
     
    public class Main extends MovieClip{
         
        public function Main():void {
 
        }
    }
}

Вы хотите, чтобы функция основного класса настраивала сцену для вас.

1
2
3
4
5
6
7
public function Main():void {
    //This will setup the animation of the slides
    setupSlides();
     
    //This will setup the slides navigation
    setupNavigation();
}

Мы будем работать с этими переменными:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
//An array that will store the slides for easier access
private var slides:Array;
 
//A Number that will set a margin for the slides
private var offset:Number
 
//A timeline that will store the slide tweens
private var slideline:TimelineMax
 
//A timeline that will store each slide tween
private var singlelines:TimelineMax;
 
//This timeline groups the main animation timeline and the single slides animations timeline
private var timeline:TimelineMax;

Ядро микросайта. Я использую 3 основных функции этого движка, но сначала представьте себе временную шкалу, как если бы она была реальной.

  1. Первая функция — insert (), которая вставляет анимацию движения в текущий кадр. Это означает, что каждый раз, когда вы вставляете (), вы добавляете анимацию движения в кадр, с которым работаете, и все вставки запускаются одновременно.
  2. Второй — append (), этот метод позволяет мне добавлять анимацию к временной шкале в последовательности.
  3. Третий — appendMultiple (), этот метод позволяет передать массив анимаций для одновременного запуска, последовательности или задержки, в зависимости от того, как я установил параметры.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
private function setupSlides():void {
        //populates the slides
        slides = new Array(home_mc, about_mc, works_mc, contacts_mc)
         
        //sets the offset
        offset = 110
         
        //instantiates the timeline for the main slides
        slideline = new TimelineMax()
         
        //instantiates the timeline for each of the slides
        singlelines = new TimelineMax();
         
        //instatiates the timeline that will contain the other 2 timelines
        timeline = new TimelineMax();
         
        var i:int = 0
        while (i < slides.length) {
            //sets an index so i know in wich position the current slide is
            slides[i].index = i
            //aligns the slides
            slides[i].x = i * 650 + offset
            //creates the tweens and appends them to a timeline
            slideline.insert(TweenLite.to(slides[i], 3, { x:slides[i].x — 650*3,ease:Linear.easeNone } ))
            //increments the i for the next loop
            i++
        }
         
        //initial states
        home_mc.text_mc.alpha = 0
        home_mc.image_mc.alpha = 0
        about_mc.text_mc.alpha = 0
        works_mc.text_mc.alpha = 0
        works_mc.image1_mc.alpha = 0
        works_mc.image2_mc.alpha = 0
        works_mc.image3_mc.alpha = 0
        contacts_mc.text_mc.alpha = 0
         
        //sequencing the animations
        singlelines.append(TweenLite.to(home_mc.text_mc, 0.2, { alpha:1 } ))
        singlelines.append(TweenLite.to(home_mc.image_mc, 0.2, { alpha:1 } ), -0.1)
        singlelines.append(TweenLite.to(about_mc.text_mc, 0.2, { alpha:1 } ), 0.5)
        singlelines.append(TweenLite.to(works_mc.text_mc, 0.2, { alpha:1 } ),0.15)
        singlelines.append(TweenLite.to(works_mc.image1_mc, 0.2, { alpha:1 } ), 0.05)
        singlelines.append(TweenLite.to(works_mc.image2_mc, 0.2, { alpha:1 } ), 0.05)
        singlelines.append(TweenLite.to(works_mc.image3_mc, 0.2, { alpha:1 } ), 0.05)
        singlelines.append(TweenLite.to(contacts_mc.text_mc, 0.2, { alpha:1 } ),0.55)
        //makes both timelines active at the same time.
        timeline.appendMultiple([slideline, singlelines]);
        //starts timeline paused
        timeline.pause();

Нам нужна только одна переменная, и слайдер должен знать, сколько нужно скользить.

1
private var scroll_amount:Number;

Теперь мы настроим scroll_amount и свяжем несколько слушателей с некоторыми функциями.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
private function setupNavigation():void {
         
        //sets the scroll amount
        scroll_amount = navigation_mc.width-navigation_mc.selection_mc.width
         
        navigation_mc.selection_mc.buttonMode = true
         
        //on Mouse Down calls downHandler function
        navigation_mc.selection_mc.addEventListener(MouseEvent.MOUSE_DOWN, downHandler);
         
        //this listener is set on stage in case you drag out
        stage.addEventListener(MouseEvent.MOUSE_UP, upHandler)
         
        //play, pause and rewind event handler associations
        play_bt.addEventListener(MouseEvent.CLICK, playSlides)
        pause_bt.addEventListener(MouseEvent.CLICK, pauseSlides)
        rewind_bt.addEventListener(MouseEvent.CLICK, rewindSlides)
         
    }

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

01
02
03
04
05
06
07
08
09
10
private function downHandler(e:MouseEvent):void {
    //makes sure that the slider update is off before making it draggable
    setUpdateSlider(false)
    //adds a listener to mouse movement so every time the mouse moves it updates the navigation slides
    stage.addEventListener(MouseEvent.MOUSE_MOVE, updateNavigationSlides)
    //starts drag of the slider
    navigation_mc.selection_mc.startDrag(false, new Rectangle(0, 0, scroll_amount, 0));
    //updates navigation 1 time
    updateNavigationSlides(null)
}

Этот метод вызывается, когда мышь нажата. Он просто останавливает перетаскивание и удаляет слушателя.

1
2
3
4
5
6
private function upHandler(e:MouseEvent):void {
    //removes the listener on mouse movements
    stage.removeEventListener(MouseEvent.MOUSE_MOVE, updateNavigationSlides)
    //stops the drag
    navigation_mc.selection_mc.stopDrag()
}

Мне нравится, как я могу просто «пойти и остановиться» на лейбле или на время в совершенно виртуальной временной шкале:

1
2
3
4
5
private function updateNavigationSlides(e:MouseEvent):void {
    //goes to that part in time,
    // the calculation is a simple proportion fraction between the x position of the selection and the current timeline duration
    timeline.gotoAndStop(navigation_mc.selection_mc.x*timeline.totalDuration/scroll_amount)
}

Использовать анимацию ActionScript в качестве видео так же просто, как установить временную шкалу и вызвать play (), pause () или reverse ().

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
//sets slider to be updated and resumes tween
private function playSlides(e:MouseEvent):void {
    timeline.timeScale = 1
    timeline.play();
    setUpdateSlider(true)
}
//removes slider to be updated and pauses tween
private function pauseSlides(e:MouseEvent):void {
    setUpdateSlider(false)
}
//sets the timescale and reverses the tween
private function rewindSlides(e:MouseEvent):void {
    timeline.timeScale = 5
    timeline.reverse();
    setUpdateSlider(true)
}

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

01
02
03
04
05
06
07
08
09
10
11
12
13
private function setUpdateSlider(bool:Boolean) {
    //case false, checks to see if there is a listener, if true pauses animation and removes tween
    if (timeline.hasEventListener(TweenEvent.UPDATE) && bool == false) {
        timeline.pause()
        timeline.removeEventListener(TweenEvent.UPDATE,updateNavigationSlider)
    }
     
    //case true, checks to see if there’s a listener, if false plays animation
    if (!timeline.hasEventListener(TweenEvent.UPDATE) && bool == true) {
        timeline.resume();
        timeline.addEventListener(TweenEvent.UPDATE,updateNavigationSlider)
    }
}

Эта функция вызывается каждый раз при обновлении события анимации

1
2
3
4
private function updateNavigationSlider(e:TweenEvent):void {
    //does exactly the same as updateNavigationSlides, but inverts the fraction so that updates the selection_mc position
    navigation_mc.selection_mc.x=timeline.currentTime*scroll_amount/timeline.totalDuration
}

Эта функция вызывается каждый раз при обновлении события анимации:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
    package {
     
    import flash.display.MovieClip;
    import flash.events.MouseEvent;
    import flash.geom.Rectangle;
    import com.greensock.TweenLite;
    import com.greensock.TimelineMax;
    import com.greensock.events.TweenEvent;
    import com.greensock.easing.Linear;
 
    public class Main extends MovieClip{
         
        public function Main():void {
            //This will setup the animation of the slides
            setupSlides();
             
            //This will setup the slides navigation
            setupNavigation();
        }
         
    ////////////////SLIDES/////////////////
         
        //An array that will store the slides for easier access
        private var slides:Array;
         
        //A Number that will set a margin for the slides
        private var offset:Number
         
        //A timeline that will store the slide tweens
        private var slideline:TimelineMax
         
        //A timeline that will store each slide tween
        private var singlelines:TimelineMax;
         
        //This timeline groups the main animation timeline and the single slides animations timeline
        private var timeline:TimelineMax;
         
        private function setupSlides():void {
            //populates the slides
            slides = new Array(home_mc, about_mc, works_mc, contacts_mc)
             
            //sets the offset
            offset = 110
             
            //instantiates the timeline for the main slides
            slideline = new TimelineMax()
             
            //instantiates the timeline for each of the slides
            singlelines = new TimelineMax();
             
            //instaciates the timeline that will contain the other 2 timelines
            timeline = new TimelineMax();
             
            var i:int = 0
            while (i < slides.length) {
                //sets an index so i know in wich position the current slide is
                slides[i].index = i
                //aligns the slides
                slides[i].x = i * 650 + offset
                //creates the tweens and appends them to a timeline
                slideline.insert(TweenLite.to(slides[i], 3, { x:slides[i].x — 650*3,ease:Linear.easeNone } ))
                //pauses the slideline so it won’t start automatically
                 
                //increments the i for the next loop
                i++
            }
             
            //initial states
            home_mc.text_mc.alpha = 0
            home_mc.image_mc.alpha = 0
            about_mc.text_mc.alpha = 0
            works_mc.text_mc.alpha = 0
            works_mc.image1_mc.alpha = 0
            works_mc.image2_mc.alpha = 0
            works_mc.image3_mc.alpha = 0
            contacts_mc.text_mc.alpha = 0
             
            //sequencing the animations
            singlelines.append(TweenLite.to(home_mc.text_mc, 0.2, { alpha:1 } ))
            singlelines.append(TweenLite.to(home_mc.image_mc, 0.2, { alpha:1 } ), -0.1)
            singlelines.append(TweenLite.to(about_mc.text_mc, 0.2, { alpha:1 } ), 0.5)
            singlelines.append(TweenLite.to(works_mc.text_mc, 0.2, { alpha:1 } ),0.15)
            singlelines.append(TweenLite.to(works_mc.image1_mc, 0.2, { alpha:1 } ), 0.05)
            singlelines.append(TweenLite.to(works_mc.image2_mc, 0.2, { alpha:1 } ), 0.05)
            singlelines.append(TweenLite.to(works_mc.image3_mc, 0.2, { alpha:1 } ), 0.05)
            singlelines.append(TweenLite.to(contacts_mc.text_mc, 0.2, { alpha:1 } ),0.55)
             
            timeline.appendMultiple([slideline, singlelines]);
            timeline.pause();
             
        }
         
        private function gotoLabel(label:String):void {
            slideline.tweenTo(label,{ease:Linear.easeInOut});
        }
         
         
         
         
    //////////////////NAVIGATION/////////////////////
 
        private var scroll_amount:Number;
         
        private function setupNavigation():void {
             
            //sets the scroll ammount
            scroll_amount = navigation_mc.width-navigation_mc.selection_mc.width
             
            navigation_mc.selection_mc.buttonMode = true
             
            //on Mouse Down calls downHandler function
            navigation_mc.selection_mc.addEventListener(MouseEvent.MOUSE_DOWN, downHandler);
             
            //this listener is set on stage in case you drag out
            stage.addEventListener(MouseEvent.MOUSE_UP, upHandler)
             
            //play, pause and rewind event handler associations
            play_bt.addEventListener(MouseEvent.CLICK, playSlides)
            pause_bt.addEventListener(MouseEvent.CLICK, pauseSlides)
            rewind_bt.addEventListener(MouseEvent.CLICK, rewindSlides)
             
        }
         
        private function downHandler(e:MouseEvent):void {
            //makes sure that the slider update is off before making it draggable
            setUpdateSlider(false)
            //adds a listener to mouse movement so every time the mouse moves it updates the navigation slides
            stage.addEventListener(MouseEvent.MOUSE_MOVE, updateNavigationSlides)
            //starts drag of the slider
            navigation_mc.selection_mc.startDrag(false, new Rectangle(0, 0, scroll_amount, 0));
            //updates navigation 1 time
            updateNavigationSlides(null)
        }
 
        private function upHandler(e:MouseEvent):void {
            //removes the listener on mouse movements
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, updateNavigationSlides)
            //stops the drag
            navigation_mc.selection_mc.stopDrag()
        }
         
        private function updateNavigationSlides(e:MouseEvent):void {
            //goes to that part in time, the calculation is a simple proportion fraction between the x position of the selection and the current timeline duration
            timeline.gotoAndStop(navigation_mc.selection_mc.x*timeline.totalDuration/scroll_amount)
        }
         
        //sets slider to be updated and resumes tween
        private function playSlides(e:MouseEvent):void {
            timeline.timeScale = 1
            timeline.play();
            setUpdateSlider(true)
        }
        //removes slider to be updated and pauses tween
        private function pauseSlides(e:MouseEvent):void {
            setUpdateSlider(false)
        }
        //sets the timescale and reverses the tween
        private function rewindSlides(e:MouseEvent):void {
            timeline.timeScale = 5
            timeline.reverse();
            setUpdateSlider(true)
        }
         
         
        private function setUpdateSlider(bool:Boolean) {
            //case false, checks to see if there is a listener, if true pauses animation and removes tween
            if (timeline.hasEventListener(TweenEvent.UPDATE) && bool == false) {
                timeline.pause()
                timeline.removeEventListener(TweenEvent.UPDATE,updateNavigationSlider)
            }
             
            //case true, checks to see if there’s a listener, if false plays animation
            if (!timeline.hasEventListener(TweenEvent.UPDATE) && bool == true) {
                timeline.resume();
                timeline.addEventListener(TweenEvent.UPDATE,updateNavigationSlider)
            }
        }
         
        private function updateNavigationSlider(e:TweenEvent):void {
            //does exactly the same as updateNavigationSlides, but inverts the fraction so that updates the selection_mc position
            navigation_mc.selection_mc.x=timeline.currentTime*scroll_amount/timeline.totalDuration
        }
    }
}

Будь то Timeline Lite или Timeline Max, создавать интерактивные движущиеся графические приложения с ними очень легко.

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

Надеюсь, вам понравился этот урок, спасибо за чтение!