0,0
рейтинг
16 января 2010 в 19:44

Загрузчик фотографий как vkontakte на Flex

Неделю назад мои знания action script ограничивались тем, как добавить событие onclick на баннер перед загрузкой в баннерную сеть. В качестве загрузчика файлов я использовал swfupload, и очень не хотел влезать внутрь swf-ника и разбираться в коде. Мне не нравится flash, я ни разу не дизайнер и теряюсь, когда вижу все эти слои, кадры, инструменты для рисования звездочек и motion guides.

Потом я наткнулся на эту эту потрясающе-красивую штуку, и узнал, что есть flex. И что flex — это круто, потому что даже такой супер-начинающий как я, с нуля за несколько дней смог написать загрузчик фотографий с предпросмотром, ресайзом на клиенте и upload-баром, примерно такой, какой используется на сайте vkontakte.ru.

Есть три причины, из-за которых я решил использовать flash для загрузки фотографий. Это FileReference, FileReferenceList и flash.display.Bitmap. В 10-й версии флеш плеера у FileReference появилась функция load(), с помощью которой можно просматривать выбранные фотографии в ролике локально без загрузки на сервер. FileReferenceList позволяет в файловом диалоге с помощью shift-а выбрать сразу несколько фотографий. Bitmap делает ресайз картинок перед отправкой на сервер. Все это нельзя сделать на чистом javascript-е.

Итак, пишем загрузчик фотографий как vkontakte на flex (пошаговое пособие для совсем начинающих).

Прежде всего нужно поставить flex builder 3 (здесь есть версия, которой можно пользоваться 60 дней) и обновить флеш плеер до 10-й версии. Создадим новый flex project. Тип приложения — web application, тип сервера — none. Сразу же нужно исправить компилятор проекта, для этого выбираем Project->Properties->Flex Compiler и меняем параметр «Require Flash Player version» на 10.0.0. Если это не сделать, функция load() у объекта FileReference не будет работать.

Сначала расположим все необходимые элементы на странице, а потом будем писать скрипт. Зададим фиксированные размеры рабочей области (тегу application), внутрь поместим panel, внутрь панели — TileList, ProgressBar и ControlBar с кнопками «Выбрать фотографии», «Начать загрузку» и «Очистить». После TileList добавим HBox c элементами ProgressBar и кнопкой «отмена». Вот что получится.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="540" height="465">

<mx:Panel title="Загрузка фотографий"
  paddingTop="10" paddingLeft="10" paddingBottom="10" paddingRight="10"
  width="100%" height="100%">

  <mx:TileList
    alternatingItemColors="[#FFFFFF,#CCCCCC,#AAAAAA]"
    verticalScrollPolicy="on"
    columnWidth="120" columnCount="4" rowHeight="110" rowCount="3" />

  <mx:HBox horizontalAlign="center" width="100%">
    <mx:ProgressBar />
    <mx:Button label="Отмена" />
  </mx:HBox>
    
  <mx:ControlBar horizontalAlign="right">
    <mx:Button label="Выбрать фотографии" />
    <mx:Button label="Начать загрузку" />
    <mx:Button label="Очистить" />
  </mx:ControlBar>
</mx:Panel>
</mx:Application>


* This source code was highlighted with Source Code Highlighter.


Скроем ProgressBar и будем показывать его только когда нажимаем на кнопку «начать загрузку (visible =»false"). Сделаем enabled=«false» у кнопок «начать загрузку» и «очистить» (они будут активны только когда список фотографий непуст). Добавим id-шники ко всем важным элементам.

Добавим тег <mx:Script> и будем в нем писать код. Подключим flash.net.FileReferenceList и mx.collections.ArrayCollection и заведем главную глобальную переменную photos типа ArrayCollection.
<mx:Script>
  <![CDATA[

    import flash.net.FileReferenceList;
    import mx.collections.ArrayCollection;
    
    [Bindable]
    private var photos:ArrayCollection = new ArrayCollection;  

  ]]>
</mx:Script>


* This source code was highlighted with Source Code Highlighter.

[Bindable] означает, что переменная photos может быть связана с другими элементами. Укажем ее в качестве dataProvider-а к TileList, и тогда все изменения в массиве photos будут автоматически отражаться в TileList.

Добавим глобальную переменную frList типа FileReferenceList. На клик по кнопке «Выбрать фотографии» добавим функцию selectPhotos. Для того, чтобы отлавливать событие, когда в frList.browse() в файловом диалоге завершается выбор фоток, у frList нужно указать addEventListener(Event.COMPLETE,addPhotos). Необязательным параметром функции frList.browse() служит массив объектов типа FileFilter, там можно задать маску для названий файлов. Наконец напишем функцию addPhotos, которая будет перебирать все файлы, выбранные в frList.fileList и добавлять их в массив photos. Вот что получится.
import mx.events.CollectionEvent;
import flash.net.FileReferenceList;
import mx.collections.ArrayCollection;
    
[Bindable]
private var photos:ArrayCollection = new ArrayCollection;  
private var frList:FileReferenceList = new FileReferenceList;

private function init():void
{
  frList.addEventListener(Event.SELECT,addPhotos);
}    

private function selectPhotos():void
{
  frList.browse([new FileFilter("Изображения jpeg","*.jpg;*.jpeg")]);
}

private function addPhotos():void
{
  for (var i:uint = 0; i < frList.fileList.length; i++)
  {
    var elem:Object = new Object;
    elem.fr:FileReference = FileReference(frList.fileList[i]);
    photos.addItem(elem);
  }
}

* This source code was highlighted with Source Code Highlighter.

Нужно, чтобы кнопки «Начать загрузку» и «Отмена» были активны только когда массив photos не пуст. В Функцию инициализации добавим обработчик:
photos.addEventListener(CollectionEvent.COLLECTION_CHANGE,function()
{
  startUploadButton.enabled = (photos.length>0);
  clearPhotosButton.enabled = (photos.length>0);
});

* This source code was highlighted with Source Code Highlighter.

Теперь напишем itemRenderer для нашего TileList. itemRenderer отвечает за то, каким образом показывать элемент массива photos в ячейке TileList. Вынесем код itemRenderer-а в отдельный MXML компонент. Сделаем File->New->MXML Component с именем photoThumb, based on Canvas width 120 height 110. В TileList добавим свойство itemRenderer со значением photoThumb.

Теперь будем писать код компонента. Сделаем, чтобы при наведении на каждую фотографию на ней возникала панель с управляющими кнопочками (у нас пока будет только одна кнопка «удалить»). Соответствующий элемент массива, к которому вызывается itemRenderer, находится в глобальной переменной data. У нас каждый такой элемент — это объект с единственным свойством fr типа FileReference. Соответственно, чтобы в ячейке указать имя файла, нужно написать <mx:Label text="{data.fr.name}"/>. Публичные функции родителя вызываются через parentDocument. Вот полный код itemRenderer-а, бекграунд у родительского Canvas-а задан для того, чтобы корректно обрабатывался rollOver.
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
  width="120" height="110"
  backgroundColor="#FFFFFF" backgroundAlpha="0"
  rollOver="{controls.visible=true}" rollOut="{controls.visible=false}">

  <mx:VBox width="100%" height="75" y="5" horizontalAlign="center">
    <mx:Image source="{data.fr.data}" maxWidth="100" maxHeight="75" horizontalAlign="center" verticalAlign="middle" />
  </mx:VBox>
  <mx:Label text="{data.fr.name}" width="100%" truncateToFit="true" bottom="0" textAlign="center" />

  <mx:VBox id="controls" visible="false" y="65" right="10" horizontalAlign="right">
    <mx:Button label="X" click="parentDocument.clearPhoto(data)" fontSize="6" width="30" height="15" />
  </mx:VBox>
</mx:Canvas>


* This source code was highlighted with Source Code Highlighter.

Все работает кроме того, что при выборе больших фоток они не успевают загрузиться, и TileList их не показывает. Чтобы это исправить, добавим в функцию addPhotos обновление TileList после загрузки каждой фотографии:
private function addPhotos(e:Event):void
{
  for (var i:uint = 0; i < frList.fileList.length; i++)
  {
    var elem:Object = new Object;
    elem.fr = FileReference(frList.fileList[i]);
    elem.fr.load();
    elem.fr.addEventListener(Event.COMPLETE,refreshThumb);
    photos.addItem(elem);
  }
}
    
private function refreshThumb(e:Event):void
{
  photosList.invalidateList();
}


* This source code was highlighted with Source Code Highlighter.

Добавим простые функции удаления всех фоток и удаления выбранной фотки, используя методы removeAll, removeItemAt и getItemIndex у класса ArrayCollection. При этом функция, которая вызывается из itemRender-а, должна быть публичной.
private function clearPhotos():void
{
  photos.removeAll();
}
    
public function clearPhoto(data:Object):void
{
  photos.removeItemAt(photos.getItemIndex(data));
}

* This source code was highlighted with Source Code Highlighter.

На данном этапе получено работающее приложение, которое показывает иконки файлов и работает локально. Мультиселект при выборе файлов тоже работает. Осталось добавить загрузку выбранных файлов на сервер и задействовать ProgressBar. Это просто. При нажатии на кнопку «Начать загрузку» будем брать первый элемент из photos, создавать URLRequest, вызывать у FileReference метод upload и добавим event listener-ы, которые будут управлять прогресс-баром и отслеживать, когда файл загрузится. После загрузки удаляем первый элемент из photos и запускаем все заново. Вот код:
private function startUpload():void
{
  photosProgressContainer.visible = true;
      
  var fr:FileReference = photos.getItemAt(0).fr;
  fr.cancel();
  fr.addEventListener(ProgressEvent.PROGRESS,uploadProgress);
  fr.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,uploadComplete);
  fr.upload(new URLRequest("http://ragneta.com/tests/flexupload/upload.php"));
}

private function uploadProgress(e:ProgressEvent):void
{
  photosProgress.setProgress(e.bytesLoaded,e.bytesTotal);
}

private function uploadComplete(e:DataEvent):void
{
  photos.removeItemAt(0);
  if (photos.length > 0)
    startUpload();
  else
    photosProgressContainer.visible = false;
}


* This source code was highlighted with Source Code Highlighter.

На этом все, здесь полный код: Uploader.mxml, photoThumb.mxml. Дальше в ролик нужно передавать какую-нибудь авторизацию, я передаю идентификатор сессии через flashvars, соответственно во flex переданные переменные находятся в массиве Application.application.parameters. Затем в инициализации делаю HTTPRequest, отправляю сессию и получаю имя юзера, его альбомы и все остальное. Также нужно отлавливать ошибки и исключения, разбирать ответ сервера итд. Здесь написан только необходимый минимум.

Если нет необходимости загружать исходники фотографий, можно делать ресайз до отправки на сервер. Делается с помощью flash.display.Bitmap, вот пример.

В процессе подготовки поста обнаружил странный баг. Прогресс-бар и событие FileReference.cancel() некорректно работают на WinVista + FF 3.5.7 + Flash Player 10.0.42, но на аналогичном WinXP + FF 3.5.7 + Flash Player 10.0.42 все хорошо.

Также пока не решил проблему с поворотом изображений. Во-первых не нашел, как делать анимированное преобразование через задание новой image.transform.matrix. Вторая проблема — мой Rotate применяется не к данным, которые передаются в itemRenderer, а к тегу самого itemRenderera. Если повернуть картинку, а потом ее удалить и загрузить на ее место новую, она окажется повернутой. При этом событие initialize каждой ячейки происходит только один раз. Приходится в itemRenderer на dataChange вешать поворот в 0, хотя хватило бы, если бы TileList умел полностью уничтожать ячейки при удалении данных, и потом проводить повторную инициализацию.
Алексей Кузнецов @Kasheftin
карма
37,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое

Комментарии (49)

  • –7
    Тоже некоторое время назад учил Flex, потом понял, что Flex сильно ограниченный фреймворк, и многие вещи через него просто невозможно сделать…
    • +1
      Можно поподробнее?
      • +7
        например приложения легче 300Кб :)
        • +3
          А теперь учим матчасть. SDK можно отвязать через RSL. И он грузится только один раз(причем для любого домена).
      • 0
        Я пробовал создать RSS Reader на флеше…
        В итоге оказалось, что он поддерживает буквально несколько HTML тегов, поэтому возник нереальный геморой например с тем, чтобы парсить код вставки ютуб ролика или например, чтобы отобразить анимированную GIF картинку.

        Вообще отсутствие поддержки HTML не дает комфортно создавать флеш приложения с текстом.
        Например, хочу сделать флешку, в которой 10 пунктов меню, кликаешь по пунку и подгружается текст этого пункта из БД.
        Но как этот текст форматировать? Если, даже, стандартно тег table не поддерживает, а только после написания нескольких костылей.

        ИМХО, я считаю, что форматирование текста очень важный момент, и он должен был быть реализован в фреймворке…

        Там еще какие-то проблемы были, сейчас уже не припомню, помню что на форуме флешер.ру разводили руками и говорили что flex неповоротлив и что проще сразу было делать на чистом флеше + AS
        • +8
          Флеш (вернее базовый класс TextField, унаследованный от DisplayObject, а только он работает с текстом) не поддерживает html. То, что там есть свойство htmlText говорит лишь о том, что они сделали небольшое удобство людям, которые хотят в тексте видеть, например, функционал , и при этом не реализовывать его ручками. Это НЕ html, это реализация поддержки тега.

          Я считаю, что поддержка html ни в коей мере не должна находится в ядре флеша (globalplayer.swc), если надо — делаем google:(parser+html+as3) и используем уже написанные библиотеки.

          Далее, для особо продвинутого форматирования текста был создан фреймворк TextLayout (написан на чистом as3, как и флекс). Это для тех случаев, когда стандартный flash.text.* недостаточен. Однако TextLayout весит 300КБ, соотвественно ваш проект увеличится примерно на столько же в релизе, однако этот фреймворк позволяет делать с текстом такое, что html+css+js даже и не снилось.

          Посути флеш — это SWF-Tags + Actionscript (abc-код в fp9 и выше). Часть из swftags можно реализовать на as(3), например тег DefineShape (в fp10 это получится DefineShape4):
          var s:Shape = new Shape();
          s.graphics = ....;
          addChild(s);

          Flex и TextLayout это лишь фреймворки, использующие as3, посему и ограничены лишь ядром флеша. Т.е если FP9 не поддерживает RTMFP, в отличие от FP10; то и flex не сможет добавить этой функциональности. А вот разметку в процентах флекс дает. Но это и не минус флеша, ибо с поддержкой процентов, как писал ниже, «Hello, word!» будет весить не 576 bytes, а раза в 4 больше, и рост будет увеличиваться пропорционально используемым DisplayObjects в коде, что не приемлемо, ИМХО.

          Так что вы привели пример незнания технологий, основанных на флеше, уж извините, и клянете в этом флекс, а он тут, мягко говоря, совершенно не причем. Парсеры html на as3 есть (не говоря уже о том, что xml поддерживаетя в ядре — flash.xml.*), базовое форматирование тоже (flash.text.*), остальное дописывается ручками.
          • 0
            >html+css+js даже и не снилось
            например?
            • +2
              Demo — Linked Containers, Figures (выделение наклонного текста), Expressive Effects. Посмотрите демку полностью, поиграйтесь с настройкоми сверху.
          • 0
            спасибо, возможно я плохо изучил вопрос.
            • 0
              Да не за что. Кстати, первый найденный из запроса в гуглю as3htmlparser (demo), поддерживает довольно много.

              А флеш — это очень мощная штука, но полная картина всплывает лишь только после изучения спецификаций swf9 и выше.
    • +1
      И в чем же он ограничен, простите?
      • –1
        Присоединяюсь к вопросу
        • 0
          ТУпо первый пришедший в голову пример: чтобы сделать компонент tabbar у которого вкладки располагаются не в одну строчку, а в две, нужно сверх круто знать флекс. Это Оооооочень не тривиальная задача, которая под силу далеко не каждому.
          • +1
            Вы знаете, чтобы написать что-то серьезное, надо вообще быть специалистом в области. Для написания собственного компонента НЕОБХОДИМО знать жизненный цикл, аспекты, логику фреймворка и пр. Без этого какой смысл что-то писать? ПолуНедоСпециалисты в этой жизни слабо котируются.

            Если я верно понял что вы придумали, то эта задача на экран кода (при этом используя уже готовый TabBar из flex3 (а не TabNavigator)). Тут как раз даже не вижу сложности.
            • 0
              Как напишешь скинь в личку. Мой вариант занял 2 дня работы и пришлось написать компонент практически с нуля. mx_internal и private греют душу.
              • 0
                Вопервых, c чего вы решили, что я буду писать этот компонент? У меня своей работы достаточно и мое время стоит определенных денег. Вовторых на ты тут общаться не приянто незнакомым людям, ну да ладно. А в третьих, сформулируйте полное поведение вашего компонента (порядок заполнения табов (т.е как заполняются — сначала до упора первый или попеременно), кол-во элементов в табе (?) и/или пр.) и если у меня будет свободное время, я его вам отпишу.
                • 0
                  «Вопервых, c чего вы решили, что я буду писать этот компонент?» Ты в праве сам распоряжаться своим временем и задачами. Но если звезды сойдутся и компонент будет написан, скинь в личку примеры. Мне очень интересно будет посмотреть.

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

                  «А в третьих, сформулируйте полное поведение вашего компонента» Таб бар заполняется до упора элементами, если новая вкладка не влазит в текущую строку, создается новый ряд на N% меньше чем предидущий. Строки не меняются друг с другом местами при клике. Получается такая пирамидка с кнопочками.
    • 0
      блин… складывается такое чувство, что подавляющее большинство хабралюдей владеют только php… причем некоторые из них враждебно относятся к другим языкам и технологиям… это наверно потому, что для того чтобы начать программировать на php особо много скиллов не надо… там даже ООП появилось только в 5 версии… так что начать быть программистом php может любой школьник 8 класса…
      а утверждать чего нельзя сделать на Flex, не умея делать хотя бы что-нибудь на Flex, я бы ни стал…
  • +2
    Флекс он, конечно же, сильный, мощный фремворк, но с одним существенным недостатком — слишком много весят конечные приложения (от 1МБ флекс3, от 1.7МБ флекс4). Для интрАнета — в самый раз, для интернета — тяжеловато еще, ИМХО, даже с использованием rsl.

    Для такой задачи я бы выбрал чистый флеш и уложился бы на стандартных компонентах (fl.*) в 50-100 КБ.
    • –5
      ну не знаю у меня «Hello, word!» 279 KB.
      О какой задаче вы говорите? Flex — это RIA. Flash — это графика…
      • +4
        о задаче, которую реализовал ТС.
        «Hello, word!» — это не приложение :) Однако на флеше, только что проверил, «Hello, word!» заняло 576 bytes в релиз-версии. Разница, на сой взгляд, очевидна.
      • 0
        я писал такой загрузчик полгода назад без использования флекс.
        это был мой первый проект на ас3. итоговый размер свф — 281 кб.
        и это с подключенной библиотекой алчеми для сжатия изображений.
    • 0
      Ответил чуть выше. SDK отвязывается через RSL. Пишу статью дабы развеять заблуждения
      • 0
        Да знаю я, даже уточнил. Однако всем интересен первый клиент на приложении (у которого, скорее всего, библиотеки еще не шарены), а он не собирается ждать загрузки 10 секунд и более, он быстрее уйдет с ресурса.

        Гугля проводила исследования на эту тему — как только скорость отображения их главной страницы увеличилась на что-то типа 0.7 секунды (из за каких-то js-компоненттов), они потеряли 13% трафа. Не нахожу никак пруф-линк, но рассказывала это женщина какой-то главный аналитик Гугла. С красивыми графиками и пр. И я склонен ей доверять, в моей практике такое тоже случалось, лишь из-за банального увеличения веса страницы траф падал.
  • +4
    Всё хорошо, но только Ваш загрузчик не уменьшает фотографии перед отправкой. В той статье ссылку на которую вы дали уменьшение идет для помещения картинки в контейнер с заданными размерами. Реальное уменьшение делается библиотеками которые перекодируют байтовый массив изображения. Есть несколько библиотек на AS3 в том числе от adobe, но у них один минус — они тормозные. Проблема тормозов решается использование adobe alchemy которая позволяет использовать компилированый код написанный на С++ и благодаря этому повысить производительность. Насколько я знаю вконтакте как раз использует alchemy.
    Я делал подобный загрузчик как раз с использованием alchemy для уменьшения картинок. Посмореть можно как работает «уменьшалка» тут
    Если интересно могу написать как создавать подобное. Так же могу написать о том как делать скинабельные компоненты на флэше.
    • +2
      Интересно, пишите.
    • 0
      Странно, ссылка не прошла
      aeon.catpic.ru/alchemy/
    • +1
      Круто, конечно пишите. Я вроде давно веб-разработкой занимаюсь, но про alchemy впервые слышу, чувствую себя пещерным человеком. И то что flex-овые приложения великоваты получаются не учел. Ролик без ресайза весит 600 кб, еще сишный image_resize 180 кб.
    • 0
      Насколько я знаю, Alchemy просто транслирует C/C++ код в Actionscript. Ни о каком приросте производительности речи и не идет, т.к. код исполняется все той же виртуальной машиной Actionscript (AVM2).
      Тут, скорее, наоборот имеет место снижение производительности, ведь вслед за самой C/C++ программой тянутся все ее include-ы.
      Как я понял, назначение этой технологии — портировать существующие алгоритмы во Flash.

      Вот небольшая статья про Alchemy: www.automatastudios.com/2008/11/21/understanding-adobe-alchemy/
      • 0
        Зачастую идет прирост, на тестах это видно, ибо Alchemy использует несколько недокументированных возможностей as3. Вот одна из них, использование которой в Alchemy дало началу Virtual Memory API в haXe.

        Так что не все так просто.
      • 0
        Я сам делал замеры используя разные классы для кодирования изображений в сравнении с тем что дает алхимия, прирост был от 3 до 10 раз. Так что для некоторых целей alchemy очень полезна.
      • 0
        скорость получается за счёт работы с ByteArray. в 10м флэше появились «скрытые» операторы работы с ByteArray, которые не доступны обычным смертным, и которые очень активно используются компилятором алхимии.
      • 0
        поправочка: не транслирует в Actionscript, а компилирует в байткод AVM2
  • –5
    не вчитывался в код, но с виду поразительно похоже на WPF
    • +6
      не вчитывался в код, но с виду поразительно похоже на XML :)
      • –1
        ну какбы XAML это расширение XML, да
        • +1
          Ну а MXML (код в статье) это расширение XML, которое позже транслируется в as3, а потом as3 компилируется в abc-код (ну то есть в .swf)
  • +1
    Анимированный поворот можно делать через <mx:Rotate>, не знаю, насколько это современно, да и там, кажется нет возможности работы с матрицей преобразования. Просто указывается цель target, определяются углы поворота angleFrom и angleTo и используются методы анимации play и stop.
    • 0
      Да, я с помощью mx:Rotate и делаю, а то, что вылезает, скрываю. Там еще есть mx:Zoom, который меняет масштаб, и конструкция <mx:Parallel> которая вроде как позволяет эти эффекты запускать одновременно. Только я это пока не победил.
  • +4
    Так и не нашел ссылки на само созданное приложение. Сделали бы демку как это будет выглядеть в итоге?
  • 0
    На Javascript скоро будет File API значительно распространён (пока только Safari 4 и Firefox 3.6), а модификацию изображений можно через Canvas делать (тот же www.pixastic.com/).
    • 0
      Это хорошие новости, только 6-й ослик настроение портит…
      • 0
        И 7-ой… да и 8-ой.
  • +4
    Где живьем увидеть пример вашего загрузчика? (демо)
  • +5
    Ну как хэллоуворлд конечно пример канает, но в продакшн я бы такое запустить постеснялся. Автор следите за слушаетлями, которых вы создаете. У вас будут очень большие проблемы с памятью, обещаю ) А потом будут очень большие проблемы у меня, когда придется отбиваться от очередного холиворщика, который ненавидит флеш за то, то тот палит проц и жрет память. Вобщим сделал addEventListener, сделай removeEventListener или хотя-бы поставь слабую ссылку, иначе по рукам. Проблемы с поворотом через матрицу трансформаций решаются библиотеками типа TweenMax, потому-что встроенные твины во флексе какие-то ущербные. Так-же неплохо было-бы вообще понять философию itemRenderer`а. Он на то и называется itemRenderer, что не работает ни с чем кроме itemData. Вообще. Т.е. вызывать что-то там из parent document это грубое нарушение инкапсуляции (по рукам да). И дергать методы itemRenderer`а из его контейнера это тоже запрещено. А вообще все круто, хороших и полезных Вам приложений. Флекс это очень интересный и многогранный фреймворк.
    • 0
      Спасибо за советы.

      А как бы Вы сделали удаление itemRenderer-ов? Есть, к примеру, в itemRenderer кнопка «удалить» и при клике на нее нужно удалять соответствующий элемент из TileList. Ведь какое-то управление на элементах TileList хочется иметь, те же повороты, удаления, переименовать файл итд. Как правильно это программировать?

      Еще совсем общий вопрос — как написать нормальное приложение на flash или flex? Нормальное в смысле целый сайт типа www.nvidia.com/object/cuda_home.html, miniusa.com/ или www.rafinadhome.ru/? Во flex есть сцены, где можно указывать, какие элементы удалить и добавить на страницу, но при большом количестве страниц невозможно не запутаться. + хочется вынести максимум параметров из swf-ника, чтобы не требовалось его компилировать при каждом изменении.

      Может быть есть туториал по созданию нормального flash-сайта, подскажете? 7 лет назад, когда я вроде как выучил php, устроился на работу, и коллеги сразу прочистили мне мозги и объяснили, что я ничего не знаю, что есть MVC, и как писать сайт. Сейчас у меня похожие неясности с flash, но не устраиваться же теперь на работу, чтобы все выяснить:). И главный теоретический вопрос — в логической структуре приложения, где делать границу между тем, что должен отдавать некий xml-config и тем, что должно быть зашито в самом swf.
      • 0
        Удалите itemData из dataProvider. TileList обработает событие и убьет ненужный renderer.

        Большие приложения обычно пишутся с использованием микроархитекруты Cairngorm. Это специально адаптированный для флекса MVC + DataBinding. С его использованием можно написать практически любое нужное вам приложение. Правда трудозатратен гад и требует большого количества в принципе ненужного кода. На каждый чих новый класс. Хороший tutorial можно найти тут www.davidtucker.net/category/cairngorm/
  • 0
    Кажется, я видел java-апплеты для такой задачи, но есть смысл поддерживать и флэш тоже. По опыту использования аналогичных приложений/апплетов посоветую протестировать работу сабжа на нестабильном соединении — ситуация, когда апплет наглухо заглючивает при обрыве tcp-соединения, мягко говоря, удовольствия не доставляет. Идеалом в этом отношении вижу google picasa — поставил работу на закачку, и делай дальше асинхронно что угодно — загрузка асинхронна с интерфейсом и восстанавливается после ошибок.

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

    Итого, имхо, идеал — когда поддерживается и java, и флэш, и загрузка архивом, и загрузка файлов по одному, причём в первых двух случаях загрузка асинхронна — пока загружаются файлы, можно выбрать и поставить следующие, а во вторых двух пользователю показывается progress bar на javascript, показывающий текущий прогресс загрузки в процентах.
  • 0
    Буду признателен за ответ!

    Я добавил переменную — public var count:int;
    В ней хранится общее кол-во загруженных файлов count = photos.length;
    Также, вместо имени файла, я вывожу порядковый номер(добавил новое свойство num и присваиваю номер текущего элемента, отсчет веду от единицы):

    private function addPhotos(e:Event):void
    {
    for (var i:uint = 0; i < frList.fileList.length; i++)
    {
    var elem:Object = {fr:FileReference(frList.fileList[i]),num:i};
    elem.num = count+1;
    elem.fr.load();
    elem.fr.addEventListener(Event.COMPLETE,refreshThumb);
    photos.addItem (elem);
    }
    }

    В рендере вывожу номер таким образом:
    <mx:Label text=«Фото №{data.num}» width=«100%» truncateToFit=«true» bottom=«0» textAlign=«center» />

    Вопрос в том, что при удалении фотографии, порядковый номер не меняется. Т.е. если есть 5 фотографий и я удалю 2-ю и 3-ю, то в списке будет порядок – 1, 4, 5, а по логике, после удаления должен быть 1,2,3.

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

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