Статьи

Создайте 3D-фотогалерею Flickr с помощью Flex и Away3D

В этом выпуске я продемонстрирую, как создать динамическую фотогалерею с помощью Flickr API. Чтобы добавить немного изюминки, мы используем возможности Away3D и отображаем фотографии в 3D-среде.

Здесь есть о чем поговорить, так что давайте продолжим!




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

  • Получен ключ API Flickr.
  • Библиотеки ActionScript AS3Flickr и AS3CoreLib загружаются и на них ссылаются из Flex Builder.
  • Файлы междоменной политики Flickr загружаются, чтобы позволить Flex получать доступ к изображениям из удаленных доменов.
  • Поиск Flickr выполняется.
  • Результаты используются для поиска URL-адресов изображений Flickr.
  • Сами изображения загружаются и сохраняются / отображаются.

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

За последние несколько лет среда выполнения Flash достигла впечатляющего прогресса. Широкое развертывание среды выполнения Flash с плагинами Adobe AIR и браузерами, а также повышение производительности в более поздних версиях означает, что Flash имеет очень разнообразную экосистему библиотек и приложений. Он превратился из инструмента анимации в универсальную платформу для разработки игр, бизнес-приложений, 3D-визуализаций, видеоплееров и многого другого.

3D-движки развивались вместе с Flash в течение некоторого времени, превратившись из любопытства в полнофункциональные и даже коммерческие библиотеки. Away3D — это один из самых популярных бесплатных Flash 3D-движков, и недавно была выпущена более короткая и быстрая версия Away3D под названием Away3D Lite . В то время как в Away3D Lite отсутствуют некоторые изюминки, присутствующие в более сложных 3D-движках, его акцент на простоте означает, что он идеально подходит для простого приложения, такого как 3D-фотоальбом.

Вы можете бесплатно скачать копию Away3D Lite 1.0 с этой веб-страницы здесь . Скачайте и распакуйте исходный код движка в удобное место.

Движение камеры в 3D-галерее будет осуществляться с помощью библиотеки Greensock TweenMax , которую вы можете найти на этой странице здесь . Снова загрузите и распакуйте библиотеку в удобное место.

Библиотеки AS3Flickr и AS3CoreLib используются для связи с веб-сервисом Flickr. Вы можете найти подробности об этих библиотеках в статье.
Создайте программу просмотра фотографий, используя Flex и Flickr API .

Создайте новый проект Flex и добавьте библиотеки Away3D Lite, TweenMax, AS3Flickr и AS3CoreLib в путь сборки Flex.

applicationComplete = «appComplete ()»

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

FRAMERATE = «100»

Это устанавливает ограничение частоты кадров для приложения на уровне 100 кадров в секунду. Значение по умолчанию — 24, и увеличение этого параметра сделает приложение более плавным.

width = «600» height = «400» backgroundGradientAlphas = «[1.0, 1.0]» backgroundGradientColors = «[# 000000, # 374040]»

Эти атрибуты определяют размер и цвет фона приложения Flex.

Ваш тег приложения должен выглядеть примерно так:

01
02
03
04
05
06
07
08
09
10
11
<mx:Application
xmlns:mx=»http://www.adobe.com/2006/mxml»
layout=»absolute»
applicationComplete=»appComplete()»
width=»600″
height=»400″
backgroundGradientAlphas=»[1.0, 1.0]»
backgroundGradientColors=»[#000000, #374040]»
frameRate=»100″>
 
</mx:Application>

Добавьте следующие теги в тег Application.

1
2
<mx:TextInput x=»10″ y=»10″ id=»txtSearch»/>
<mx:Button x=»178″ y=»10″ label=»Search» fillAlphas=»[0.9, 0.9, 0.9, 0.9]» click=»{applicationManager.flickrSearch(this.txtSearch.text)}»/>

Мы дадим пользователю возможность искать Flickr и отображать результаты в нашей 3D-галерее фотографий во время выполнения. Эти два тега добавляют текстовое поле, в которое можно ввести поисковую фразу, и кнопку, чтобы начать поиск.

Событие click для кнопки вызывает applicationManager.flickrSearch (this.txtSearch.text) . ApplicationManager будет создан на более поздних этапах, а функция flickrSearch будет содержать код для связи с Flickr и загрузки фотографий.

Добавьте тег Script в тег Application. Именно здесь будет написан код ActionScript.

1
2
3
4
5
<mx:Script>
<![CDATA[
// code goes here
]]>
</mx:Script>

Добавьте следующую переменную внутри тега Script.

1
private var applicationManager:ApplicationManager = null;

Класс ApplicationManager будет отвечать за инициализацию движка Away3D, загрузку изображений Flickr и перемещение камеры. Мы держим ссылку на нее в переменной applicationManager, чтобы кнопка, созданная на шаге 8, могла вызывать функцию flickrSearch.

1
2
3
4
5
Security.loadPolicyFile(«http://api.flickr.com/crossdomain.xml»);
Security.loadPolicyFile(«http://farm1.static.flickr.com/crossdomain.xml»);
Security.loadPolicyFile(«http://farm2.static.flickr.com/crossdomain.xml»);
Security.loadPolicyFile(«http://farm3.static.flickr.com/crossdomain.xml»);
Security.loadPolicyFile(«http://farm4.static.flickr.com/crossdomain.xml»);

Чтобы получить доступ к изображениям на серверах Flickr, необходимо загрузить файлы междоменной политики. Более подробно это описано в статье « Создание средства просмотра фотографий с помощью Flex и API-интерфейса Flickr» .

Добавьте новую функцию с именем appComplete.

1
2
3
4
5
private function appComplete():void
{
applicationManager = new ApplicationManager();
this.addChildAt(new SpriteUIComponent(applicationManager), 0);
}

Эта функция вызывается, когда приложение Flex загружено и инициализировано. Именно здесь мы создаем новый экземпляр класса ApplicationManager и добавляем его в качестве дочернего элемента управления. Обратите внимание, что мы фактически передаем экземпляр класса SpriteUIComponent в функцию addChildAt.

Как вы увидите в следующих шагах, ApplicationManager расширяет один из классов шаблонов из Away3D Lite API. Эти классы шаблонов сами расширяют класс Flex Sprite. Даже если функция addChildAt будет принимать Sprite, во время выполнения будет сгенерировано исключение. Это связано с тем, что только классы, расширяющие класс UIComponent, могут быть добавлены в дочерние элементы управления приложения Flex. Чтобы обойти это ограничение, SpriteUIComponent расширяет класс UIComponent, а затем добавляет Sprite в качестве собственного дочернего элемента.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package
{
    import flash.display.Sprite;
     
    import mx.core.UIComponent;
     
    public class SpriteUIComponent extends UIComponent
    {
        public function SpriteUIComponent(sprite:Sprite)
        {
            super ();
         
            explicitHeight = sprite.height;
            explicitWidth = sprite.width;
         
            addChild (sprite);
        }
    }
}

Как было упомянуто выше, класс SpriteUIComponent расширяет класс UIComponent (то есть он может быть добавлен как дочерний элемент приложения Flex), а затем добавляет предоставленный объект Sprite в качестве своего собственного дочернего элемента.

Импортируйте следующие пакеты

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
import away3dlite.core.base.*;
import away3dlite.core.utils.*;
import away3dlite.loaders.*;
import away3dlite.materials.*;
import away3dlite.primitives.*;
import away3dlite.templates.*;
     
import com.adobe.webapis.flickr.*;
import com.adobe.webapis.flickr.events.*;
     
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.net.*;
     
import com.greensock.*;
     
import mx.collections.*;

Определите класс ApplicationManager как расширение класса BasicTemplate.

1
public class ApplicationManager extends BasicTemplate

Новая функция, включенная в Away3D Lite, — это шаблоны классов. Почти каждое приложение Away3D должно инициализировать те же базовые классы, как камера и представление, а также настроить прослушиватели событий для событий кадра. Эти общие шаги, которые раньше должны были кодироваться каждым разработчиком вручную, теперь выполняются одним из нескольких шаблонных классов. Мы расширим один из этих шаблонных классов, BasicTemplate, с помощью ApplicationManager.

ApplicationManager будет иметь несколько постоянных переменных, которые определяют внешний вид и функции класса.

1
2
3
private static const SEARCH_STRING:String = «landscape»;
private static const MAX_RESULTS:int = 50;
private static const API_KEY:String = «YourFlickrAPIKey»;

Эти три константы относятся к веб-сервису Flickr.

1
2
private static const PHOTO_HEIGHT:Number = 50;
private static const PHOTO_WIDTH:Number = PHOTO_HEIGHT * 1.618;

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

1
2
3
private static const PHOTO_CLOUD_WIDTH:Number = 1000;
private static const PHOTO_CLOUD_HEIGHT:Number = 1000;
private static const PHOTO_CLOUD_DEPTH:Number = 3000;

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

1
private static const NUMBER_PHOTOS:int = 300;

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

1
2
3
private static const CAMERA_JUMP_TIME:Number = 3;
private static const CAMERA_DIST_FROM_PHOTO:Number = 30;
private static const CAMERA_DIST_JUMP_BACK:Number = 100;

Эти переменные определяют движение и скорость камеры при переходе от одной фотографии к другой. Камера будет следовать кривой Безье, при этом начало кривой составляет 30 единиц назад от фотографии, двигаясь к точке 100 единиц назад, а затем заканчивая точкой 30 единиц назад от следующей фотографии.

1
2
[Embed(source=»../media/texture.jpg»)]
protected static const DefaultTexture:Class;

Все изображения, которые будут отображаться, поступают с Flickr, что означает, что будет начальная задержка при получении фотографий. Тем временем будет отображаться изображение, встроенное в SWF-файл, чтобы дать пользователю возможность взглянуть на что-то, кроме белых прямоугольников.

1
2
3
protected var textures:ArrayCollection = new ArrayCollection();
protected var photos:ArrayCollection = new ArrayCollection();
protected var loadedTextures:int = 0;

Изображения, возвращенные из Flickr, хранятся в коллекции текстур. Сетки Away3D Lite, которые будут отображать изображения, хранятся в коллекции фотографий. Переменная loadTextures отслеживает, сколько изображений было загружено из Flickr, поэтому они могут быть сохранены в соответствующей позиции в коллекции текстур.

Добавьте новую функцию с именем onInit.

1
override protected function onInit():void

Как только базовый объект BasicTemplate инициализируется сам, вызывается функция onInit. Именно здесь мы инициализируем расширяющий класс.

1
2
for (var i:int = 0; i < MAX_RESULTS; ++i)
addTexture(Cast.bitmap(DefaultTexture));

Сначала мы создаем коллекцию текстур для использования в наших трехмерных фото-сетках, изначально все с использованием изображения по умолчанию, встроенного в шаге 17. Cast — это служебный класс, предоставляемый Away3D Lite, и здесь мы используем его для преобразования встроенного изображения в BitmapData. объект, который передается в функцию addTexture.

1
2
for (var j:int = 0; j < NUMBER_PHOTOS; ++j)
createPlane();

Теперь мы создаем сетки, которые будут отображать фотоизображения. 3D-фотографии на самом деле будут плоскостями: 2D-прямоугольники без глубины, которые будут смотреть на камеру.

1
flickrSearch(SEARCH_STRING);

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

1
this.debug = false;

Для свойства debug класса BasicTemplate установлено значение false, что отключает экран статистики отладки по умолчанию, который обычно отображается в приложении Away3D Lite.

1
2
3
4
this.camera.x = 0;
this.camera.y = 0;
this.camera.z = 10;
this.camera.lookAt(new Vector3D(0, 0, 0), new Vector3D(0, 1, 0));

По умолчанию класс BasicTemplate размещает камеру вдоль отрицательного конца оси z, оглядываясь назад к началу координат вдоль положительной оси z. Когда плоскости создаются функцией createPlane, они также создаются так, что их фронт направлен вдоль положительной оси z. Это означает, что камера по умолчанию будет смотреть на заднюю поверхность плоскостей.

Как правило, в 3D-приложениях полигоны, расположенные спиной к камере, не видны (это называется отбраковкой лицевой стороны), поэтому, чтобы увидеть плоскости, нам нужно переместить камеру вверх к положительному концу оси z, а затем оглянуться на начало координат вдоль отрицательная ось Z.

1
var randomPhoto:Mesh = photos.getItemAt(Math.random() * (MAX_RESULTS — 1)) as Mesh;

Затем мы получаем ссылку на случайную плоскость, хранящуюся в коллекции фотографий.

1
2
3
this.camera.x = randomPhoto.x;
this.camera.y = randomPhoto.y;
this.camera.z = randomPhoto.z + CAMERA_DIST_FROM_PHOTO;

Камера тогда немного расположена перед этой случайной плоскостью. Это первая фотография, которую пользователь увидит при загрузке приложения.

1
bezierJump();

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

Добавьте новую функцию с именем addTexture.

1
2
3
4
5
6
protected function addTexture(data:BitmapData):void
{
var texture:BitmapMaterial = new BitmapMaterial(data);
texture.smooth = true;
textures.addItem(texture);
}

Функция addTexture, вызываемая onInit на шаге 19, создает новый класс BitmapMaterial (который является классом, который определяет текстуру трехмерных фотографий) с использованием предоставленного BitmapData, устанавливает для его свойства smooth значение true и добавляет его в коллекцию текстур.

Добавьте новую функцию с именем createPlane.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
protected function createPlane():void
{
    var mesh:Plane = new Plane(textures.getItemAt(Math.random() * (MAX_RESULTS — 1)) as BitmapMaterial,
    PHOTO_WIDTH,
    PHOTO_HEIGHT,
    1,
    1,
    false);
             
    mesh.x = Math.random() * PHOTO_CLOUD_WIDTH;
    mesh.y = Math.random() * PHOTO_CLOUD_HEIGHT;
    mesh.z = Math.random() * PHOTO_CLOUD_DEPTH;
             
    scene.addChild(mesh);
             
    photos.addItem(mesh);
}

Функция createPlane, вызываемая onInit на шаге 19, создает новую плоскость, используя размеры, определенные константами на шаге 16 и текстурированные с помощью случайного BitmapMaterial из коллекции текстур, размещает их случайным образом в области «облачного фото» и добавляет их в сцена (объект Away3D из класса BasicTemplate), чтобы они были видны, и добавляет их в коллекцию фотографий, чтобы мы могли легко ссылаться на них позже.

Добавьте две новые функции, одну с именем flickrSearch, а другую с именем onPhotosSearch.

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
public function flickrSearch(search:String):void
{
    var service:FlickrService = new FlickrService(API_KEY);
    service.addEventListener(FlickrResultEvent.PHOTOS_SEARCH, onPhotosSearch);
    service.photos.search(«», search, «any», «», null, null, null, null, -1, «», MAX_RESULTS, 1);
}
 
 
protected function onPhotosSearch(event:FlickrResultEvent):void
{
    for each (var photo:Photo in event.data.photos.photos)
    {
        var imageURL:String = ‘http://static.flickr.com/’ +
        photo.server + ‘/’ +
        photo.id + ‘_’ +
        photo.secret + ‘_m.jpg’;
        var loader:Loader = new Loader();
        loader.contentLoaderInfo.addEventListener(
            Event.COMPLETE,
            function(event:Event):void
            {
                var texture:BitmapMaterial = textures.getItemAt(loadedTextures) as BitmapMaterial;
                texture.bitmap = event.currentTarget.content.bitmapData;
                ++loadedTextures;
                loadedTextures %= MAX_RESULTS;
            }
        );
        loader.load(new URLRequest(imageURL));
}
}

Обе эти функции взяты почти строка за строкой из « Построить просмотрщик фотографий с помощью Flex» и «Flickr API» . Единственное отличие состоит в том, что при загрузке изображений из Flickr их BitmapData назначается свойству bitmap объектов BitmapMaterial, хранящихся в коллекции текстур. Это, в свою очередь, изменяет изображение, отображаемое на плоскостях в трехмерной сцене.

Таким образом, мы можем динамически обновлять отображаемые 3D-фотографии с помощью нескольких вызовов функции flickrSearch, когда пользователь выполняет поиск из основного графического интерфейса.

Функция bezierJump вызывается несколько раз, чтобы перемещать камеру с одной фотографии на другую.

1
protected function bezierJump():void

Кривые Безье — это удобный способ плавного перемещения камеры по кривой, определяемой всего тремя контрольными точками: текущее положение камеры перед фотографией, положение позади камеры и конечный пункт назначения перед новой фотографией.

1
var randomPhoto:Mesh = photos.getItemAt(Math.random() * (MAX_RESULTS — 1)) as Mesh;

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

1
2
3
4
5
TweenMax.to(this.camera,CAMERA_JUMP_TIME,
{
    x: randomPhoto.x,
    y: randomPhoto.y,
    z: randomPhoto.z + CAMERA_DIST_FROM_PHOTO,

Затем мы используем TweenMax для перемещения положения камеры (как определено свойствами x, y и z) прямо перед положением случайно выбранной конечной фотографии …

1
delay: 2,

после начальной задержки в 2 секунды (что означает, что пользователь просматривает каждую фотографию в течение 2 секунд) …

1
2
3
4
5
6
bezier:
[{
    x: this.camera.x,
y: this.camera.y,
z: this.camera.z + CAMERA_DIST_JUMP_BACK
}],

вдоль кривой Безье, на которую влияет точка сразу за текущим положением камеры …

1
2
onComplete: bezierJump
});

рекурсивный вызов функции bezierJump после завершения перемещения.

Таким образом, камера перемещается к фотографии, просматривает ее в течение 2 секунд, переходит к следующей фотографии и снова запускает процесс. В общем, рекурсивный вызов функций твининга — отличный способ создания сценариев перемещения в приложениях Flex.

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

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