Как то раз, зимним вечером делать мне было нечего и решил я перевести полезный, как мне тогда показалось, пост о 15 сниппетах для Action Script 3. Оригинал можно-увидеть-там-если-кликнуть-на-это-длинное-словосочетание-через-дефис, а перевод статьи можно увидеть тут, и никуда (кроме хабраката) кликать и не нужно.
Многие дополнительные примеры кода, которых не было в оригинальной статье, предоставлены юзером Flashist.
Авторы статьи предлагают представить себе массив, в качестве колоды карт, из которой, на каждом шаге цикла, «достаётся» случайная карта, после чего она же добавляется в конец этой колоды. Лично мне не понятно, почему они не использовали стандартную функцию сортировки массивов (и векторов) с помощью которой можно было бы сделать примерно следующее:
Второй способ кажется мне, более понятным. Тем более, что это встроенное средство AS3.
Авторы предлагают такой вот простой и короткий способ позиционирования обектов. Оператор остатка от деления (%) позволяет корректно позиционировать объекты по оси X, а деление с округлением в меньшую сторону (Math.floor) помогает разобраться с расстановкой по Y.
В примере создаётся 20 объектов некоего вымышленного класса MyDisplayObject, которые располагаются внутри сетки с 5-ю столбцами. Как вы уже могли догадаться, цифра 5 в коде означает количество столбцов сетки, т.е. если бы столбцов было 7, то вместо цифры 5 мы бы ставили 7.
Базовый класс для всех контейнеров с визуальным содержимым (я сейчас говорю про DisplayObjectContainer, да да), не имеет своего метода для удаления сразу всех дочерних объектов. Не беда! =) Сделаем такой метод сами, благо, делается он совсем не сложно:
В качестве дополнения, презент вам от пользователя Flashist, который делится ещё парой функций для работы с DisplayObjectContainer и их «детьми»:
Чтобы получить URL страницы, в которую встроена флешка необходимо использовать класс ExternalInterface. Чтобы не вдаваться в лишние детали, скажу лишь, что в примере мы используем ExternalInterface для того, чтобы обратиться к DOM (Document Object Model) HTML страницы, в которую встроена наша флешка.
Недостатком этого подхода является то, что, флешка должна быть встроена в HTML страницу, с параметром allowscriptaccess установленным в sameDomain or always. Если вы сами контролируете встраивание флешки в HTML страницу, то для вас это может не быть проблемой, однако, если флешка встраивается другими людьми, этот способ может и не сработать. Для использования этого кода, не забудьте импортировать flash.external.ExternalInterface класс к себе в документ:
В качестве альтернативы можно использовать свойство url у объекта loaderInfo, к этому свойству нужно обращаться через корневой объект флешки (или через stage (прим. автора)). Используя этот способ, вы не узнаете URL HTML страницы, где расположена флешка, но сможете узнать где находится сама флешка. Этот способ позволит вам узнать, на каких доменах выложена ваша флешка.
От себя добавлю, что для того, чтобы знать, где выложена ваша флешка, а так же для сбора другой очень полезной статистической информации, можно использовать крутой-супер-пупер сервис MochiBot, я так и делаю, ага )
Этот сниппет меня самого немного порадовал, так как, несмотря на его очевидность и простоту, я не задумывался о нём раньше. Смысл в том, что передавая в функцию DisplayObjectContainer мы запускаем рекурсивный вызов этой функции, который округляет координаты самого контейнера и всех его дочерних объектов. Ну а если один из дочерних объектов является сам представителем класса DisplayObjectContainer, то в функцию передаётся уже он, и так до последнего, пока все вложенные контейнеры не будут перебраны.
Ах, да, проверка на Stage стоит для того, чтобы случайно не попробовать обратиться к свойствам x и y объекта Stage, который их не поддерживает (выдастся эксепшн).
Ну, тут уж совсем всё просто, даже и объяснять ничего не хочется ) Просто бери и юзай.
И очередной дополнительный презент от Flashist. В этот аналог функции «встроены», внимание, возможность:
а) Автоматически округлять к меньшему целому числу.
б) Автоматически округлять к ближайшему целому числу.
в) Автоматически округлять к большему целому числу.
Вау, это и правда круто:
Опять же, ничего особо сложного в этом нет, все и так должны понять. Простая и часто требуемая функция:
А это уже поинтереснее. Подобные функции часто требуются при разработке игр или приложений, где нужно реагировать на движение/положение курсора мышки:
Важно помнить, что функция возвращает угол в радианах, а не в градусах (как нам всем было бы привычней). Но с этим маленьким недостатком нам помогут разобраться следующие функции.
Полезный сниппет для создания сайтов и всяких-там регистраций в играх.
Стоит понимать, что 100% гарантии данный RegExp не даёт (прим. автора: к сожалению, пока я не видел ни одного RegExp, который бы не ошибался). В моих трёхминутных эксперементах он ошибся по-крайней мере в 3 случаях. Попробуйте проверить адреса: -mymail@mail.mail, .mymail@mail.mail и mymail@mail.mail.
Если у вас когда-нибудь была необходимость в удалении некоторых символов из строки, то вот решение ваших проблем =)
Добродушный Flashist делится с нами «продвинутой» версией этого сниппета, с помощью которого вы можете удалять любые подстроки (не только пробелы) и вставлять на их место так же, любые подстроки (не только пустую строку):
Наверно, термин Slug, правильнее всего на русский язык будет переверсти, как ЧПУ (человеко-понятные урлы), т.е. такая ссылка, которую человек может легко прочитать.
Данный сниппет берёт исходную строку и вырезает из неё все некорректные для формирования URL символы, т.е. все символы кроме латиницы, цифр, дефиса и подчёркивания. Пробелы между «корректными» словами заменяются дефисами. Так, если передать в функцию строку «Привет, это статья про Flash !^@#&*!@^#*&, ActionScript, Adobe, сниппеты и тому_подобные_штуки-дрюки», то в ответ она вернёт «-flash-actionscript-adobe-__-».
Честно говоря, данный функционал, за, наверно, уже 4 года Flash-разработок мне ни разу не потребовался, но я не исключаю, что он может быть кому-то полезен, мало ли какие-задачи встречаются у разработчиков.
А это уже интереснее, куда интереснее ) В общем сниппет позволяет очистить текст от символов HTML разметки и оставить только «чистый» текст. Вводите «Click here to find out more», а вам оставляют только «Click here to find out more.», клёво, что ещё сказать.
Опять же, с проблемой конфликтов пространств имён в XML я тоже никогда не сталкивался, но в оригинальной статье говорится, что такие проблемы иногда случаются, когда XML загружаются из разных источников.
Ну вот, наверно, и всё. Надеюсь, что эти сниппеты облегчат кому-то жизнь и будут полезны в повседневной разработке. Для себя я отметил парочку интересных, которые, думаю, ещё пригодятся мне.
Ещё раз повторюсь, что свои примеры кода к посту любезно предоставил Flashist, которому изрядно подпортили карму другие пользователи после отчаянного поста, где он советовал подумать нам всем о том, как они ничтожны. Не судите о нём строго =) Он уже и сам немного пожалел о таком теге к посту и немного дерзких комментариях. Собственно этот пост, наверно, с удовольствием опубликовал бы он сам, да только карма не позволяет (это я так типо пытаюсь выбить ему пару плюсов в карму.
Многие дополнительные примеры кода, которых не было в оригинальной статье, предоставлены юзером Flashist.
1. Случайная сортировка
for (var i:uint = 0; i < myArray.length; i++)
{
var rand:uint = int(Math.random() * myArray.length);
myArray.push( myArray.splice( rand, 1 )[0] );
}
* This source code was highlighted with Source Code Highlighter.
Авторы статьи предлагают представить себе массив, в качестве колоды карт, из которой, на каждом шаге цикла, «достаётся» случайная карта, после чего она же добавляется в конец этой колоды. Лично мне не понятно, почему они не использовали стандартную функцию сортировки массивов (и векторов) с помощью которой можно было бы сделать примерно следующее:
/**
* Специальная функция сортировки массива сортировки массива
*
* @param obj1 ссылка на 1-й элемент массива.
* @param obj2 ссылка на 2-й элемент массива.
*
* @return число, которое будет определять сортировку массива (-1, 0 или 1).
*/
public function randomizeSortFunction(obj1:Boolean, obj2:Object):int
{
var randNum:int = -1 + Math.floor((Math.random() * 3));
return randNum;
}
// Создаём ммассив и случайно сортируем его
var array:Array = [0, 1, 2, 3, 4];
array.sort(ArrayTools.randomizeSortFunction);
trace(array);
* This source code was highlighted with Source Code Highlighter.
Второй способ кажется мне, более понятным. Тем более, что это встроенное средство AS3.
2. Позиционирование объектов по сетке
Авторы предлагают такой вот простой и короткий способ позиционирования обектов. Оператор остатка от деления (%) позволяет корректно позиционировать объекты по оси X, а деление с округлением в меньшую сторону (Math.floor) помогает разобраться с расстановкой по Y.
for (var i:uint = 0; i < 20; i++)
{
var displayObject:MyDisplayObject = new MyDisplayObject();
displayObject.x = displayObject.width * ( i % 5 );
displayObject.y = displayObject.height * Math.floor( i / 5 );
addChild(displayObject);
}
* This source code was highlighted with Source Code Highlighter.
В примере создаётся 20 объектов некоего вымышленного класса MyDisplayObject, которые располагаются внутри сетки с 5-ю столбцами. Как вы уже могли догадаться, цифра 5 в коде означает количество столбцов сетки, т.е. если бы столбцов было 7, то вместо цифры 5 мы бы ставили 7.
3. Удаление всех «детей» у DisplayObjectContainer
Базовый класс для всех контейнеров с визуальным содержимым (я сейчас говорю про DisplayObjectContainer, да да), не имеет своего метода для удаления сразу всех дочерних объектов. Не беда! =) Сделаем такой метод сами, благо, делается он совсем не сложно:
/**
* Удаление всех дочерних клипов внутри какого-то родительского клипа.
*
* @param parentClip ссылка на клип, внутри которого нужно будет удалить все дочерние клипы.
*/
static public function removeAllChildren(parentClip:DisplayObjectContainer):void
{
// Пока в клипе есть хотя бы 1 дочерний клип, удаляем клип на самом нижнем слое
while(parentClip.numChildren > 0)
{
parentClip.removeChildAt(0);
}
}
* This source code was highlighted with Source Code Highlighter.
В качестве дополнения, презент вам от пользователя Flashist, который делится ещё парой функций для работы с DisplayObjectContainer и их «детьми»:
/**
* Скрытие всех дочерних клипов внутри какого-то родительского клипа.
*
* @param parentClip ссылка на клип, внутри которого нужно будет скрыть все дочерние клипы.
*/
static public function hideAllChildren(parentClip:DisplayObjectContainer):void
{
var childrenCount:int = parentClip.numChildren;
for (var childrenIndex:int = 0; childrenIndex < childrenCount; childrenIndex++)
{
parentClip.getChildAt(childrenIndex).visible = false;
}
}
/**
* Показывание всех дочерних клипов внутри какого-то родительского клипа.
*
* @param parentClip ссылка на клип, внутри которого нужно будет показать все дочерние клипы.
*/
static public function showAllChildren(parentClip:DisplayObjectContainer):void
{
var childrenCount:int = parentClip.numChildren;
for (var childrenIndex:int = 0; childrenIndex < childrenCount; childrenIndex++)
{
parentClip.getChildAt(childrenIndex).visible = true;
}
}
/**
* Удаление дочерним клипом самого себя из родительского клипа.
*
* @param child ссылка на дочерний клип.
*/
static public function childRemoveItselfFromParent(child:DisplayObject):void
{
// Если клип не создан, то прерываем функцию
if (child == null || child.parent == null)
{
return;
}
child.parent.removeChild(child);
}
parentClip.removeChildAt(0);
}
}
* This source code was highlighted with Source Code Highlighter.
4. Получение URL страницы, в которую встроена SWF
Чтобы получить URL страницы, в которую встроена флешка необходимо использовать класс ExternalInterface. Чтобы не вдаваться в лишние детали, скажу лишь, что в примере мы используем ExternalInterface для того, чтобы обратиться к DOM (Document Object Model) HTML страницы, в которую встроена наша флешка.
Недостатком этого подхода является то, что, флешка должна быть встроена в HTML страницу, с параметром allowscriptaccess установленным в sameDomain or always. Если вы сами контролируете встраивание флешки в HTML страницу, то для вас это может не быть проблемой, однако, если флешка встраивается другими людьми, этот способ может и не сработать. Для использования этого кода, не забудьте импортировать flash.external.ExternalInterface класс к себе в документ:
function get currentURL():String
{
var url:String;
if (ExternalInterface.available)
{
return ExternalInterface.call("window.location.href");
}
return url;
}
* This source code was highlighted with Source Code Highlighter.
В качестве альтернативы можно использовать свойство url у объекта loaderInfo, к этому свойству нужно обращаться через корневой объект флешки (или через stage (прим. автора)). Используя этот способ, вы не узнаете URL HTML страницы, где расположена флешка, но сможете узнать где находится сама флешка. Этот способ позволит вам узнать, на каких доменах выложена ваша флешка.
root.loaderInfo.url;
* This source code was highlighted with Source Code Highlighter.
От себя добавлю, что для того, чтобы знать, где выложена ваша флешка, а так же для сбора другой очень полезной статистической информации, можно использовать крутой-супер-пупер сервис MochiBot, я так и делаю, ага )
5. Округление координат DisplayObjectContainer объектов и их «детей»
Этот сниппет меня самого немного порадовал, так как, несмотря на его очевидность и простоту, я не задумывался о нём раньше. Смысл в том, что передавая в функцию DisplayObjectContainer мы запускаем рекурсивный вызов этой функции, который округляет координаты самого контейнера и всех его дочерних объектов. Ну а если один из дочерних объектов является сам представителем класса DisplayObjectContainer, то в функцию передаётся уже он, и так до последнего, пока все вложенные контейнеры не будут перебраны.
function roundPositions(displayObjectContainer:DisplayObjectContainer):void
{
if (!(displayObjectContainer is Stage))
{
displayObjectContainer.x = Math.round(displayObjectContainer.x);
displayObjectContainer.y = Math.round(displayObjectContainer.y);
}
for (var i:uint = 0; i < displayObjectContainer.numChildren; i++)
{
var child:DisplayObject = displayObjectContainer.getChildAt(i);
if (child is DisplayObjectContainer)
{
roundPositions(child as DisplayObjectContainer);
}else
{
child.x = Math.round(child.x);
child.y = Math.round(child.y);
}
}
}
* This source code was highlighted with Source Code Highlighter.
Ах, да, проверка на Stage стоит для того, чтобы случайно не попробовать обратиться к свойствам x и y объекта Stage, который их не поддерживает (выдастся эксепшн).
6. Случайное число в между 2-мя числами
Ну, тут уж совсем всё просто, даже и объяснять ничего не хочется ) Просто бери и юзай.
function random(min:Number, max:Number):Number
{
return min + Math.random() * (max - min);
}
* This source code was highlighted with Source Code Highlighter.
И очередной дополнительный презент от Flashist. В этот аналог функции «встроены», внимание, возможность:
а) Автоматически округлять к меньшему целому числу.
б) Автоматически округлять к ближайшему целому числу.
в) Автоматически округлять к большему целому числу.
Вау, это и правда круто:
/**
* Возвращение случайного числа в заданных рамках.
*
* @param minNum минимальное значение для случайного числа.
* @param maxNum максимальное значение для случайного числа.
* @param isNeedFloor нужно ли округлять к меньшему целому числу.
* @param isNeedRound нужно ли округлять к ближайшему целому числу.
* @param isNeedCeil нужно ли округлять к большему целому числу.
*
* @return случайное число в заданных рамках.
*/
static public function getRandomNum(minNum:Number, maxNum:Number, isNeedFloor:Boolean = false, isNeedRound:Boolean = false, isNeedCeil:Boolean = false):Number
{
var randNum:Number = minNum + Math.random() * (maxNum - minNum);
if (isNeedFloor)
{
randNum = Math.floor(randNum);
}
if (isNeedRound)
{
randNum = Math.round(randNum);
}
if (isNeedCeil)
{
randNum = Math.ceil(randNum);
}
return randNum;
}
* This source code was highlighted with Source Code Highlighter.
7. Случайное булево значение
Опять же, ничего особо сложного в этом нет, все и так должны понять. Простая и часто требуемая функция:
function get randomBoolean():Boolean
{
return Math.random() >= 0.5;
}
* This source code was highlighted with Source Code Highlighter.
8. Нахождение угла между 2-мя точками
А это уже поинтереснее. Подобные функции часто требуются при разработке игр или приложений, где нужно реагировать на движение/положение курсора мышки:
function getAngle (x1:Number, y1:Number, x2:Number, y2:Number):Number
{
var dx:Number = x2 - x1;
var dy:Number = y2 - y1;
return Math.atan2(dy,dx);
}
* This source code was highlighted with Source Code Highlighter.
Важно помнить, что функция возвращает угол в радианах, а не в градусах (как нам всем было бы привычней). Но с этим маленьким недостатком нам помогут разобраться следующие функции.
9. Перевод градусов в радианы и обратно
/**
* Функции для работы с углами.
*/
/**
* Перевод величины угла из градусов в радианы.
*
* @param angle величина угла в градусах.
*
* @return величина угла в радианах.
*/
static public function convertAngleToRadians(angle:Number):Number
{
var radians:Number = angle / 180 * Math.PI;
return radians;
}
/**
* Перевод величины угла из радианов в градусы.
*
* @param radians величина угла в радианах.
*
* @return величина угла в градусах.
*/
static public function convertRadiansToAngle(radians:Number):Number
{
var angle:Number = radians * 180 / Math.PI;
return angle;
}
* This source code was highlighted with Source Code Highlighter.
10. Проверка корректности Email
Полезный сниппет для создания сайтов и всяких-там регистраций в играх.
function isValidEmail(email:String):Boolean
{
var emailExpression:RegExp = /([a-z0-9._-]+?)@([a-z0-9.-]+)\.([a-z]{2,4})/i;
return emailExpression.test(email);
}
* This source code was highlighted with Source Code Highlighter.
Стоит понимать, что 100% гарантии данный RegExp не даёт (прим. автора: к сожалению, пока я не видел ни одного RegExp, который бы не ошибался). В моих трёхминутных эксперементах он ошибся по-крайней мере в 3 случаях. Попробуйте проверить адреса: -mymail@mail.mail, .mymail@mail.mail и mymail@mail.mail.
11. Удаление пробелов
Если у вас когда-нибудь была необходимость в удалении некоторых символов из строки, то вот решение ваших проблем =)
function stripSpaces(string:String):String
{
var s:String = string;
return s.split(" ").join("");
}
* This source code was highlighted with Source Code Highlighter.
Добродушный Flashist делится с нами «продвинутой» версией этого сниппета, с помощью которого вы можете удалять любые подстроки (не только пробелы) и вставлять на их место так же, любые подстроки (не только пустую строку):
/**
* Функция, которая будет заменять в тексте все найденные последовательности символов на новые последовательности символов.
*
* @param sourceString исходная строка, которую нужно будет очистить.
* @param oldString текст, который нужно будет заменить.
* @param newString текст, на который будет происходить замена.
*
* @return текст, с заменёнными последовательностями необходимого текста.
*/
static public function replaceText(sourceString:String, oldString:String, newString:String):String
{
// Разбиваем строку при нахождении искомой подстроки и соединяем, добавляя новую подстроку
var replacedString:String = sourceString.split(oldString).join(newString);
// Возвращаем переменную с очищенным текстом
return replacedString;
}
* This source code was highlighted with Source Code Highlighter.
12. Slugify
Наверно, термин Slug, правильнее всего на русский язык будет переверсти, как ЧПУ (человеко-понятные урлы), т.е. такая ссылка, которую человек может легко прочитать.
function slugify(string:String):String
{
const pattern1:RegExp = /[^\w- ]/g; // Matches anything except word characters, space and -
const pattern2:RegExp = / +/g; // Matches one or more space characters
var s:String = string;
return s.replace(pattern1, "").replace(pattern2, "-").toLowerCase();
}
* This source code was highlighted with Source Code Highlighter.
Данный сниппет берёт исходную строку и вырезает из неё все некорректные для формирования URL символы, т.е. все символы кроме латиницы, цифр, дефиса и подчёркивания. Пробелы между «корректными» словами заменяются дефисами. Так, если передать в функцию строку «Привет, это статья про Flash !^@#&*!@^#*&, ActionScript, Adobe, сниппеты и тому_подобные_штуки-дрюки», то в ответ она вернёт «-flash-actionscript-adobe-__-».
13. Удаление из подстрок http:// или https:// и опциональное удаление www из какой-нибудь строки
Честно говоря, данный функционал, за, наверно, уже 4 года Flash-разработок мне ни разу не потребовался, но я не исключаю, что он может быть кому-то полезен, мало ли какие-задачи встречаются у разработчиков.
function stripHttp(string:String, stripWWW:Boolean = false):String
{
var s:String = string;
var regexp:RegExp = new RegExp(!stripWWW ? "https*:\/\/" : "https*:\/\/(www\.)*", "ig");
return s.replace(regexp, "");
}
* This source code was highlighted with Source Code Highlighter.
14. Удаление HTML разметки
А это уже интереснее, куда интереснее ) В общем сниппет позволяет очистить текст от символов HTML разметки и оставить только «чистый» текст. Вводите «Click here to find out more», а вам оставляют только «Click here to find out more.», клёво, что ещё сказать.
function stripTags(string:String):String
{
var s:String = string;
var regexp:RegExp = new RegExp("<[^<]*<", "gi");
return s.replace(regexp, "");
}
* This source code was highlighted with Source Code Highlighter.
15. Удаление пространств имён XML
Опять же, с проблемой конфликтов пространств имён в XML я тоже никогда не сталкивался, но в оригинальной статье говорится, что такие проблемы иногда случаются, когда XML загружаются из разных источников.
function stripXMLNamespaces(xml:XML):XML
{
var s:String = xml.toString();
var pattern1:RegExp = /\s*xmlns[^\'\"]*=[\'\"][^\'\"]*[\'\"]/gi;
s = s.replace(pattern1, "");
var pattern2:RegExp = /<[\/]{0,1}(\w+:).*?>/i;
while(pattern2.test(s)) {
s = s.replace(pattern2.exec(s)[1], "");
}
return XML(s);
}
* This source code was highlighted with Source Code Highlighter.
P.S.:
Ну вот, наверно, и всё. Надеюсь, что эти сниппеты облегчат кому-то жизнь и будут полезны в повседневной разработке. Для себя я отметил парочку интересных, которые, думаю, ещё пригодятся мне.
Ещё раз повторюсь, что свои примеры кода к посту любезно предоставил Flashist, которому изрядно подпортили карму другие пользователи после отчаянного поста, где он советовал подумать нам всем о том, как они ничтожны. Не судите о нём строго =) Он уже и сам немного пожалел о таком теге к посту и немного дерзких комментариях. Собственно этот пост, наверно, с удовольствием опубликовал бы он сам, да только карма не позволяет (это я так типо пытаюсь выбить ему пару плюсов в карму.