Статьи

Создание приложения Snappy Snapshot с помощью Flash Builder 4

Существует множество сайтов, на которых вы можете выбрать изображение своего профиля, сделав снимок с помощью веб-камеры, а не загружать его. Из этого туториала вы узнаете, как делать снимки и делать с ними что угодно, используя Flash Builder 4 с Ruby on Rails или PHP.


Нажмите на демонстрационную ссылку выше, но имейте в виду, что вы не сможете использовать функцию «Сохранить», если не запустите ее самостоятельно на сервере, который поддерживает PHP. Вы можете щелкнуть правой кнопкой мыши> Просмотр источника, чтобы увидеть исходный код приложения.


Чтобы в полной мере воспользоваться этим учебным пособием, рекомендуется, чтобы вы уже знали некоторые из новых функций Flash Builder 4, такие как новые пространства имен и компоненты. Кроме того, вам понадобится Flash Builder 4 для запуска исходного кода без необходимости что-либо менять.

Пользователи Flex 3: не волнуйтесь, вы все равно можете следовать этому руководству. Вам нужно изменить все пространства имен «fx» и «s» на «mx», например: «<s: Button>» становится «<mx: Button>». Тег «Объявление» не существует (напишите, что внутри, снаружи). «Group» и «BorderContainer» будут «Canvas». «VGroup» будет «VBox». «HGroup» будет «HBox». И нет «ChromeColor» (вам нужно будет по-другому стилизовать кнопку).


Прежде всего, нам нужно создать новый проект Flex. Откройте Flash Builder 4 и нажмите «Файл> Создать> Проект Flex».

Запустите приложение

Откроется следующий диалог:

Запустите приложение

Выберите «Имя проекта»: в нашем случае это будет «CameraSnapshot», но вы можете использовать все, что захотите. Вы также можете установить «Расположение проекта» где угодно. Поскольку он будет работать в браузере, мы оставим «Веб» проверенным. Мы будем использовать версию SDK по умолчанию и не будем выбирать какую-либо серверную технологию.

Хит Next.

Запустите приложение

Мы не будем ничего менять здесь, нажмите Далее.

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

Запустите приложение

Наш проект создан. Это свежее новое приложение Flash Builder 4!

Запустите приложение

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

Создайте новый файл ActionScript: «Файл»> «Создать»> «Файл ActionScript».

Запустите приложение

Дайте ему имя, мы выберем: «cam», но опять же, оно может быть любым, что вы хотите

Запустите приложение

Вы можете оставить «Пакет» пустым. Нажмите Finish. Теперь давайте начнем кодировать!


Теперь, когда наш проект создан, нам нужно место для отображения нашей камеры. Давайте добавим VideoDisplay в наш файл CameraSnapshot.mxml после тега «Заявления»:

1
<mx:VideoDisplay id=»theCam» width=»533″ height=»400″/>

Идентификатор важен, потому что именно так мы относимся к этому конкретному VideoDisplay.

Вы можете изменить ширину и высоту VideoDisplay так, как вам удобно, но не забывайте сохранять соотношение сторон 4: 3, чтобы избежать искажения изображения. Если вы не имеете дело с конкретным случаем.

Также обратите внимание, что мы использовали префикс пространства имен «mx» вместо «s» . Если мы используем здесь префикс пространства имен «s» , Flash Builder выдаст ошибку, когда мы попытаемся использовать метод attachCamera. Мы увидим этот метод на следующем шаге.


Теперь, когда у нас есть место для отображения камеры пользователя, давайте его получим! Создайте новую функцию внутри файла cam.as :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private function getCam():void
{
    if (Camera.getCamera())
    {
        // assign the user’s default camera to a variable
        var camera:Camera = Camera.getCamera();
         
        // set the camera quality to be the highest as possible
        camera.setQuality(0, 100);
         
        // set the width, height, frames per second
        camera.setMode(theCam.width, theCam.height, 30);
         
        // attach the camera to our «theCam» VideoDisplay
        theCam.attachCamera(camera);
    }
     
    else
    {
        //add your own method to tell the user his problem
    }
 
}

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

В camera.setMode вы должны понимать «theCam.width» как «ширину нашего VideoDisplay». В Flex это называется привязкой данных. Говоря простым языком: «ширина и высота камеры всегда и автоматически будут равны ширине и высоте камеры». Итак, если вы решите изменить размер VideoDisplay позже, размер камеры изменится автоматически.

После получения и настройки нашей камеры мы прикрепляем ее к нашей «камере». Он говорит нашему VideoDisplay, что отображать.


Давайте импортируем наш cam.as в наш файл CameraSnapshot.mxml , иначе у нас не будет доступа к функции, которую мы только что сделали:

1
<fx:Script source=»cam.as»/>

Если вы сохранили «cam.as» в другой папке, просто добавьте имя папки перед «cam.as», например: «Different_folder / cam.as»

Теперь нам нужно указать нашему приложению, чтобы он действительно запускал эту функцию. Мы добавим метод creationComplete, вызывающий getCam (); внутри открывающего тега «Приложение». Это означает, что наша камера будет отображаться, как только приложение будет полностью создано:

1
2
3
4
  <s:Application xmlns:fx=»http://ns.adobe.com/mxml/2009″
xmlns:s=»library://ns.adobe.com/flex/spark»
xmlns:mx=»library://ns.adobe.com/flex/mx» minWidth=»955″ minHeight=»600″
creationComplete=»getCam();»>

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

Запустите приложение

Обратите внимание: некоторым пользователям, особенно на Mac, возможно, придется сменить камеру по умолчанию, которую получает Flash Player. Внутри запущенного приложения: щелкните правой кнопкой мыши (или щелкните cmd +)> Конфигурации …> Перейдите на вкладку «значок веб-камеры» ниже> Измените ее на «настоящую» камеру.


На этом этапе мы обернем наш тег «VideoDisplay» в «VGroup», чтобы расположить элементы, которые мы добавим, по вертикали. Вы сами увидите это позже.

1
2
3
<s:VGroup horizontalCenter=»0″ verticalCenter=»0″>
        <mx:VideoDisplay id=»theCam» width=»533″ height=»400″/>
    </s:VGroup>

Обратите внимание, что для свойств HorizontalCenter и VerticalCenter установлено значение «0». Это означает, что «VGroup» будет в 0 пикселях от центра родительского контейнера, в нашем случае, всего приложения.

Вы можете снова запустить приложение: измените размер окна вашего браузера и обратите внимание, что вы всегда в центре.


Чтобы добавить нашу кнопку «Сфотографируй», нам нужно обернуть наш «VideoDisplay» тегом «Group», где макет является абсолютным, и все помещается друг на друга (если только вы не расположите их с помощью X и Y или разместите их на несколько пикселей от верха, справа, снизу или слева).

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

1
2
3
4
5
<s:VGroup horizontalCenter=»0″ verticalCenter=»0″>
    <s:Group id=»videoArea»>
        <mx:VideoDisplay id=»theCam» width=»533″ height=»400″/>
    </s:Group>
</s:VGroup>

Обратите внимание, что мы только что добавили тег «Group». Это внутри нашей недавно добавленной «VGroup» и оборачивает наш хорошо известный «VideoDisplay»

Теперь добавляем кнопку «Сфотографируй». Он появится внутри красивого полупрозрачного «BorderContainer», который мы напишем под нашим «VideoDisplay», взгляните:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<mx:VideoDisplay id=»theCam» width=»533″ height=»400″/>
 
<s:BorderContainer
    bottom=»0″
    width=»100%»
    backgroundColor=»black»
    backgroundAlpha=»0.4″
    borderColor=»black»
    height=»55″>
     
    <s:Button
        id=»trigger»
        horizontalCenter=»0″
        verticalCenter=»0″
        label=»Take a picture!»
        height=»35″/>
     
</s:BorderContainer>

Обратите внимание, что наша область кнопок расположена на расстоянии 0 пикселей от дна и имеет черный полупрозрачный (backgroundAlpha) фон. Мы также добавили нашу кнопку захвата под названием «триггер». Он расположен прямо посередине нашего «BorderContainer».


Добавьте «chromeColor» и «color» к нашей кнопке «trigger», и наш код должен выглядеть следующим образом:

1
2
3
4
5
6
7
8
<s:Button
    id=»trigger»
    horizontalCenter=»0″
    verticalCenter=»0″
    height=»35″
    label=»Take a picture!»
    chromeColor=»#33abe9″
    color=»#ffffff»/>

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


Теперь мы добавим местозаполнитель, где мы можем предварительно просмотреть изображение, которое мы сделаем позже. Напишите это под нашим «VideoDisplay» и над нашим «BorderContainer».

1
2
3
<s:Group id=»previewBox» visible=»false»>
    <mx:Image id=»preview» width=»100%» height=»100%»/>
</s:Group>

Мы добавили «Группу» под названием «previewBox», которая оборачивает «Изображение» под названием «Предварительный просмотр».


Добавьте следующий код вверху нашего файла «cam.as».

1
// ActionScript file import flash.display.BitmapData;

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


Теперь пришло время сфотографировать. Давайте добавим функцию, которая сделает это:

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
public function takePicture():void {
     
    //if we are not previewing any picture, we’ll take one 🙂
    if (!previewBox.visible) {
         
        //create a BitmapData variable called picture that has theCam’s size
        var picture:BitmapData = new BitmapData(theCam.width, theCam.height);
         
        //the BitmapData draws our theCam
        picture.draw(theCam);
         
        //Our preview’s source is a new Bitmap made of picture’s BitmapData
        preview.source = new Bitmap(picture);
         
       //stores this BitmapData into another BitmapData (outside this function)
        bm = picture;
         
        //makes the previewBox visible, so we can see our picture
        previewBox.visible = true;
         
        //change our trigger label, so the user will be able to try again
        trigger.label = «Take another picture…»;
         
        //changes the color of the button
        trigger.setStyle(‘chromeColor’, ‘#ff0000’);
                 
    }
         
    //if we are previewing a picture…
    else {
         
        //makes the previewBox invisible
        previewBox.visible = false;
         
        //changes the label
        trigger.label = ‘Take a picture!’;
         
       //changes the color of the button
        trigger.setStyle(‘chromeColor’, ‘#33abe9’);
         
    }
     
}

Комментарии выше «// (…)» расскажут вам, что происходит.

Теперь добавьте свойство click в нашу кнопку триггера (CameraSnapshot.mxml), чтобы вызвать нашу недавно созданную функцию takePicture:

1
2
3
4
5
6
7
8
9
<s:Button
    id=»trigger»
    horizontalCenter=»0″
    verticalCenter=»0″
    height=»35″
    label=»Take a picture!»
    chromeColor=»#33abe9″
    color=»#ffffff»
    click=»takePicture();»/>

Запустите приложение и сделайте снимок!


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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<fx:Declarations>
    <!— Place non-visual elements (eg, services, value objects) here —>
     
    <mx:Fade id=»flashFX» duration=»550″ />
     
    <s:Parallel id=»discardPhoto»>
        <s:children>
            <mx:Zoom
                duration=»350″
                zoomWidthFrom=»1.0″
                zoomWidthTo=»0.01″
                zoomHeightFrom=»1.0″
                zoomHeightTo=»0.01″
                target=»{previewBox}»/>
            <mx:Fade duration=»350″/>
        </s:children>
    </s:Parallel>
     
</fx:Declarations>

Тег «Fade» заставит вспышку исчезнуть реалистично. Тег «Параллель» будет запускать «Масштаб» и «Исчезать» одновременно, удаляя нашу фотографию со стилем.


Давайте добавим наш фонарь под изображением «предварительного просмотра»:

1
2
3
4
5
6
7
8
9
<mx:Image id=»preview» width=»100%» height=»100%»/>
 
<s:BorderContainer
    id=»flashLight»
    width=»100%»
    height=»100%»
    hideEffect=»{flashFX}»
    backgroundColor=»white»
    backgroundAlpha=»0.8″/>

Обратите внимание, что «hideEffect» установлен в «{flashFX}»: когда «flashLight» становится невидимым, этот эффект срабатывает. Кроме того, «backgroundAlpha» установлен на «0,8», поэтому наша вспышка не такая яркая. Наш фонарь — это просто белый BorderContainer, который появляется, а затем быстро уходит, создавая эффект «вспышки».

Теперь нам просто нужно установить свойство visible для «flashLight» в «true» и «false» (активируя эффект flash) внутри нашей функции «takePicture», которая теперь будет выглядеть так:

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
public function takePicture():void {
     
    //if we are not previewing any picture, we’ll take one 🙂
    if (!previewBox.visible) {
         
        //create a BitmapData variable called picture that has theCam’s size
        var picture:BitmapData = new BitmapData(theCam.width, theCam.height);
         
        //the BitmapData draws our theCam
        picture.draw(theCam);
         
        //Our preview’s source is a new Bitmap made of picture’s BitmapData
        preview.source = new Bitmap(picture);
         
        //stores this BitmapData into another BitmapData (outside this function)
        bm = picture;
         
        //makes the previewBox visible, so we can see our picture
        previewBox.visible = true;
         
        //displays the flashLight
        flashLight.visible = true;
         
        //makes the flashLight go way
        flashLight.visible = false;
         
        //change our trigger label, so the user will be able to try again
        trigger.label = «Take another picture…»;
     
        //changes the color of the button
        trigger.setStyle(‘chromeColor’, ‘#ff0000’);
         
    }
         
        //if we are previewing a picture…
    else {
         
        //makes the previewBox invisible
        previewBox.visible = false;
         
        //changes the label
        trigger.label = ‘Take a picture!’;
         
        //changes the color of the button
        trigger.setStyle(‘chromeColor’, ‘#33abe9’);
         
    }
     
}

Измените «Группу» с именем «previewBox» (CameraSnapshot.mxml), чтобы она использовала эффект «discardPhoto»:

1
<s:Group id=»previewBox» visible=»false» hideEffect=»{discardPhoto}»>

Обратите внимание на «hideEffect» снова. Запустите приложение, сделайте снимок, сделайте еще один и посмотрите эффекты!


Давайте добавим кнопку Сохранить и Отменить прямо под закрывающим тегом нашей «Группы», называемой «videoArea», и над закрывающим тегом «VGroup»:

1
2
3
4
5
6
7
8
9
<s:HGroup verticalAlign=»middle» horizontalAlign=»right» width=»100%»>
    <mx:LinkButton label=»Cancel»/>
    <s:Button
        id=»savePic»
        label=»Save picture»
        height=»30″
        enabled=»false»
        toolTip=»Make it your profile image!»/>
</s:HGroup>

Мы обернули кнопки «Отмена» и «Сохранить изображение» внутри тега «HGroup» (который будет отображать их горизонтально). Мы установили для свойства «verticalAlign» значение «middle», чтобы кнопка «Отмена» располагалась посередине высоты «savePic». Мы также устанавливаем «width» на «100%» и «horizontalAlign» на «right».

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

Внутри файла «cam.as», после некоторых изменений, наша функция «takePicture» теперь будет выглядеть так:

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
52
53
54
55
public function takePicture():void {
     
    //if we are not previewing any picture, we’ll take one 🙂
    if (!previewBox.visible) {
         
        //create a BitmapData variable called picture that has theCam’s size
        var picture:BitmapData = new BitmapData(theCam.width, theCam.height);
         
        //the BitmapData draws our theCam
        picture.draw(theCam);
         
        //Our preview’s source is a new Bitmap made of picture’s BitmapData
        preview.source = new Bitmap(picture);
         
        //stores this BitmapData into another BitmapData (outside this function)
        bm = picture;
         
        //makes the previewBox visible, so we can see our picture
        previewBox.visible = true;
         
        //displays the flashLight
        flashLight.visible = true;
         
        //makes the flashLight go way
        flashLight.visible = false;
         
        //change our trigger label, so the user will be able to try again
        trigger.label = «Take another picture…»;
         
        //enables the savePic button
        savePic.enabled = true;
         
        //changes the color of the button
        trigger.setStyle(‘chromeColor’, ‘#ff0000’);
         
    }
         
    //if we are previewing a picture…
    else {
         
        //makes the previewBox invisible
        previewBox.visible = false;
         
        //changes the label
        trigger.label = ‘Take a picture!’;
                 
        //disables the savePic button
        savePic.enabled = false;
         
        //changes the color of the button
        trigger.setStyle(‘chromeColor’, ‘#33abe9’);
         
    }
     
}

Выше мы только что добавили 2 строки кода, чтобы включить и отключить кнопку Сохранить.


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

Давайте создадим функцию, которая отправляет нашу картинку на сервер, когда мы нажимаем «Сохранить картинку»:

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public function savePicture():void {
     
    //change the savePic button label so the user knows as soon as possible
    //that we are saving his picture
    savePic.label = «Saving…»
     
    //disables the button so the user don’t click it twice
    savePic.enabled = false;
     
    //the trigger button displays a nice message
    trigger.label = «That’s a nice picture :)»
     
    //disables the «trigger» button, now is too late to take another picture!
    trigger.enabled = false;
     
     
    //creates a new JPEGEncoder called «je»
    //sets the quality to 100 (maximum)
    var je:JPEGEncoder = new JPEGEncoder(100);
     
    //creates a new ByteArray called «ba»
    //JPEGEnconder encodes our «bm» Bitmap data: our «picture»
    var ba:ByteArray = je.encode(bm);
    //this ByteArray is now an encoded JPEG
     
    //creates a new Base64Encoder called «be»
    var be:Base64Encoder = new Base64Encoder();
     
    //encodes our «ba» ByteArray (wich is our JPEG encoded picture) with base64Encoder
    be.encodeBytes(ba);
     
    //Now we have our «encodedData» string to send to the server
    var encodedData:String = be.flush();
     
     
     
    //this is the HTTPService that we will use to send our data to the server
    var handleService:HTTPService = new HTTPService();
     
    //now we set what URL we want… Set the URL of your server-side page/action
    //this is a typical Ruby on Rails URL.
    handleService.url = «http://localhost:3000/users/camerasnap»;
     
    //another example of URL:
    //appUrl.url = «http://www.example.com/handlePicture.php»;
     
    //or, a relative path:
    //appUrl.url = «/handlePicture.php»
     
     
    //we choose POST as our method
    handleService.method = «POST»;
     
    //here we show the busy cursor for better visual feedback
    handleService.showBusyCursor = true;
     
    //Finally, we send our «encodedData» as a «content» variable
    handleService.send({content: encodedData});
     
     
    // 1 — in your server-side code you can handle the «param» or «post» variable called «content»
    // 2 — use a base64 decoder
    // 3 — write it to disc (now you have a real image saved in your server)
    // 4 — make this image the user’s profile picture or anything you want
     
}

В этой функции мы делаем три вещи: меняем некоторые метки и отключаем некоторые кнопки, кодируем нашу картинку в JPEG и, наконец, отправляем закодированные данные (строка Base64) на сервер.

Опять же, комментарии выше «// (…)» могут рассказать вам, как мы это сделали.

Теперь наша кнопка «Сохранить изображение» должна вызвать функцию «Сохранить изображение». Добавьте метод «click»:

1
2
3
4
5
6
7
8
<s:Button
    id=»savePic»
    label=»Save picture»
    height=»30″
    enabled=»false»
    toolTip=»Make it your profile image!»
    click=»savePicture();»
    />

В следующих шагах я написал только необходимый код, чтобы вы могли делать все что угодно с сохраненным графическим файлом. Вам нужно будет написать код, чтобы сделать «example_name.jpg» профилем пользователя (например). К сожалению, я не могу описать, как вы можете это сделать, поскольку это сильно меняется в зависимости от вашего текущего решения. Место для другого урока, я думаю …

В следующем примере показано, как сохранить изображение на вашем сервере с помощью Ruby on Rails или PHP , это довольно просто!


01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
require «base64»
   
def camerasnap
    
  #associate the param sent by Flex (content) to a variable
  file_data = params[:content]
   
  #Decodes our Base64 string sent from Flex
  img_data = Base64.decode64(file_data)
   
  #Set an image filename, with .jpg extension
  img_filename = «example_name.jpg»
   
  #Opens the «example_name.jpg» and populates it with «img_data» (our decoded Base64 send from Flex)
  img_file = File.open(img_filename, «wb») { |f|
   
  #now we have a real JPEG image in our server, do anything you want with it!
  #Write what’s necessary to make it a profile picture, an album photo, etc…
 
end

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
 
    //associate the param sent by Flex (content) to a variable
    $file_data = $_POST[‘content’];
     
    //Decodes our Base64 string sent from Flex
    $img_data = base64_decode($file_data);
     
    //Set an image filename, with .jpg extension
    $img_filename = «example_name.jpg»;
     
    //Opens the «example_name.jpg»
    $fp = fopen ($img_filename, «w»);
     
    //populates it with «img_data» (our decoded Base64 send from Flex)
    fwrite ($fp, $img_data);
     
    //closing the file pointer
    fclose ($fp);
     
    //now we have a real JPEG image in our server, do anything you want with it!
    //Write what’s necessary to make it a profile picture, an album photo, etc…
 
?>

Эти два примера выше (Rails и PHP) максимально просты и понятны. Вы можете написать их всего за 1 строку кода (Rails) и 2 строки (PHP), если хотите.


Перед загрузкой SWF на ваш сайт рекомендуется экспортировать его как оптимизированный SWF (сборка выпуска):

Экспортная сборка релиза

После экспорта вам нужно будет загрузить все, что находится внутри папки «bin-release» (находится внутри папки вашего проекта).

Надеюсь, вам понравился этот урок! С этим «изображением в реальном времени» вы можете многое сделать, я уже использую его в производстве, чтобы мои пользователи могли быстро изменить изображение своего профиля. Скажите нам, что вы думаете, будет творческое или инновационное использование этой функции в комментариях ниже. Благодарность!