В этом уроке я расскажу вам о создании простого слайдера, который будет прокручивать персональный микросайт. Мы будем использовать класс GreenSock Timeline Lite и продемонстрируем, насколько простым он может сделать ваш рабочий процесс анимации Flash.
Окончательный результат предварительного просмотра
Давайте посмотрим на конечный результат, к которому мы будем стремиться:
Вступление
Время от времени в нашей жизни происходят изменения, которые заставляют нас переосмыслить то, как мы действуем. Это особенно верно в нашем сообществе, где мы ежедневно сталкиваемся с изменениями, которые ставят под сомнение то, как мы строим то, что строим.
Некоторые из этих изменений относятся к худшему, например потеря поддержки .php webservice во Flash ide, но большинство из них к лучшему, например, советы по оптимизации. Время от времени кто-то создает класс, который революционизирует наш взгляд на Flash.
Как Papervision3d для 3d или box2d для физики, теперь есть Timeline для анимации. Этот простой пакет в конечном итоге изменит способ структурирования анимации ActionScript, позволяя создавать бесконечное количество виртуальных временных шкал полностью динамически, предоставляя вам полный контроль над анимацией. Если это не так, вы можете просто добавить любую нужную вам функцию в качестве плагина.
Шаг 1: Где взять
Это самая сложная часть всего урока.
Просто зайдите на http://blog.greensock.com/timelinemax и загрузите копию платформы анимации GreenSock для AS3. Это zip-файл, сохраните его на жестком диске, экспортируйте все в папку и скопируйте папку «com» в корень того места, где вы планируете использовать класс. Все это очень хорошо задокументировано (как вы можете видеть в папке с документами), и у вас даже есть визуализатор легкости.
Шаг 2: Необходимые файлы
Помимо папки com, я создал Main.as, который будет служить классом документа, и TimelineMicrosite.fla для рисования пользовательского интерфейса. Я также скопировал badge made-with-tweenmax-108×54.gif из папки значков, которая находится в zip-файле, который мы скачали ранее.
Шаг 3: Структура
Я не собираюсь концентрироваться на том, как создать пользовательский интерфейс, так как это полностью зависит от вас. Однако я дам вам указания, которым я следовал при создании этого микросайта.
Начните с создания пяти слоев и назовите их: фон, слайды, навигация, игрок и нижний колонтитул.
Шаг 4: Фон и слайды
Фоновый слой содержит простой градиент, больше ничего. Слой слайдов содержит несколько видеороликов. Каждый мувиклип является областью микросайта. В этом случае это home_mc, about_mc, works_mc и contacts_mc. Каждый из них имеет вложенные мувиклипы с именами экземпляров.
Шаг 5: навигация, игрок и нижний колонтитул
Слой навигации имеет мувиклип navigation_mc, внутри которого есть selection_mc. Его структура такая, как показано на рисунке ниже.
Нижний колонтитул — всего лишь импорт значка tweenmax. Вот полное дерево:
Шаг 6: Класс документа
Вы все знаете, как это делается правильно? В случае, если вы забыли вот скелет для класса основного документа:
1
2
3
4
5
6
7
8
9
|
package {
public class Main extends MovieClip{
public function Main():void {
}
}
}
|
Шаг 7: Импорт
Если вы используете 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 {
}
}
}
|
Шаг 8: Основная функция
Вы хотите, чтобы функция основного класса настраивала сцену для вас.
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();
}
|
Шаг 9: переменные слайдов
Мы будем работать с этими переменными:
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;
|
Шаг 10: настройка слайдов
Ядро микросайта. Я использую 3 основных функции этого движка, но сначала представьте себе временную шкалу, как если бы она была реальной.
- Первая функция — insert (), которая вставляет анимацию движения в текущий кадр. Это означает, что каждый раз, когда вы вставляете (), вы добавляете анимацию движения в кадр, с которым работаете, и все вставки запускаются одновременно.
- Второй — append (), этот метод позволяет мне добавлять анимацию к временной шкале в последовательности.
- Третий — 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();
|
Шаг 11: Переменные навигации
Нам нужна только одна переменная, и слайдер должен знать, сколько нужно скользить.
1
|
private var scroll_amount:Number;
|
Шаг 12: Настройка навигации
Теперь мы настроим 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)
}
|
Шаг 13: функция downHandler
Этот метод вызывается, когда мышь находится над перетаскивателем. Он активирует слушателя движения мыши, который сообщает слайдам, куда идти. Это также удаляет любого слушателя, который связан с игроком.
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)
}
|
Шаг 14: функция upHandler
Этот метод вызывается, когда мышь нажата. Он просто останавливает перетаскивание и удаляет слушателя.
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()
}
|
Шаг 15: функция updateNavigationSlides
Мне нравится, как я могу просто «пойти и остановиться» на лейбле или на время в совершенно виртуальной временной шкале:
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)
}
|
Шаг 16: Видео
Использовать анимацию 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)
}
|
Шаг 17: Настройка обновлений слайдера
Поскольку существует два метода навигации по этому микросайту, мы должны убедиться, что один из них не влияет на другой, что впоследствии может привести к ошибкам. Поэтому нам нужно настроить небольшой сеттер, чтобы определить, будет ли он обновлять ползунок или нет в соответствии с анимацией временной шкалы, а не наоборот. Для этого мы создаем 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)
}
}
|
Шаг 18: Обновление ползунка
Эта функция вызывается каждый раз при обновлении события анимации
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
}
|
Шаг 19: Полный код
Эта функция вызывается каждый раз при обновлении события анимации:
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, создавать интерактивные движущиеся графические приложения с ними очень легко.
Этот урок только царапает поверхность того, что может сделать класс. У него очень гибкий рабочий процесс, я все еще прохожу его, но уверяю вас, что, поиграв с этим классом и поняв, как с ним думать, вы поймете мою шумиху.
Надеюсь, вам понравился этот урок, спасибо за чтение!