Существует множество сайтов, на которых вы можете выбрать изображение своего профиля, сделав снимок с помощью веб-камеры, а не загружать его. Из этого туториала вы узнаете, как делать снимки и делать с ними что угодно, используя Flash Builder 4 с Ruby on Rails или PHP.
Окончательный результат предварительного просмотра
Нажмите на демонстрационную ссылку выше, но имейте в виду, что вы не сможете использовать функцию «Сохранить», если не запустите ее самостоятельно на сервере, который поддерживает PHP. Вы можете щелкнуть правой кнопкой мыши> Просмотр источника, чтобы увидеть исходный код приложения.
Шаг 1. Особенности Flash Builder 4
Чтобы в полной мере воспользоваться этим учебным пособием, рекомендуется, чтобы вы уже знали некоторые из новых функций Flash Builder 4, такие как новые пространства имен и компоненты. Кроме того, вам понадобится Flash Builder 4 для запуска исходного кода без необходимости что-либо менять.
Пользователи Flex 3: не волнуйтесь, вы все равно можете следовать этому руководству. Вам нужно изменить все пространства имен «fx» и «s» на «mx», например: «<s: Button>» становится «<mx: Button>». Тег «Объявление» не существует (напишите, что внутри, снаружи). «Group» и «BorderContainer» будут «Canvas». «VGroup» будет «VBox». «HGroup» будет «HBox». И нет «ChromeColor» (вам нужно будет по-другому стилизовать кнопку).
Шаг 2. Создание нового проекта Flex
Прежде всего, нам нужно создать новый проект Flex. Откройте Flash Builder 4 и нажмите «Файл> Создать> Проект Flex».
Откроется следующий диалог:
Выберите «Имя проекта»: в нашем случае это будет «CameraSnapshot», но вы можете использовать все, что захотите. Вы также можете установить «Расположение проекта» где угодно. Поскольку он будет работать в браузере, мы оставим «Веб» проверенным. Мы будем использовать версию SDK по умолчанию и не будем выбирать какую-либо серверную технологию.
Хит Next.
Мы не будем ничего менять здесь, нажмите Далее.
На этом следующем шаге мы также будем использовать настройки по умолчанию, поэтому нажмите «Готово»:
Наш проект создан. Это свежее новое приложение Flash Builder 4!
Шаг 3. Создание файла ActionScript
У нас будет внешний файл ActionScript, который будет выполнять всю логику за нас.
Создайте новый файл ActionScript: «Файл»> «Создать»> «Файл ActionScript».
Дайте ему имя, мы выберем: «cam», но опять же, оно может быть любым, что вы хотите
Вы можете оставить «Пакет» пустым. Нажмите Finish. Теперь давайте начнем кодировать!
Шаг 4: заполнитель камеры
Теперь, когда наш проект создан, нам нужно место для отображения нашей камеры. Давайте добавим VideoDisplay в наш файл CameraSnapshot.mxml после тега «Заявления»:
1
|
<mx:VideoDisplay id=»theCam» width=»533″ height=»400″/>
|
Идентификатор важен, потому что именно так мы относимся к этому конкретному VideoDisplay.
Вы можете изменить ширину и высоту VideoDisplay так, как вам удобно, но не забывайте сохранять соотношение сторон 4: 3, чтобы избежать искажения изображения. Если вы не имеете дело с конкретным случаем.
Также обратите внимание, что мы использовали префикс пространства имен «mx» вместо «s» . Если мы используем здесь префикс пространства имен «s» , Flash Builder выдаст ошибку, когда мы попытаемся использовать метод attachCamera. Мы увидим этот метод на следующем шаге.
Шаг 5: Получение камеры
Теперь, когда у нас есть место для отображения камеры пользователя, давайте его получим! Создайте новую функцию внутри файла 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, что отображать.
Шаг 6: Отображение камеры
Давайте импортируем наш 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();»>
|
Шаг 7: Первый запуск
Все идет нормально. Теперь запустите приложение и посмотрите в него, прежде чем мы перейдем к следующему шагу 🙂
Обратите внимание: некоторым пользователям, особенно на Mac, возможно, придется сменить камеру по умолчанию, которую получает Flash Player. Внутри запущенного приложения: щелкните правой кнопкой мыши (или щелкните cmd +)> Конфигурации …> Перейдите на вкладку «значок веб-камеры» ниже> Измените ее на «настоящую» камеру.
Шаг 8: макет и позиционирование
На этом этапе мы обернем наш тег «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 пикселях от центра родительского контейнера, в нашем случае, всего приложения.
Вы можете снова запустить приложение: измените размер окна вашего браузера и обратите внимание, что вы всегда в центре.
Шаг 9: кнопка захвата
Чтобы добавить нашу кнопку «Сфотографируй», нам нужно обернуть наш «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».
Шаг 10: Стиль кнопки
Добавьте «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»/>
|
Вы можете снова запустить приложение и посмотреть, как у нас дела.
Шаг 11: Изображение Предварительный просмотр Placeholder
Теперь мы добавим местозаполнитель, где мы можем предварительно просмотреть изображение, которое мы сделаем позже. Напишите это под нашим «VideoDisplay» и над нашим «BorderContainer».
1
2
3
|
<s:Group id=»previewBox» visible=»false»>
<mx:Image id=»preview» width=»100%» height=»100%»/>
</s:Group>
|
Мы добавили «Группу» под названием «previewBox», которая оборачивает «Изображение» под названием «Предварительный просмотр».
Шаг 12: Подготовка к снимку
Добавьте следующий код вверху нашего файла «cam.as».
1
|
// ActionScript file import flash.display.BitmapData;
|
Здесь мы только что импортировали все, что нам нужно для того, чтобы взять и отправить картинку на сервер.
Шаг 13: сделайте снимок!
Теперь пришло время сфотографировать. Давайте добавим функцию, которая сделает это:
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();»/>
|
Запустите приложение и сделайте снимок!
Шаг 14: Добавление крутых эффектов
Теперь добавим несколько классных эффектов: когда мы сделаем снимок, мы увидим вспышку. Когда мы откажемся от картинки, она исчезнет. Измените тег «Объявления», добавив следующий код:
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» заставит вспышку исчезнуть реалистично. Тег «Параллель» будет запускать «Масштаб» и «Исчезать» одновременно, удаляя нашу фотографию со стилем.
Шаг 15: Эффект Flash
Давайте добавим наш фонарь под изображением «предварительного просмотра»:
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’);
}
}
|
Шаг 16: Откажитесь от эффекта изображения
Измените «Группу» с именем «previewBox» (CameraSnapshot.mxml), чтобы она использовала эффект «discardPhoto»:
1
|
<s:Group id=»previewBox» visible=»false» hideEffect=»{discardPhoto}»>
|
Обратите внимание на «hideEffect» снова. Запустите приложение, сделайте снимок, сделайте еще один и посмотрите эффекты!
Шаг 17: Кнопка Сохранить
Давайте добавим кнопку Сохранить и Отменить прямо под закрывающим тегом нашей «Группы», называемой «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 строки кода, чтобы включить и отключить кнопку Сохранить.
Шаг 18: Сохранение картинки
Теперь мы рассмотрим одну из многих вещей, которые вы можете сделать со своей картинкой: отправка ее на сервер. При этом вы можете назначить его как фотографию профиля пользователя, новую фотографию альбома и т. Д.
Давайте создадим функцию, которая отправляет нашу картинку на сервер, когда мы нажимаем «Сохранить картинку»:
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();»
/>
|
Шаг 19: Обработка на стороне сервера
В следующих шагах я написал только необходимый код, чтобы вы могли делать все что угодно с сохраненным графическим файлом. Вам нужно будет написать код, чтобы сделать «example_name.jpg» профилем пользователя (например). К сожалению, я не могу описать, как вы можете это сделать, поскольку это сильно меняется в зависимости от вашего текущего решения. Место для другого урока, я думаю …
В следующем примере показано, как сохранить изображение на вашем сервере с помощью Ruby on Rails или PHP , это довольно просто!
Шаг 20: Обработка Ruby on Rails на стороне сервера
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
|
Шаг 21: Обработка PHP на стороне сервера
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), если хотите.
Шаг 22: Экспорт сборки выпуска
Перед загрузкой SWF на ваш сайт рекомендуется экспортировать его как оптимизированный SWF (сборка выпуска):
После экспорта вам нужно будет загрузить все, что находится внутри папки «bin-release» (находится внутри папки вашего проекта).
Вывод
Надеюсь, вам понравился этот урок! С этим «изображением в реальном времени» вы можете многое сделать, я уже использую его в производстве, чтобы мои пользователи могли быстро изменить изображение своего профиля. Скажите нам, что вы думаете, будет творческое или инновационное использование этой функции в комментариях ниже. Благодарность!