Статьи

Создание галереи изображений по категориям с XML и AS3

XML — это формат данных, который хорошо подходит для динамических галерей изображений. Это также очень легко обрабатывать во Flash с AS3. С помощью XML и ActionScript мы собираемся создать галерею изображений, которая будет динамичной и разделена на разные темы.
Мы также узнаем, как использовать очень практичный класс анимации, называемый Tweener, для перемещения значков различных тем и миниатюр. В этом уроке я сосредоточусь на эффективной обработке данных, извлеченных из XML; все модные изображения анимации зависит от вас;)


Сначала я поделюсь, как я настроил свою сцену. Это не фиксированные параметры, поэтому, если вы хотите что-то изменить, это прекрасно. Просто убедитесь, что вы изменили код в этом руководстве, чтобы он соответствовал вашим настройкам (особенно в отношении размера сцены).

Моя сцена 900 х 600 пикселей; Я установил черный цвет фона и частоту кадров 25 кадров в секунду. Хотя SWF-фильм имеет длину всего один кадр, настройка fps важна, потому что это повлияет на анимацию, которую мы собираемся выполнить.


Как вы можете видеть, мы собираемся использовать класс документа, но прежде чем перейти к этому, нам нужно настроить слои и разместить объекты, которые мы собираемся использовать.


Весь наш неподвижный контент будет находиться на слое под названием «BigPic + Title + Arrows» (создайте его сейчас). Первый — это пустой мувиклип под названием Img (имя экземпляра: img); это Мак, в который мы собираемся загрузить каждую большую картинку. Создайте это и поместите в (x: 450, y: 220).


Самый простой способ создать это — использовать большой символ «<». Создайте новое статическое текстовое поле, выберите нужный шрифт и размер, введите «<», а затем используйте команду «Разбить»: выберите символ и нажмите сочетание клавиш CTRL + B или « Изменить»> «Разорвать на части» .

Затем преобразуйте эту форму в мувиклип, назовите его «Стрелка» и измените точку регистрации на центр левой стороны (где указывает стрелка).



Нам понадобятся два из них на сцене, поэтому перетащите еще одного из библиотеки. Отразить один из них по горизонтали ( Изменить> Трансформировать> Отразить по горизонтали ). Поместите левый в (x: 0, y: 220) и присвойте ему имя экземпляра ‘prevArrow’. Правильный должен идти в (x: 900, y: 220), и иметь имя экземпляра ‘nextArrow’.


Создайте динамическое текстовое поле шириной 900px (чтобы вы могли использовать заголовки сколько угодно). Поместите его в (x: 0, y: 440) и присвойте ему имя экземпляра ‘txtField’. Я использовал шрифт Arial в 16pt, выровненный по центру; не забудьте вставить это!



Это просто маленькие элементы дизайна для значков тем и миниатюр, чтобы они исчезали на границах сцены. Создайте прямоугольник шириной 30px, высотой 130px (без обводки — только заливка), и, оставив выделенный прямоугольник, перейдите на панель «Цвет» и измените стиль заливки со сплошного на линейный. Установите оба цвета на черный, но установите один из них на 0% альфа.



Теперь преобразуйте прямоугольник в мувиклип (точка рег .: левый верхний угол, название: обложка). Сделайте то же самое, что и со стрелками: перетащите два экземпляра на сцену и переверните один из них. В каждом случае альфа-сторона 0% должна быть ближе к центру сцены.

Разместите их по бокам сцены: (слева: (x: 0, y: 470); справа: (x: 900, y: 470)).

Хорошо, мы закончили с этим слоем.


Под нашим существующим слоем создайте новый под названием «themes + thumbs». На этом слое создайте пустой мувиклип для значков тем (имя: «Темы», рег. Точка: верхний левый угол, имя экземпляра: «темы», х: 0, у: 470) и еще один для миниатюр (имя: smallPics, точка рег .: левый верхний угол, имя экземпляра: smallPicsMc, x: 0, y: 510).

Нам нужно создать еще несколько символов, которые не начинаются на сцене, но мы создадим их в ActionScript позже.


Создайте пустой мувиклип (имя: «SmallPicButton», рег. Точка: верхний левый угол). Этот MC будет содержать один эскиз; у нас будет много экземпляров этого символа, поэтому мы создадим каждый из них во время выполнения.

Чтобы сделать это, мы должны экспортировать этот символ для ActionScript: на панели «Библиотека» щелкните этот символ правой кнопкой мыши и выберите « Свойства» . Установите флажок «Экспорт для ActionScript», затем установите для класса значение «SmallPicButton». Базовый класс остается как есть.


После того, как вы нажмете ОК, дважды щелкните по этому символу в библиотеке, чтобы войти в режим редактирования, затем перейдите на панель «Действия» — сейчас мы напишем некоторый код. Мы собираемся убедиться, что этот MovieClip ведет себя как правильная кнопка.


Скопируйте и вставьте этот код в панель «Действия»:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
//if the cursor is over the symbol we change its alpha to 1
function rollOver(e:MouseEvent):void{
    alpha = 1;
}
  
//if the cursor just moved off the symbol, we change its alpha to 0.5
function rollOut(e:MouseEvent):void{
    alpha = 0.5;
}
  
//register the event listeners to run the above functions
addEventListener(MouseEvent.ROLL_OVER, rollOver);
addEventListener(MouseEvent.ROLL_OUT, rollOut);
  
//this guarantees that the cursor changes to the little pointing hand over the symbol
buttonMode = true;
useHandCursor = true;
  
//set its initial alpha to 0.5
alpha = 0.5;

Этот символ будет использоваться для значков, по которым вы можете щелкнуть, чтобы выбрать другую тематическую категорию — какой сюрприз :). Это похоже на SmallPicButton, поэтому для его создания повторите шаги 8-10 — только измените имя и класс на ThemeButton вместо SmallPicButton. Вам не нужно ничего менять в коде.


Итак, мы создали два слоя: верхний — BigPic + заголовок + стрелки, нижний — темы + превью.

На слое BigPic + Title + Arrows у нас есть img, prevArrow, nextArrow, txtField и две закрывающие пластины по бокам снизу.

На слое themes + thumbs у нас есть два пустых фрагмента ролика: Themes, которые будут содержать все значки тем, и smallPicsMc, который будет содержать все эскизы.

В библиотеке у нас есть символы SmallPicButton и ThemeButton с правильно установленными опциями связывания.

Я надеюсь, что ты со мной так далеко. Очень важно правильно именовать символы, потому что в противном случае следующий код не будет работать.


Итак, мы закончили с Flash-частью. Перед началом кодирования нам нужно сделать две вещи: поместить все изображения в удобную структуру папок и создать наш XML-файл.

В той же папке, что и ваш FLA-файл, создайте папку с именем «pics». В этой папке создайте два других: один из них называется «маленький» (чтобы содержать миниатюры), а другой — «большой» (чтобы содержать большие изображения). В обеих папках у вас будет одинаковая структура папок: одна папка для каждой темы.



Каждая из ваших миниатюр должна иметь то же имя, что и соответствующая большая картинка. Важно, чтобы в «маленькой» папке все изображения были высотой 80 пикселей, чтобы соответствовать нашему интерфейсу. Размер больших изображений не важен, потому что мы собираемся изменить их размер, прежде чем добавлять их на сцену, но имейте в виду, что максимальный размер изображения, которое мы сможем показать, составляет 840 на 420 пикселей.



Создайте новый текстовый файл в любой программе файлового менеджера и назовите его «pics.xml».

Вы можете редактировать этот файл с помощью любого текстового редактора, такого как Блокнот, но гораздо проще редактировать его с помощью Flash.


Я расскажу вам только то, что нам нужно для правильной работы XML, если вы хотите узнать больше об XML, вы можете найти множество учебных пособий здесь, в Activetuts + (например , Dru Kepple ) или на других страницах в Интернете — и не забудь: гугл твой друг;)

В этом XML-файле мы собираемся описать структуру папок (и изображения в ней), чтобы Flash мог читать и интерпретировать ее.

1
2
3
4
5
<pics>
    <theme name=»The name of the theme»>
        <pic title=»The title of the picture» filename=»FilenameOfThePicture.jpg» />
    </theme>
</pics>

Таким образом, фото является корневым элементом, и все идет между тегами фото. Если вы хотите добавить новую тему, просто скопируйте и вставьте существующий элемент темы и измените его атрибуты. Если вы хотите добавить новое изображение в одну из тем, просто скопируйте и вставьте в соответствующие теги рис. И измените его атрибуты. Атрибут name тега theme должен совпадать с именем папки, потому что именно здесь мы и скажем Flash искать файл. И имя, и имя файла чувствительны к регистру.


Нажмите « Файл»> «Создать» и выберите «Файл ActionScript». Скопируйте и вставьте следующий код.

1
2
3
4
5
6
7
package {
      
    public class Gallery extends MovieClip
    {
          
    }
}

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


Первая функция, которую мы начинаем писать, это конструктор. Это основная функция всей программы, и она будет первым кодом, запускаемым при запуске SWF.

Скопируйте и вставьте этот код между фигурными скобками, которые идут вместе со строкой «Public Class Gallery extends MovieClip»:

1
2
3
4
public function Gallery():void
{
              
}

Первое, что нам нужно сделать, это загрузить созданный нами XML-файл. Мы сделаем это с помощью класса URLLoader, который находится в пакете flash.net .

Чтобы использовать его, нам нужно импортировать этот пакет. На самом деле, давайте просто импортируем каждый пакет, который нам понадобится. Скопируйте и следующий код и вставьте его выше строки «MovieClip галереи открытого класса»:

1
2
3
4
5
6
import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.text.*;
import flash.xml.*;
import caurina.transitions.*;

Помните, что импорт всегда будет в начале кода (после части ‘package {‘), объявление нелокальных переменных будет перед конструктором, а все функции будут после конструктора.

Чтобы Flash импортировал этот пакет «caurina.transitions», этот пакет должен находиться в той же папке, что и FLA и ваш класс документов. Итак, откройте мой исходный zip-файл и скопируйте папку \ caurina \ в папку вашего проекта.

После того, как мы импортировали нужные нам пакеты, мы можем объявить и создать новый экземпляр нашей переменной URLLoader:

1
var urlLoader:URLLoader = new URLLoader();

(Поместите этот код в функцию конструктора.)

Теперь мы можем указать Flash загрузить наш XML-файл и добавить прослушиватель событий в urlLoader:

1
2
3
4
5
public function Gallery():void
{
    urlLoader.load(new URLRequest(«pics.xml»));
    urlLoader.addEventListener(Event.COMPLETE, urlLoadComplete);
}

Поэтому, когда urlLoader завершит загрузку pics.xml, Flash запустит функцию urlLoadComplete, которая будет следующей нашей записью …


Когда файл XML загружен, нам нужно поместить всю информацию, содержащуюся в нем, в объект XML. Затем, чтобы использовать это, нам также понадобится объект XMLList:

1
2
3
//these are non-local variables
var xml:XML;
var list:XMLList;

После того, как конструктор вставил это:

1
2
3
4
5
protected function urlLoadComplete(e:Event):void
{
    xml = new XML(urlLoader.data);
    list = new XMLList(xml.children());
}

Теперь все дочерние узлы элемента pics, то есть все теги темы, находятся в переменной списка . Если вы хотите увидеть, что там, вставьте ‘trace (list);’ после второй строки функции urlLoadComplete.


Для этого нам понадобится цикл for. Итак, сначала нам нужно объявить переменную цикла для правильной работы цикла и массив для объектов themeButton:

1
2
3
//these are non-local variables
var themeButtons:Array = new Array();
var i:int;

После двух существующих строк функции urlLoadComplete мы должны начать писать наш цикл:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
for(i = 0; i< list.length(); i++)
{
    //we create a new instance of the ThemeButton symbol
    var themeButton:MovieClip = new ThemeButton();
    //we set the content of the textfield to the name of the theme
    themeButton.txt.text = list[i].@name;
    //we set the name of the textfield instance to be the same as its content
    themeButton.name = list[i].@name;
    //we add the click eventListener
    themeButton.addEventListener(MouseEvent.CLICK, themeClick);
    //we place the clips in a row with 10px padding
    themeButton.x = i*(themeButton.width+10);
    //we put the movieclip in the themes MC
    themes.addChild(themeButton);
    //…and in the themeButtons array also
    themeButtons[i] = themeButton;
}

После этого мы помещаем все кнопки в MC тем, а затем выравниваем их по центру сцены:

1
2
//change 450 to match the width of your stage
themes.x = 450-themes.width/2;

Вы можете проверить свой фильм сейчас и посмотреть, работает ли он. Вы должны увидеть кнопки вашей темы (работающие как кнопки) в строке …


Для того, чтобы перемещать themeButtons, мы добавляем mouseLove eventListener на сцену; вставьте это в конструктор:

1
stage.addEventListener(MouseEvent.MOUSE_MOVE, slideTheme);

Перед тем как написать функцию slideTheme, мы объявим еще одну нелокальную переменную:

1
2
//this will help calculate the position to which the themes should slide
var ratio:Number;

В функции slideTheme мы будем использовать класс Tweener, в частности, одну функцию этого класса, называемую addTween (). (Вы можете прочитать все об этом классе здесь .)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
protected function slideTheme(e:MouseEvent):void
{
    if(mouseY>470 && mouseY< 600)//we move the themeButtons if the cursor is the themeButtons-thumbs area
    {
        ratio = themes.width/850;
        //we move the themes MC if it is longer then the stage
        if(themes.width > 900)
        {
            //if it is longer, the position depends on the cursor’s X position
            Tweener.addTween(themes, {x: (450-themes.width/2)-(mouseX-450)*ratio, time: 1});
        else
        {
            //otherwise, we align it to the center of the stage
            Tweener.addTween(themes, {x: (450-themes.width/2), time: 1});
        }
    }
}

Проверь свой фильм; MC тем должен двигаться (если он длиннее сцены).


Прежде чем мы начнем писать функцию, нам нужно объявить еще несколько нелокальных переменных:

01
02
03
04
05
06
07
08
09
10
11
var j:int;
//if we click on one of the theme icons, it will be contained in this variable
var themeClicked:MovieClip = new ThemeButton();
//the list of the pictures in a particular theme
var picsList:XMLList;
var smallPicSource:Array;
var bigPicSource:Array;
//this will contain all the thumbs
var smallPics:Array;
//this will contain the titles of the pictures in the selected theme
var picTitles:Array;

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

01
02
03
04
05
06
07
08
09
10
protected function themeClick(e:MouseEvent):void
{
    //the whole function shall be executed only if the theme you selected is not the same as you selected just before
    if (themeClicked != e.currentTarget)
    {
         //makes the smallPicsMc invisible — it’s on the stage, but it contains nothing yet
        smallPicsMc.visible = false;
        //removes the mouseMove eventListener — added afterwards
        stage.removeEventListener(MouseEvent.MOUSE_MOVE, slideSmallPics);
        j = 0;

Если на сцене было изображение (в img Mc), оно будет удалено, а текстовое поле заголовка будет очищено:

1
2
3
4
5
if(img.numChildren > 0)
{
    img.removeChildAt(0);
}
titleTxt.text = «»;

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

1
2
3
4
5
6
if (themeClicked != null){ //if it’s not the first time you click on a theme
    themeClicked.alpha = 0.5;
}
themeClicked = MovieClip(e.currentTarget);
themeClicked.alpha = 1;
themeClicked.removeEventListener(MouseEvent.ROLL_OUT, themeClicked.rollOut);

Следующая часть этой функции будет фильтровать содержимое списка только по элементам выбранной вами темы:

01
02
03
04
05
06
07
08
09
10
//loop goes through the themeButtons array
for (i=0; i< themeButtons.length; i++)
{
    //if the name of the themeButton you clicked on matches the current item in the array
    if (e.currentTarget.name == themeButtons[i].name)
    {
        //we make picsList contain all the <pic> elements from that theme
        picsList = new XMLList(list[i].pic);
    }
}

Если smallPicsMc содержит какие-либо элементы (то есть вы уже щелкнули по какой-либо теме), мы удалим их все.

1
2
3
4
5
6
7
if (smallPicsMc.numChildren != 0)
{
    for(i=smallPicsMc.numChildren; i>0; i—)
    {
        smallPicsMc.removeChildAt(i-1);
    }
}

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
if (picsList.length() > 0)// if the picsList XMLList has at least 1 element in it
{
    //we create new arrays
    //(if they have already been created, we clear their contents)
    smallPicSource = new Array();
    bigPicSource = new Array();
    smallPics = new Array();
    picTitles = new Array();
      
    //loop through picsList
    for(i=0; i< picsList.length(); i++)
    {
        //now we create the source path of the images
        smallPicSource[i] = «pics/small/» + e.currentTarget.name +»/» + picsList.@filename[i];
        bigPicSource[i] = «pics/big/» + e.currentTarget.name +»/» + picsList.@filename[i];
        //put the titles in the picTitles array
        picTitles[i] = picsList.@title[i];
    }
                      
    j = -1;
    //this will eventually load the small pics
    smallPicLoad(null);

Если в выбранной теме нет картинок, мы сообщаем пользователю, что она скоро появится.

01
02
03
04
05
06
07
08
09
10
else
{
    //if img had a picture in it…
    if(img.numChildren > 0)
    {
        img.removeChildAt(0);
    }
    //then we write, instead of the title, that this theme is coming soon
    titleTxt.text = «Coming soon…»;
}

Эта функция делает то же самое, что и функция slideTheme, но с smallPicsMc вместо MC тем.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
protected function slideSmallPics(e:MouseEvent):void
{
    if(mouseY>470 && mouseY< 600){
        ratio = smallPicsMc.width/850;
        if(smallPicsMc.width > 900)
        {
            Tweener.addTween(smallPicsMc, {x: (450-smallPicsMc.width/2)-(mouseX-450)*ratio, time: 1});
        }
        else
        {
            Tweener.addTween(smallPicsMc, {x: (450-smallPicsMc.width/2), time: 1});
        }
    }
}

Эта функция загружает большие пальцы в массиве smallPics и отображает процесс загрузки.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
protected function smallPicLoad(e:Event):void
{
    if (j < smallPicSource.length-1)
    {
        j++;
        //it tells the user which thumbs are loading now
        loadTxt.text = «Loading thumbs: » + (j+1).toString() +» / » + (smallPicSource.length).toString();
        //creates a Loader object in the array
        smallPics[j] = new Loader();
        //loads the next element of the smallPicSource array
        smallPics[j].load(new URLRequest(smallPicSource[j]));
        //if it’s loaded, call this function again
        smallPics[j].contentLoaderInfo.addEventListener(Event.COMPLETE, smallPicLoad);
    }
    else
    {
        //if all of the elements of the array are loaded, call the smallPicComplete function
        smallPicComplete();
    }
}

Это довольно сложно, поэтому я дам более подробное объяснение. Он загружает эскизы один за другим; это как цикл, но я делаю цикл «вручную», почти рекурсивно. Это решение было необходимо, потому что я хотел, чтобы миниатюры появлялись одновременно. Напомним, что ранее мы установили видимость smallPicsMc в false, чтобы мы могли раскрывать миниатюры вместе.

[/исходный код]


Сначала мы должны объявить две другие нелокальные переменные:

1
2
var bigClicked:String;//the source of the big picture
var cpi:uint;//it stands for CurrentPictureIndex: it’s the index of the picture which is shown

Это первая часть функции, в которой мы загружаем первое большое изображение, затем заполняем массив smallPicButtons и smallPicsMc.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
protected function smallPicComplete(e: Event = null):void
{
    bigClicked = bigPicSource[0];//sets the source of the big picture to the first one in the array
    loadPic(bigPicSource[0]);//calls the loadPic function with the same parameter
    cpi = 0;
      
    var smallPicButtons:Array = new Array();//this will store the created smallPicButtons
      
    for(i=0; i< smallPics.length; i++)
    {
        smallPicButtons[i] = new SmallPicButton();//we create a new instance of the SmallPicButton object in the smallPicButtons array
        smallPicButtons[i].addChild(smallPics[i]);//we put the matching element of the smallPics array to the smallPicButtons array
  
        if (i>0)
        {
            smallPicButtons[i].x = smallPicButtons[i-1].x+smallPicButtons[i-1].width+20;//beginning with the second element, we place them in a line as we did it with the themeButtons
        }
        smallPicButtons[i].data = bigPicSource[i];
  
        smallPicsMc.addChild(smallPicButtons[i]);
        smallPicButtons[i].addEventListener(MouseEvent.CLICK, click);// we add a click eventListener to that button
    }

Это вторая половина этой функции. Здесь мы раскрываем миниатюры и стрелки навигации (и устанавливаем их готовыми к навигации).

01
02
03
04
05
06
07
08
09
10
11
smallPicsMc.visible = true;
smallPicsMc.alpha = 0;
Tweener.addTween(smallPicsMc, {alpha:1, time:1});
stage.addEventListener(MouseEvent.MOUSE_MOVE, slideSmallPics);
  
nextArrow.addEventListener(MouseEvent.CLICK, nextPic);
prevArrow.addEventListener(MouseEvent.CLICK, prevPic);
prevArrow.visible = false;
nextArrow.visible = true;
prevArrow.buttonMode = true;
nextArrow.buttonMode = true;

Прокомментировав строки, в которых мы вызываем функцию, которую мы еще не написали, вы сможете проверить свой фильм, щелкнуть по кнопкам темы и показать и сдвинуть миниатюры.


Эта функция загружает следующее изображение в строке. Это вызвано нажатием на следующую стрелку.

1
2
3
4
5
6
7
8
protected function nextPic(e:Event = null):void
{
    if (cpi < bigPicSource.length-1)//if there is one more picture in the bigPicSource array
    {
        cpi++;
        loadPic(bigPicSource[cpi]);
    }
}

Эта функция загружает предыдущее изображение в строке. Это обратная функция nextPic, которая запускается нажатием на предыдущую стрелку.

1
2
3
4
5
6
7
8
protected function nextPic(e:Event = null):void
{
    if (cpi > 0)//if it’s not the first picture we want to load
    {
        cpi—;
        loadPic(bigPicSource[cpi]);
    }
}

Еще одна нелокальная переменная для объявления:

1
var bigPic:String;

Эта функция вызывается нажатием на миниатюру:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
protected function click(e:MouseEvent):void
{
    //if this picture is not the same as shown already
    if (bigClicked != e.currentTarget.data)
    {
        if(img.numChildren > 0) //if there is already something in the img MC
        {
            img.removeChildAt(0);
        }
        titleTxt.text = «»;
        //we store the source path of the big picture of the thumbnail
        bigClicked = e.currentTarget.data;
        bigPic = e.currentTarget.data;
        loadPic(bigPic);
    }
}

Эта функция загружает большую картинку и заботится о навигационных стрелках.

Сначала мы должны объявить Loader, который загрузит картинку …

1
var bigLoader:Loader;

… а теперь актуальная функция:

1
2
3
4
5
6
7
protected function loadPic(bigPic):void
{
    if(img.numChildren > 0) //if this is not the first picture we load
    {
        img.removeChildAt(0);
    }
    titleTxt.text = «»;

Затем мы создаем объект Loader, запускаем загрузку и добавляем несколько слушателей.

1
2
3
4
bigLoader = new Loader();
bigLoader.load(new URLRequest(bigPic));
bigLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
bigLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, bigLoadComplete);

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

1
2
3
4
5
6
7
for (i=0; i< bigPicSource.length; i++)
{
    if (bigPic == bigPicSource[i]) //if the source path of the images match
    {
        cpi = i;
    }
}

Спрятаны или показаны стрелки навигации, зависит от значения cpi.

1
2
3
4
5
6
7
8
9
if (cpi > 0) //if this is not the first picture
    prevArrow.visible = true;
if (cpi == 0) //if this is the first picture
    prevArrow.visible = false;
              
if (cpi == bigPicSource.length-1) //if this is the last one
    nextArrow.visible = false;
if (cpi < bigPicSource.length-1) //if this is not the last one
    nextArrow.visible = true;

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

1
2
3
4
5
protected function progress(e: ProgressEvent): void
{
    //we write the percentage of the loading progress into the loadTxt dynamic textfield
    loadTxt.text = «Loading picture: » + Math.floor((e.bytesLoaded / e.bytesTotal) * 100) + «%»;
}

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

01
02
03
04
05
06
07
08
09
10
11
12
protected function bigLoadComplete(e:Event):void
{
    //the loading has ended and we don’t need this text till the next loading
    loadTxt.text = «»;
    //we use cpi to get the title that belongs to this picture
    titleTxt.text = picTitles[cpi];
  
    //we create a new bitmap object, and we put the picture in it
    var bitmap:Bitmap = e.target.content;
    bitmap.smoothing = true;
    var origWidth:Number = bitmap.width;
    var origHeight:Number = bitmap.height;

Мы создаем несколько новых переменных, чтобы мы могли правильно изменить размер изображения. Они должны идти внутри функции bigLoadComplete ().

01
02
03
04
05
06
07
08
09
10
11
var maxWidth = 840;
var maxHeight = 420;
// — it depends on your layout
  
//these will store the new size of the image
var newWidth:Number;
var newHeight:Number;
  
//this variable is the ratio of the sides of the image
//we will do the resizing with the help of this ratio
var ratio:Number = origWidth / origHeight;

Эта часть будет устанавливать новый размер изображения.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
//if one of the sides of the picture is longer than the space
if (origWidth > maxWidth || origHeight > maxHeight)
{
    //if the width-difference is bigger then the height-difference (portrait)
    if (maxWidth — origWidth > maxHeight — origHeight)
    {
        newHeight = maxHeight;
        newWidth = Math.round (newHeight * ratio);
    }
    else //if the orientation is landscape or shaped like a square
    {
        newWidth = maxWidth;
        newHeight = Math.round(newWidth / ratio);
    }
}
else //if the picture is smaller then the space
{
    //the new size will be the same as the original
    newHeight = origHeight;
    newWidth = origWidth;
}

Мы устанавливаем свойства растрового изображения, а затем раскрываем его на сцене.

01
02
03
04
05
06
07
08
09
10
bitmap.width = newWidth;
bitmap.height = newHeight;
bitmap.x = -bitmap.width/2;
bitmap.y = -bitmap.height/2;
//(since the img MC is in the center we should align the bitmap to the center of the MC)
              
img.addChild(bitmap);
              
img.alpha = 0;
Tweener.addTween(img, {alpha:1, time:1});

Все в порядке! Мы сделали сейчас! Я надеюсь, что вы могли понять идеи в этой статье (и вам тоже понравилось).

Спасибо за чтение!

Наконец, вот и весь код:

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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
package {
      
    import flash.display.*;
   import flash.events.*;
    import flash.net.*;
   import flash.text.*;
    import flash.xml.*;
    import caurina.transitions.*;
      
    public class Gallery extends MovieClip
    {
        var urlLoader:URLLoader = new URLLoader();
        var xml:XML;
        var list:XMLList;
        var picsList:XMLList;
          
        var themeButtons:Array = new Array();
        var themeClicked:MovieClip = new ThemeButton();
          
        var i:int;
        var j:int;
          
        var smallPicSource:Array;
        var bigPicSource:Array;
        var smallPics:Array;
        var picTitles:Array;
          
        var bigLoader:Loader;
          
        var bigPic:String;
        var bigClicked:String;
          
        var cpi:uint;
          
        var ratio:Number
                  
        public function Gallery():void
        {
            urlLoader.load(new URLRequest(«pics.xml»));
            urlLoader.addEventListener(Event.COMPLETE, urlLoadComplete);
              
            stage.addEventListener(MouseEvent.MOUSE_MOVE, slideTheme);
        }
          
        protected function urlLoadComplete(e:Event):void{
            xml = new XML(urlLoader.data);
            list = new XMLList(xml.children());
            for(i = 0; i 0)
                    img.removeChildAt(0);
                titleTxt.text = «»;
              
                if (themeClicked != null){
                    themeClicked.alpha = 0.5;
                    themeClicked.addEventListener(MouseEvent.ROLL_OUT, themeClicked.rollOut);
                }
                themeClicked = MovieClip(e.currentTarget);
                themeClicked.alpha = 1;
                themeClicked.removeEventListener(MouseEvent.ROLL_OUT, themeClicked.rollOut);
                for (i=0; i0; i—)
                        smallPicsMc.removeChildAt(i-1);
                }
                  
                if (picsList.length() > 0)
                {
                    smallPicSource = new Array();
                    bigPicSource = new Array();
                    smallPics = new Array();
                    picTitles = new Array();
                      
                    for(i=0; i 0)
                        img.removeChildAt(0);
                    titleTxt.text = «Coming soon…»;
                }
            }
        }
          
        protected function smallPicLoad(e:Event):void
        {
            if (j < smallPicSource.length-1)
            {
                j++;
                loadTxt.text = «Loading thumbs: » + (j+1).toString() +» / » + (smallPicSource.length).toString();
                smallPics[j] = new Loader();
                smallPics[j].load(new URLRequest(smallPicSource[j]));
                smallPics[j].contentLoaderInfo.addEventListener(Event.COMPLETE, smallPicLoad);
            }else
            {
                smallPicComplete();
            }
        }
          
        protected function smallPicComplete(e: Event = null):void{
            bigClicked = bigPicSource[0];
            loadPic(bigPicSource[0]);
            cpi = 0;
                      
            var smallPicButtons:Array = new Array();
              
            for(i=0; i0)
                    smallPicButtons[i].x = smallPicButtons[i-1].x+smallPicButtons[i-1].width+20;
                smallPicButtons[i].data = bigPicSource[i];
                  
                smallPicsMc.addChild(smallPicButtons[i]);
                smallPicButtons[i].addEventListener(MouseEvent.CLICK, click);
            }
              
            smallPicsMc.visible = true;
            smallPicsMc.alpha = 0;
            Tweener.addTween(smallPicsMc, {alpha:1, time:1});
            stage.addEventListener(MouseEvent.MOUSE_MOVE, slideSmallPics);
              
            nextArrow.addEventListener(MouseEvent.CLICK, nextPic);
            prevArrow.addEventListener(MouseEvent.CLICK, prevPic);
            prevArrow.visible = false;
            nextArrow.visible = true;
            prevArrow.buttonMode = true;
            nextArrow.buttonMode = true;
        }
          
        protected function nextPic(e:Event = null):void
        {
            if (cpi < bigPicSource.length-1)
            {
                cpi++;
                loadPic(bigPicSource[cpi]);
            }
        }
          
        protected function prevPic(e:Event = null):void
        {
            if (cpi > 0)
            {
                cpi—;
                loadPic(bigPicSource[cpi]);
            }
        }
          
        protected function loadPic(bigPic):void
        {
            if(img.numChildren > 0)
                img.removeChildAt(0);
            titleTxt.text = «»;
              
            bigLoader = new Loader();
            bigLoader.load(new URLRequest(bigPic));
            bigLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
            bigLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, bigLoadComplete);
            for (i=0; i 0)
                prevArrow.visible = true;
            if (cpi == 0)
                prevArrow.visible = false;
              
            if (cpi == bigPicSource.length-1)
                nextArrow.visible = false;
            if (cpi < bigPicSource.length-1)
                nextArrow.visible = true;
        }
          
        protected function progress(e: ProgressEvent): void {
            loadTxt.text = «Loading picture: » + Math.floor((e.bytesLoaded / e.bytesTotal) * 100) + «%»;
        }
          
        protected function bigLoadComplete(e:Event):void{
            loadTxt.text = «»;
            titleTxt.text = picTitles[cpi];
              
            var bitmap:Bitmap = e.target.content;
            bitmap.smoothing = true;
            var origWidth:Number = bitmap.width;
            var origHeight:Number = bitmap.height;
              
            var maxWidth = 840;
            var maxHeight = 420;
              
            var newWidth:Number;
            var newHeight:Number;
              
            var ratio:Number = origWidth / origHeight;
              
            if (origWidth > maxWidth || origHeight > maxHeight)
            {
                if (maxWidth — origWidth > maxHeight — origHeight)
                {
                    newHeight = maxHeight;
                    newWidth = Math.round(newHeight * ratio);
                }else
                {
                    newWidth = maxWidth;
                    newHeight = Math.round(newWidth / ratio);
                }
            }else
            {
                newHeight = origHeight;
                newWidth = origWidth;
            }
              
            bitmap.width = newWidth;
            bitmap.height = newHeight;
            bitmap.x = -bitmap.width/2;
            bitmap.y = -bitmap.height/2;
              
            img.addChild(bitmap);
              
            img.alpha = 0;
            Tweener.addTween(img, {alpha:1, time:1});
        }
        protected function click(e:MouseEvent):void
        {
            if (bigClicked != e.currentTarget.data){
                if(img.numChildren > 0)
                    img.removeChildAt(0);
                titleTxt.text = «»;
                bigClicked = e.currentTarget.data;
                bigPic = e.currentTarget.data;
                loadPic(bigPic);
            }
        }
          
        protected function slideSmallPics(e:MouseEvent):void
        {
            if(mouseY>470 && mouseY< 600){
                ratio = smallPicsMc.width/850;
                if(smallPicsMc.width > 900)
                {
                    Tweener.addTween(smallPicsMc, {x: (450-smallPicsMc.width/2)-(mouseX-450)*ratio, time: 1});
                }
                else
                {
                    Tweener.addTween(smallPicsMc, {x: (450-smallPicsMc.width/2), time: 1});
                }
            }
        }
          
        protected function slideTheme(e:MouseEvent):void
        {
            if(mouseY>470 && mouseY< 600){
                ratio = themes.width/850;
                if(themes.width > 900)
                {
                    Tweener.addTween(themes, {x: (450-themes.width/2)-(mouseX-450)*ratio, time: 1});
                }
                else
                {
                    Tweener.addTween(themes, {x: (450-themes.width/2), time: 1});
                }
            }
        }
    }
}