AS3Coder blog

Блог от AS3Coder'a о JavaScript, HTML, CSS... и немного о Flash.

вторник, 9 января 2018 г.

Front-End Developer на Кипр

Друзья по цеху, очень нужен Front-End Developer на Кипр.

Проекты: торговые платформы и рекламно-аналитические системы


У нас множество веб-сайтов и сервисов, а будет еще больше. Для их развития и поддержания нам нужно много хороших веб-программистов, знающих, что такое действительно классный интерфейс. Если вы из таких, и можете сделать технологичное и юзабельное решение, смело присылайте свое резюме!

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

Требования: 
  • Разработка с использованием JavaScript, CSS и HTML 
  • Опыт управления командами разработчиков 
  • Портфолио проектов, реализованных под вашим руководством (или с вашим участием) 
  • Знание принципов построения пользовательских интерфейсов, основ дизайна, эргономики 
Плюсами будут знания в смежных областях:
  • Понимание работы Microsoft IIS, SQL СУБД и http/https 
  • Общие представления или опыт в SEO 
  • Знание и понимание методов обеспечения безопасности веб-сервера 
Программисты front-end требуются для двух принципиально разных проектов. Вы можете выбирать, где именно хотите работать и какие именно задачи хотите решать.

Задачи в проекте "Торговые платформы":
  • Разработка торгового приложения для веб-платформ (десктоп, мобильные) 
  • Обеспечение сетевой безопасности веб-сервисов 
  • Оптимизация и рефакторинг кода для снижения сетевых задержек 
  • Работа с большим объемом данных (например, отображение 100 000 строк в браузере) 
  • Разработка графических компонентов для отображения графиков 

Используемые технологии: Javascript (ES5, ES6), HTML5, CSS3, Node, Less, Git, MVC, WebGL, WebSocket, Crypto API, TypedArray

Задачи в проекте "Рекламно-аналитической система":
  • Разработка всего UI системы с учетом User Experience (UX) 
  • Разработка и реализация оптимального отображения данных (различные типы графиков, таблицы и прочее) 
  • Общая разработка интерфейсов для десктоп и мобильных платформ 

Используемые технологии: Javascript (ES5, ES6), HTML5, CSS3, Node, Require JS, Less, D3, Git, MVC, REST

Что мы предлагаем

В каком бы проекте вы ни хотели работать, мы обеспечим вам самые лучшие условия:
  • Полная оплата вашего проезда и проживания для посещения собеседования 
  • Компенсация переезда, мы выплачиваем одноразовую компенсацию до 10 000 евро 
  • Корпоративная квартира на время поиска постоянного жилья 
  • Помощь в оформлении необходимых документов 
  • Заработная плата выше рынка 
  • Медицинская страховка для вас и вашей семьи 
  • Офис на берегу моря, широкие возможности для досуга и занятий спортом 
  • Кипр — курортная страна в Средиземном море, которая дарит 300 солнечных дней в году 
  • Бесплатное питание 
  • Уникальный опыт, сильная команда 
Присоединяйтесь!

P.S. Если вы не совсем вписываетесь в требования, но хотите работать у нас, все равно отправьте нам свое резюме. Мы с радостью познакомимся с вами и попробуем что-нибудь придумать.

https://www.metaquotes.net/ru/company/vacancies/front-end-developer

Подписываюсь под каждым пунктом. С удовольствием получу ваше резюме на farid@metaquotes.net. Буду собеседовать лично. Особенно буду рад бывшим Flash-девелоперам ;)

среда, 24 сентября 2014 г.

Сеты изображений. TexturePacker.

Сколько файлов изображений используются на вашем сайте или в веб-приложении? Как часто вам хотелось уменьшить их количество? Если эти вопросы хоть раз вас посещали, то этот пост для вас.

Набор изображений

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

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



На экран они выводятся  с помощью любого HTML-элемента и стиля background с указанием соответствующей позиции:
.icon { background: url('/icons.png') transparent no-repeat -16px -16px; }
Таким образом, у нас получается один большой файл со всеми изображениями, вместо множества маленьких.

Преимуществом такого способа являются:
  • удобства при разработке и поддержки проекта
  • хоть какой-то порядок в графических ресурсах проекта
  • самое главное - это меньшее количество запросов к серверу.
Если вы со мной согласны, то поговорим о том, как собрать уже имеющиеся изображения в один файл. Кто-то называет его атласом, текстурой или еще как-то, но мне больше подходит "сет" - от английского слова set (ряд, серия, набор...).

Сборка сета

Самым подходящим инструментом для выполнения подобной задачи является программа TexturePacker. Загрузить и установить её можно с официального сайта. Имеются версии для всех популярных операционных систем.



Устанавливаем, открываем и видим окно для выбора проекта:



Нас интересует пункт CSS. После выбора откроется окно проекта:



В него попробуем перетащить несколько иконок и сразу увидим предварительный вариант нашего сета:



В левой части будет находиться список файлов:



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



  • Путь к .css-файлу со стилями:



  • Всевозможные отступы между иконками:



Пример

В качестве примера я попробую объединить несколько изображений адресной книги из бесплатной коллекции иконок fugue-icons:


Вот такой сет у меня получился:


А вот и CSS-описание к нему:
/* ----------------------------------------------------
   created with http://www.codeandweb.com/texturepacker 
   ----------------------------------------------------
   $TexturePacker:SmartUpdate:3381f3f5613a5b4583ac8d9fc2098c0c:50c3d538df782baf783f7806cded96e4:1a4beba4193919b01a56dc2c2a237cfe$
   ----------------------------------------------------

   usage: <span class="{-spritename-} sprite"></span>

   replace {-spritename-} with the sprite you like to use

*/

.sprite {display:inline-block; overflow:hidden; background-repeat: no-repeat;background-image:url(icons.png);}

.address-book {width:20px; height:20px; background-position: -48px -26px}
.address-book--arrow {width:20px; height:20px; background-position: -4px -4px}
.address-book--exclamation {width:20px; height:20px; background-position: -4px -26px}
.address-book--minus {width:20px; height:20px; background-position: -4px -48px}
.address-book--pencil {width:20px; height:20px; background-position: -26px -4px}
.address-book--plus {width:20px; height:20px; background-position: -48px -4px}
.address-book-blue {width:20px; height:20px; background-position: -26px -26px}
.address-book-open {width:20px; height:20px; background-position: -26px -48px}
В итоге

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

И еще

Работать с TexturePacker можно из под командной строки. Более подробно можно ознакомиться в справке.

Смотрите также:

пятница, 29 августа 2014 г.

Emoji на вашем сайте

Что такое Emoji?

Emoji - это способ передачи электронных сообщений, состоящих не из букв, а из значков и смайликов. Придумали такой способ общения в Японии и вскоре он получил популярность по всему миру. С подробной историей появления и развития вы можете ознакомиться здесь.

Как это выглядит?

Вот так:



Изображения вставляются прямо в текст. Каждая иконка имеет свой юникод, такой же как и обычный текстовый символ. Все иконки делятся на несколько семантических групп:
  1. Эмоции
  2. Декорации
  3. Транспорт и навигация
  4. Закрытые (внутри геометрической фигуры)
  5. Несортированные
  6. Дополнительные
У каждой группы свой диапазон юникодов. Более подробно можно ознакомиться по ссылке.

В чем заключается трудность

Дело в том, что на сайтах обычно используется кодировка UTF-8. И отображаться на таком сайте наш пример будет так:



А всё потому, что в кодировке UTF-8 нет описания для этих символов. Большинство имеют код из неиспользуемого диапазона начиная с 4 байт.

Поспешу сообщить, что не всё так плохо. И уже сегодня некоторые браузеры решили проблему самостоятельно. Они находят в тексте такие символы и подменяют из на свои изображения.

Вот наш пример в InternetExplorer 11 (Windows 8.1):



В FireFox 31:



В Mobile Safari (iOS):



Но в Chrome мы увидим всё тот же набор квадратиков, который называется шумом:



Отсюда выделим следующие проблемы:
  • Отображение шума вместо иконок в некоторых браузерах
  • Не одинаковый вид на различных устройствах

Что делать?

А делать мы будем ровным счетов тоже самое, что делают остальные браузеры: искать символы в тексте и подменять их на свои изображения c помощью JavaScript.

Поиск и замена символов на иконки

Подготовка

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

Я нашел такое изображение в проекте модулей для node.js:



Загрузить файл можно по ссылке: https://raw.githubusercontent.com/node-modules/emoji/master/lib/emoji.png

Там же я нашел и описание для этой сетки иконок в CSS-файле:
... .emoji { background: url("emoji.png") top left no-repeat; width:20px; height: 20px; } .emoji2600 { background-position: -500px -120px; } .emoji2601 { background-position: -500px -140px; } .emoji2614 { background-position: -500px -200px; } .emoji26c4 { background-position: -520px -200px; } .emoji26a1 { background-position: -520px -100px; } .emoji1f300 { background-position: -20px -500px; } .emoji1f301 { background-position: -20px -520px; } .emoji1f302 { background-position: -20px -540px; } .emoji1f303 { background-position: -20px -560px; } .emoji1f304 { background-position: -20px -580px; } ...
Файл доступен по адресу: https://raw.githubusercontent.com/node-modules/emoji/master/lib/emoji.css

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

Алгоритм будет следующий:
  1. Ищем в тексте символы с юникодом в известных нам диапазонах.
  2. Заменяем найденные символы на текстовые элементы span, для которых указываем CSS-класс с HEX-кодом.

Таким образом, вместо emoji-символов мы получим span-элементы , с заданными размерами и фоновым изображением. Они будут корректно отображаться всегда и во всех браузерах.

Анализ

Проанализировав таблицу символов, я поделил их на несколько групп по диапазону кодов:

Группа Размер символа Коды
1. Флаги 8 байт Представлены в виде 2-х суррогатных пар символов в диапазоне: \ud83c\udde8-ud83c\uddfa (1-я пара) + \ud83c\udde7-\ud83c\uddfa (2-я пара)
2. Числа 4 байта Представлены в виде двух 2 байтных символов идущих подряд с диапазоном \u0023-\u0039 (1-й символ) и \u20E3 (2 символ)
3. Несортированные 3 байта Символы с кодами от \u2139 до \u3299
4. Пунктуация 3 байта Два символа с кодами \u203C и \u2049
5. Все остальные 4 байта Представлены в виде суррогатной пары в диапазоне \ud800-\udbff (1-я часть пары) + \udc00-\udfff (2-я часть пары)

Суррогатные пары

Что это такое?

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

В нашем случае большинство emoji-иконок описываются кодами превышающими формат UTF-8. Поэтому мы использовали суррогатные пары в приведенных выше диапазонах. Для этого использовался такой вот метод:
function GetHexFromSurrogatePair (a, b) { return((a - 0xD800) * 0x400 + (b - 0xDC00) + 0x10000); }
Но, так как мы будем искать по юникоду, нам нужен обратный метод:
function GetSurrogatePairFromHex (hex) { var a = Math.floor((hex - 0x10000) / 0x400) + 0xD800, b = (hex - 0x10000) % 0x400 + 0xDC00; return(['\\u' + a.toString(16), '\\u' + b.toString(16)]); }
Код

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

1. Флаги:
string = string.replace(/(\ud83c[\udde8-\uddfa])(\ud83c[\udde7-\uddfa])/g, function (match) { var hex = [ GetHexFromSurrogatePair(match.charCodeAt(0), match.charCodeAt(1)).toString(16), GetHexFromSurrogatePair(match.charCodeAt(2), match.charCodeAt(3)).toString(16) ].join(''); //--- return(['<span class="emoji emoji', hex, '"></span>'].join('')); });
2. Числа:
string = string.replace(/(\ud83c[\udde8-\uddfa])(\ud83c[\udde7-\uddfa])/g, function (match) { var hex = [ GetHexFromSurrogatePair(match.charCodeAt(0), match.charCodeAt(1)).toString(16), GetHexFromSurrogatePair(match.charCodeAt(2), match.charCodeAt(3)).toString(16) ].join(''); //--- return(['<span class="emoji emoji', hex, '"></span>'].join('')); });
3. Несортированые:
string = string.replace(/[\u0023-\u0039]\u20E3/g, function (match) { var hex = [ match.charCodeAt(0).toString(16), match.charCodeAt(1).toString(16) ].join(''); //--- return(['<span class="emoji emoji', hex, '"></span>'].join('')); });
4. Пунктуация:
string = string.replace(/[\u2139-\u3299]/g, function (match) { var hex = match.charCodeAt(0).toString(16); //--- return(['<span class="emoji emoji', hex, '"></span>'].join('')); });
5. Все остальные:
string = string.replace(/[\u203C\u2049]/g, function (match) { var hex = match.charCodeAt(0).toString(16); //--- return(['<span class="emoji emoji', hex, '"></span>'].join('')); });
Теперь осталось собрать и причесать весь код в один итоговый класс, который будет выполнять замену всех групп по очереди:
/** * Emoji class * @description http://as3coder.blogspot.com/2014/08/emoji.html * @author AS3Coder */ (function(){ /** * Define public access * @private */ var emoji = window.emoji = {}; emoji.replace = Replace; /** * Grouping by range * @constant * @private */ var GROUPS = [ [/(\ud83c[\udde8-\uddfa])(\ud83c[\udde7-\uddfa])/g, ReplaceFlags], // Flags [/[\u0023-\u0039]\u20E3/g, ReplaceNumbers], // Numbers [/[\u2139-\u3299]/g, ReplaceStandard], // Unsorted [/[\u203C\u2049]/g, ReplaceStandard], // Punctuation [/([\ud800-\udbff])([\udc00-\udfff])/g, ReplaceSurrogate] // Other (surrogate pairs) ]; /** * Method to replace all emoji characters in the icon * @param {String} Source string * @return {String} * @public */ function Replace (source) { var pattern; //--- for(var i=0, j=GROUPS.length; i<j; i++) { pattern = GROUPS[i]; if(pattern && pattern[0] && pattern[1]) { if(source.match(pattern[0])) { source = source.replace(pattern[0], pattern[1]); } } } //--- return(source); } /** * Method to replace flags * @return {String} * @private */ function ReplaceFlags (match) { return(GetHtmlCodeFromHex( [ GetHexFromSurrogatePair(match.charCodeAt(0), match.charCodeAt(1)).toString(16), GetHexFromSurrogatePair(match.charCodeAt(2), match.charCodeAt(3)).toString(16) ].join(''))); } /** * Method to replace numbers * @return {String} * @private */ function ReplaceNumbers (match) { return(GetHtmlCodeFromHex(match.charCodeAt(0).toString(16) + match.charCodeAt(1).toString(16))); } /** * Method to replace srandard charters * @return {String} * @private */ function ReplaceStandard (match) { return(GetHtmlCodeFromHex(match.charCodeAt(0).toString(16))); } /** * Method to replace surrogate pairs * @return {String} * @private */ function ReplaceSurrogate (match, p1, p2) { return(GetHtmlCodeFromHex(GetHexFromSurrogatePair(p1.charCodeAt(0),p2.charCodeAt(0)).toString(16))); } /** * The method returns the hex code for a surrogate pair * @return {String} * @private */ function GetHexFromSurrogatePair (a, b) { return((a - 0xD800) * 0x400 + (b - 0xDC00) + 0x10000); } /** * The method returns an html code for icon image * @param {String} hex * @return {String} * @private */ function GetHtmlCodeFromHex (hex) { return(['<span class="emojic"><span class="emoji emoji', hex, '"></span><span class="emojit">&#x', hex, ';</span></span>'].join('')); } //--- })();
Пример. Нужно смотреть в разных браузерах

Original text: After replacing:

Исходный код примера (163 кб)

Смотрите также:

четверг, 7 августа 2014 г.

Сохранить изображение с камеры на JavaScript

Я уже писал, о том как сохранить изображение с камеры на ActionScript 3.0. Теперь самое время разобраться как сделать то же самое на JavaScript.

Вывод изображения с камеры

Для вывода изображения с камеры нам понадобится video-элемент. В нем мы будем отображать потоковое видео с веб-камеры. На странице выглядеть это будет так:
<video autoplay id="video"></video>
Также нам понадобиться метод navigator.getUserMedia. С помощью этого метода мы можем попросить браузер вернуть нам медиаданные пользователя, а именно: изображение с камеры и звук с микрофона. Метод довольно новый и реализован еще не во всех обозревателях (по данным caniuse.com в Chrome 21+, FireFox 17+ и Opera 18+), поэтому добавим такую вот обвязку:
navigator.getUserMedia = (navigator.getUserMedia ||
                          navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia ||
                          navigator.msGetUserMedia);
Теперь попробуем вызвать метод:
navigator.getUserMedia({ video : true }, function (){}, function(){});
В первом параметре мы указываем тип необходимых нам данных. Допустимо два параметра audio и video. В нашем случае это только video. После вызова пользователь увидит сообщение с запросом на разрешение использовать указанные устройства:

Снимок в Opera 23.0

Для реакции на выбор пользователя имеются второй и третий параметры. В них указываются ссылки на обработчики событий. Второй вызывается, если доступ к камере разрешен. Третий, если доступ запрещен.
navigator.getUserMedia({ video : true }, 
//---
function ()
{
  // Доступ к камере разрешен
}, 
function()
{
  // Доступ к камере запрещен
});
Если доступ к камере имеется, то в соответствующем обработчике будет единственный аргумент - ссылка на потоковое видео с камеры. Чтобы отобразить видео, его нужно задать ранее созданному video-элементу c помощью URL.createObjectURL:
navigator.getUserMedia({ video : true }, 
//---
function ()
{
  var video = document.getElementById('video');
  video.src = window.URL.createObjectURL(stream);
}, 
function()
{
  alert('No access to the camera!')
});
В старой Opera (которая Presto) формат параметров и ссылка на локальный медиапоток немного отличается. В рамках данной статьи, мы этого рассматривать не будем.
После того как страница получает видео с камеры, на вкладке появляется индикатор записи. Например в Chrome это выглядит так:



Снимок с экрана

Для того, чтобы сделать снимок с video-элемента, нам понадобится canvas-элемент.
<canvas id="canvas"></canvas>
Только этот элемент может снимать растровые изображения с любого элемента на странице. Для этого у двухмерного контекста имеется метод .drawImage(); В нашем случае мы будем снимать изображение с video-элемента, в котором отображается видео с камеры.
var context = canvas.getContext('2d');
context.drawImage(video, 0, 0);
Сборка файла изображения

Теперь изображение можно открыть в отдельном окне, используя адрес полученный из метода .toDataURL(); Здесь вы можете получить изображения в необходимом вам формате. Для этого достаточно указать в первом параметре MIME-тип файла. Мы будем использовать PNG-формат.
canvas.toDataURL('image/png');
Открыв файл в новом окне, можно заметить, что изображение описывается прямо в адресной строке закодированное в системе Base64.



Для работы с Base64 в JavaScript имеются методы .atob(); и .btoa(); Для декодирования строки Base64 в бинарные данные представленные в UTF-8 мы будем использовать .atob();
var utf8 = atob(canvas.toDataURL('image/png').split(',')[1]);
Получив бинарные данные файла, мы должны оформить их в файл. Для работы с файлами в JavaScript имеется объект Blob. Чтобы записать данные в файл, по-символьно пройдемся по строке в UTF-8 и соберем в Uint8Array. В итоге получим вот такой метод:
function base64toblob (base64)
{
  var utf8 = atob(base64),
  array = [];
  //---
  for(var i = 0, j = utf8.length; i < j; i++)
    array.push(utf8.charCodeAt(i));
  //---
  return(new Blob([new Uint8Array(array)], {type: 'image/png'}));
}
Сохранение файла

Теперь о том, как сохранить файл на локальный диск пользователя. Мы воспользуемся готовым решением от Eli Grey, за которое ему огромное спасибо. Речь идет о реализации заявленного FileSaver для большинства современных браузеров. Итак, скачиваем FileSaver.js и подключаем к нашей странице. Скрипт распространяется с лицензией X11/MIT.
<script type="text/javascript" src="filesaver.js"></script>
Нам необходимо только вызвать единственный метод saveAs(); в который передаем ссылку на файл и его название:
saveAs(base64toblob(canvas.toDataURL('image/png').split(',')[1]), 'image_from_camera.png');
Готовый пример и исходный код под катом.

пятница, 2 декабря 2011 г.

Сохранение звука с микрофона на ActionScript 3.0

То, что недавно казалось фантастикой, сегодня уже реальность. Начиная с версии FlashPlayer'a 10.1 у класса Microphone появилось событие sampleData.

SampleDataEvent

Это событие отправляется когда в буфере микрофона появляются аудио-данные. Событие имеет свойство data, которое содержит образцы записанных с микрофона данных. Естественно данные приходят в сыром формате. И проиграть их вне FlashPlayer'a не получиться. Поэтому их необходимо декодировать, предварительно собрав необходимое количество в бинарный массив ByteArray.

//
// Объявляем бинарный массив для хранения полученных с микрофона аудио-данных
var _samples_arr:ByteArray = new ByteArray();;
//
// Получаем экзмпляр микрофона
var _microphone:Microphone = Microphone.getMicrophone(-1);
//
// Вешаем обработчик события 
_microphone.addEventListener(SampleDataEvent.SAMPLE_DATA, onMicrophoneSampleData, false, 0, true);
//
// Обработчик обновления данных в микрофоне
function onMicrophoneSampleData (e:SampleDataEvent):void
{
  //
  // Добавляем полученные данные в биннарный массив
  _samples_arr.writeBytes(e.data);
}

Для начала выполним преобразование в .wav-формат.

WAVWriter

Специально для этого в Adobe написали класс WAVWriter.as. Останавливаться на нём не будем, потому что он довольно простой в использовании:
//
// Объявляем бинарный массив для данных .wav-файла
var wav_file:ByteArray = new ByteArray();
//
// Объявляем и настроиваем энкондер
var writer:WAVWriter = new WAVWriter();
writer.numOfChannels = 1;
writer.sampleBitRate = 16;
writer.samplingRate = 44100;
//
// Декодируем данные с микрофона в wav-формат
writer.processSamples(wav_file, _samples_arr, 44100, 1);

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

Но мы пойдем дальше. И рассмотрим преобразование наших данных в .mp3-формат. Да, такое уже возможно и реализовано. Говорим спасибо Cyril Diagn за его работу в этом направлении, а именно проект Shine MP3 Encoder on Alchemy.

Shine MP3 Encoder on Alchemy

Это .swc-библиотека с классом ShineMP3Encoder для преобразования данных из .wav-формата в .mp3. Код портирован с помощью Alchemy из энкодера написанного на С, автором которого является Gabriel Bouvigne.

Пример использования:
//
// Обнуляем позицию в массиве .wav-файла
wav_file.position = 0;
//
// Объявляем mp3-энкодер
var _mp3_encoder:ShineMP3Encoder = new ShineMP3Encoder(wav_file);
//
// Вешаем обработчики событий
_mp3_encoder.addEventListener(Event.COMPLETE, onMP3EncoderComplete, false, 0, true);
_mp3_encoder.addEventListener(ProgressEvent.PROGRESS, onMP3EncoderProcess, false, 0, true);
//
// Начинаем кодирование
_mp3_encoder.start();
//
// Обработчик процесса кодирования
function onMP3EncoderProcess (e:ProgressEvent):void
{
  trace("Encoding to mp3 ... " + Math.ceil(e.bytesLoaded * 100 / e.bytesTotal) + "%");
}
//
// Обработчик завершения кодирования
function onMP3EncoderComplete (e:Event):void
{
  trace("Encoding to mp3 complete!")
}

Теперь, после преобразования мы можем сохранить .mp3-файл штатными средствами энкодера. Для этого имеется метод saveAs()
_mp3_encoder.saveAs('record.mp3');

Если же есть необходимость отправить полученный .mp3-файл на сервер, мы можем сделать это самостоятельно, получив его данные во свойстве mp3Data.
var mp3_file:ByteArray = _mp3_encoder.mp3Data;

Ну и как обычно, простейший пример всего вышеописанного:


Ссылки по теме:
       

вторник, 25 октября 2011 г.

Доверенные .swf-файлы

С недавнего времени в контекстном меню FlashPlayer'a появился новый пункт "Глобальные настройки". А именно с версии 10.3.



Если с "Хранилищем", "Камерой и микрофоном" и "Воспроизведением" всё понятно (они итак были доступны в пункте "Параметры..."), то вот во вкладке "Дополнительно" появились доколе неизвестные настройки.

Подробнее я хочу остановить на "Настройках доверенной папки..."



Что за доверенная папка?

На самом деле слово "папки" немного вводит в заблуждение. Естественно здесь указываются .swf-файлы, которым пользователь явно доверяет. А именно:
  • домен, с которого загружаются .swf-файлы,
  • путь к локальному .swf-файлу на компьютере пользователя,
  • путь к локальному каталогу, в котором содержаться .swf-файлы
И что же мы доверяем (разрешаем) указанным файлам?

С версии 10.1 локально запущенным .swf-файлам запрещается загружать данные из сети и из локального диска пользователя. Так вот указав, что этот .swf-доверенный ему разрешается делать эти запросы.

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

Для чего указывается домен и что мы ему доверяем, я так и не разобрался. В cправке тоже ничего по поводу доменов. Может разрешаем локальным .swf-файлам загружать данные с этого домена? Не знаю. Не проверял. Может быть вы знаете?


К чему я завел этот разговор?

Недавно пришлось вернуться к одному старому проекту. Проект представляет собой простую презентацию с видео и небольшим каталогом. И вот тут, я столкнулся с тем, что главный .swf-файл зашитый в .exe-файл FlashPlayer'a не может подгрузить данные с каталога, который лежит рядом. Получаю сообщение с ошибкой о нарушении политики безопасности. Удивление конечно было огромным, когда я узнал, что в новых версиях плеера этого делать нельзя.

Чтож? Пришлось разбираться...

Как лечиться?

Ну во-первых, указать доверенный .swf-файл может сам пользователь в соотвествующем окне, о котором я говорил выше.

Во-вторых, можно сделать это за пользователя (естественно с помощью каких-то оберток или стартеров). Для этого в системе (в качестве примера возьму Windows 7, об остальных операционных системах информацию можно найти в справке) имеются каталоги, в которых хранятся .cfg-файлы конфигурации безопасности FlashPlayer'a. Таких каталогов два:

1. Для всех учетных записей системы.

C:\WINDOWS\system32\Macromed\Flash\FlashPlayerTrust

2. Для конкретного пользователя.

C:\Users\JohnD\AppData\Roaming\Macromedia\Flash Player\#Security\FlashPlayerTrust

В эти каталоги можно добавлять свои .cfg-файлы с любым именем. Простой текстовый файл, где каждая строчка - это путь до доверенных .swf-файла или папки.

Все современные среды разработки создают свои .cfg-файлы и при создании проекта дописывают в него в качестве доверенной папки папку нового проекта. Именно поэтому многие не заметили этого нововведения. Например FlashDevelop создает вот этот файл:

C:\Users\AS3Coder\AppData\Roaming\Macromedia\Flash Player\#Security\FlashPlayerTrust\FlashDevelop.cfg

А для профилактики подобных ситуаций автор кода может узнать каким образом запущен .swf-файл. Для этого существует свойство Security.sandboxType

Итого

Adobe окончательно уводит FlashPlayer с локального использования в веб. Не пишите больше локальных приложений для него, без оберток, таких как Zinc или AIR.

       

вторник, 25 января 2011 г.

Политика безопасности во Flash Player. Наиболее частные столкновения.

Часто вы сталкивались с ситуацией, когда ваш код не работает по непонятным причинам? Вам кажется, что всё уже проверено сотни раз и вы с уверенностью говорите себе, что здесь нет ошибок, и уже готовы биться головой о клавиатуру :) Спешу вас утешить, скорее всего ошибка не в коде.

В чем же дело?

А дело может быть в том, что вы нарушаете политику безопасности Flash Player, сами того не зная. Иногда Flash Player просто промолчит об этом :)

Как это предупредить?

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

В этом посте я хочу рассказать о наиболее частых нарушениях политики безопасности, с которыми мы сталкиваемся.

Загрузка контента с доменов отличных, о того с которого запущена страница с .swf-файлом

*.load();

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

BitmapData.draw();

Метод не отрисует дисплей объект, если в нем есть загруженный контент с другого домена без разрешения. Это касается дочерних элементов класса Loader, и даже TextField, если в нем есть картинки вставленные посредством HTML-разметки.

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

Как получить разрешение?

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

1. checkPolicyFile

Это файл, где перечислены домены, которым разрешено использовать контент. Называться такой файл должен сrossdomain.xml и лежать в корне сайта. Содержимое должно выглядеть следующим образом:

<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="
yoursite.com"/>
</cross-domain-policy>

Когда .swf-файл, запущенный с вашего домена, пытается выполнить запросы на другой домен, Flash Player делает автоматически делает запрос на сrossdomain.xml расположенный на другом домене. Если в нем указано разрешение для вашего домена, то Flash Player разрешит в полной мере выполнять запросы.

2. Security.allowDomain() или Security.allowInsecureDomain()

Этот способ предусмотрен для исполняемых .swf-файлов. Если Flash Player встретит в сценарии метод Security.allowDomain() или Security.allowInsecureDomain() (для https-протокола) с параметром равным доменному имени вашего сайта, то он разрешает исполнение сценариев на вашем сайте.

System.allowDomain("yoursite.com");

Взаимодействие с клиентским окружением

Еще одной из частых и самых болезненых, является ситуация когда не выполняются методы никак не связанные с сетью. Болезнь заключается в том, что Flash Player, просто молчит о нарушениях. Приведу список наиболее частых методов, в которых мы сталкиваемся с этим.

FileReference.browse();

Метод не выполнится, если внутри .swf-файла не было события нажатия клавиши мыши.

SharedObject.flush();

Метод не выполнится если размер .swf-файла встроенного на страницу меньше окна с параметрами Flash Player'a (215 x 128).

LocalConnection.send();

Метод не выполнится если вкладка со страницей, на которой запущен .swf-файл, неактивна.

Stage.displayState = StageDisplayState.FULL_SCREEN;

Метод не выполнится, если внутри .swf-файла не было события нажатия мыши.


...

Если вы сталкивались еще с чем-то подобным, пишите в комментарии я дополню этот список.

Доступ к HTML-окружению на странице

.swf-файл загруженный с другого домена (даже с разрешением) не имеет доступ к HTML-окружению на вашей странице. Для этого ему нужно разрешение. Только на этот раз, вы выдаете его сами.

При вставке .swf-файла на страницу необходимо указать параметр AllowScriptAccess с соответствующим параметром:
  • always - Разрешает доступ всем .swf-файлам
  • sameDomain - Разрешает доступ .swf-файлами, загруженным с того же домена, что и страница
  • never - Запрещает доступ всем .swf-файлам
<embed AllowScriptAccess="always" height="100" src="http://www.foreigndomain.com/example.swf" type="application/x-shockwave-flash" width="100"></embed>

Внимание: Учтите, когда вы открываете доступ к HTML-окружению .swf-файлам с неизвестных вам доменов, вы подвергаете всю безопасность на вашей страницы.

Дополнительный материал для изучения

Для более детального ознакомления со всеми правилами безопасности Flash Player, вы можете заглянуть официальную справку на русском языке в раздел "Безопасность проигрывателя Flash Player".

Также смотрите спецификацию по файлу crossdomain.xml
      

Поиск по блогу

Обо мне



Farid Shamsutdinov (AS3Coder)
Russia, Tatarstan, Kazan
as3coder@gmail.com

Подробнее...

Постоянные читатели

© 2014 Farid Shamsutdinov. При копировании материалов, ссылка на источник обязательна. Технологии Blogger.