Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Как сделать смайлы на AS3? (http://www.flasher.ru/forum/showthread.php?t=128905)

DARIUS1 20.08.2009 02:47

Как сделать смайлы на AS3?
 
Помогите пожалуйста)

Как сделать смайлы на AS3?

Делаю чат! Незнаю как сделать смайлы!
Эта методика мне не помогла! http://www.delphimaster.ru/articles/flash/index.html
Надо придумать как сделать чтобы в динамическом поле текста т.е. в самом чате
это "=)" заменялось этим :) то есть текст определённой картинкой! И конечно же я не знаю как сделать так чтобы смайл был ровно в строчке и его можно было вставлять между текста!

wvxvw 20.08.2009 02:55

Идти сюда и качать примеры:
http://labs.adobe.com/technologies/textlayout/

DARIUS1 20.08.2009 04:50

Цитата:

Сообщение от wvxvw (Сообщение 844094)
Идти сюда и качать примеры:
http://labs.adobe.com/technologies/textlayout/

СПАСИБО) Text Layout Framework Inline Images это вроде то что нужно! а как сделать саму функцию замены текста ?

Obi 20.08.2009 14:23

Строго говоря, задача состоит в том, чтобы полученный хмл вида:
Код:

<flow:TextFlow whiteSpaceCollapse="preserve" xmlns:flow="http://ns.adobe.com/textLayout/2008">
  <flow:p>
      <flow:span>Привет, Мальчики :)</flow:span>
  </flow:p>
</flow:TextFlow>

привести к виду:
Код:

<flow:TextFlow whiteSpaceCollapse="preserve" xmlns:flow="http://ns.adobe.com/textLayout/2008">
  <flow:p>
      <flow:span>Привет, Мальчики </flow:span><flow:img height="auto" width="auto" source="smile.png"/>
  </flow:p>
</flow:TextFlow>

Собственно берем список смайлов
Код:

smiles({smile:':)', source:'smile.png'}, {smile:';)', source:'smile2.png'})
и дальше начинаются проблемы. А проблемы начинаются, благодаря тому, что в tlf существует строгая иерархия элементов, например вот так быть не может:

Код:

<flow:span>Привет, мальчики <flow:img height="auto" width="auto" source="smile.png"/></flow:span>
Поскольку span низший по иерархии элемент, внутри него кроме текста ничего быть не может.
Значит просто преобразовать хмл в строку и пройтись циклом, заменяя все
Код:

:)
на
Код:

<flow:img height="auto" width="auto" source="smile.png"/>
не выйдет.

Я решал эту проблему следующим образом:

На входе у нас имеется xml:
Код:

<flow:TextFlow whiteSpaceCollapse="preserve" xmlns:flow="http://ns.adobe.com/textLayout/2008">
  <flow:p>
      <flow:span>Привет ;) Мальчики :)</flow:span>
  </flow:p>
  <flow:p>
      <flow:span>Как у вас дела? :)</flow:span>
  </flow:p>
</flow:TextFlow>

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

Привет ;) Мальчики :)
Сделать
Код:

<flow:span>Привет </flow:span><flow:img height="auto" width="auto" source="smile2.png"/>;)<flow:span> Мальчики </flow:span><flow:img height="auto" width="auto" source="smile.png"/>:)
Код AS3:

/**
 * Ищет в строке смайлы, и возвращает массив с их порядковыми номерами.
 *
 * @param        str    Строка, с которой работаем, без разметки.
 * @param        smiles Список смайликов, например [{smile:':)', source:'smile.png'}, {smile:';)', source:'smile2.png'}]
 * @return Массив, хранящий порядковый номер первого символа смайлика и сам смайлик, например [{position:8, smile:':)',source:'smile.png' }, {position:15, smile:';)',source:'smile2.png' }]
 *
 */

private function getSmileIndexes(str:String, smiles:Array):Array {
        var resultArr:Array = [];
        for (var i:uint = 0; i < smiles.length; i++) {
                var lastSmileIndex:int = -1;
 
                /* Пока есть смайлики, ищем их, начиная с позиции предыдущего */
                while (str.indexOf(smiles[i].smile, lastSmileIndex) > -1) {
                        var smPos:int = str.indexOf(smiles[i].smile, lastSmileIndex);
                        resultArr.push({position:smPos, str:smiles[i].smile, source:smiles[i].source});
                        lastSmileIndex = smPos + smiles[i].smile.length;
                }
        }
        /* Сортируем, чтобы в массиве смайлы располагались в том же порядке, в котором располагаются и в строке */
        resultArr.sortOn('position', Array.NUMERIC);
        return resultArr;
}

Дальше нужен метод, который по существующим индексам смайлов превратит xml:
Код:

<flow:span>Привет ;) Мальчики :)</flow:span>
в xmllist:
Код:

<flow:span>Привет </flow:span><flow:img height="auto" width="auto" source="smile2.png"/>;)<flow:span> Мальчики </flow:span><flow:img height="auto" width="auto" source="smile.png"/>:)
Код AS3:

/**
 * Преобразует xml в xmllist и заменяет текстовое представление необходимой разметкой.
 * @param        xml Хмл со смайлами, который необходимо отформатировать
 * @param        smileIndexes Список объектов, которые содержат индексы смайлов, ссылки на граф. представление смайла и текстовое представление смайла.
 * @return xmlList на основе вошедшего xml.
 */

private function getXMLListByXML(xml:XML, smileIndexes:Array):XMLList {
        var resultXMLList:XMLList = new XMLList();
        var s:String = xml.toString();
        for (var i:uint = 0; i < smileIndexes.length; i++) {
                var startStrPos:uint = 0;
 
                /*Если заменяем уже не первый смайлик в строке*/
                if (smileIndexes[i - 1]) {
                        startStrPos = smileIndexes[i - 1].position + smileIndexes[i - 1].str.length;
                }
 
                /*Создаем разметку для картинки*/
                var imgXML:XML = XML('<img width="auto" height="auto" source="'+smileIndexes[i].source+'"/>');
                imgXML.setNamespace(this.nameSpace);
 
                /*Теперь изеняем изначальный xml-нод*/
                var strXML:XML = new XML(xml.copy());
                /*Вырезаем смайлик*/
                strXML.* = s.substring(startStrPos, smileIndexes[i].position);
                /*Вставляем в xmllist сначала изначальную строку с вырезанным смайликом, потом вставляем строку для смайла*/
                resultXMLList[resultXMLList.length()] = strXML;
                resultXMLList[resultXMLList.length()] = imgXML;
        }
 
        /*Если смайликов больше одного, то вырезаем последний смайл из строки и завершаем лист последним элементом <flow:span>*/
        if (smileIndexes.length > 0) {
                strXML = new XML(xml.copy());
                strXML.* = s.substring(smileIndexes[i - 1].position + smileIndexes[i - 1].str.length, s.length);
                resultXMLList[resultXMLList.length()] = strXML;
        }
        return resultXMLList;
}

Ну собственно вот и все. Теперь осталось рекурсивно обойти все ноды.


Код AS3:

/**
 * Ищет смайлы и заменяет текстовое представление нужной разметкой
 * @param        xml Полный xml, содержащий текст и смайлы.
 * @param        smilesArr Список смайлов.
 */

private function searchSmileys(xml:XML, smilesArr:Array):void {
        for each(var x:XML in xml.*) {
        x.setNamespace(this.nameSpace);
                if (x.hasComplexContent()) {
                        searchSmileys(x, smilesArr);
                }else {
                        var s:String = x.toString();
                        var smileIndexes:Array = getSmileIndexes(s, smilesArr);
                        /*Вставляем полученный xmllist до того хмл, который нужно заменить*/
                        x.parent().insertChildBefore(x, getXMLListByXML(x, smileIndexes));
                        if (smileIndexes.length > 0) {
                                /*Удаляем уже ненужный нод*/
                                delete x.parent().*[x.childIndex()];
                        }
                }
        }
}

Вы еще не передумали? ;)

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

DARIUS1 20.08.2009 22:04

Obi

а у тя рабочий исходник не найдётся для примера? :rolleyes:

Obi 20.08.2009 22:07

Цитата:

Сообщение от DARIUS1 (Сообщение 844298)
Obi

а у тя рабочий исходник не найдётся для примера? :rolleyes:

За определенную нескромную плату найдется.

Я же все достаточно подробно разъяснил.

firsoff 27.01.2010 12:32

ммм во флекс фреймворке ( FlexSDK4) есть уже готовый конвертер, так что не надо велосипеды придумывать:

Код AS3:

 
var tf:* = TextConverter.importToFlow("text text <img src='dd/dd.jpg'> text2text2", TextConverter.HTML_FORMAT);
trace(TextConverter.export (tf, TextConverter.TEXT_LAYOUT_FORMAT,  "xmlType"));

вроде полностью решает проблему "текст" "смайл" "текст"

С уважением.

Jackson 03.02.2011 15:23

Эта штука решает проблему "текст" "смайл" "текст"?
Можно ли её вставить в Flex3?

Olmer 31.03.2012 18:13

К сожалению не совсем решает, т.к. есть такой баг https://bugs.adobe.com/jira/browse/SDK-21706
Тем кто не боится кривых решений, его можно обойти так:

Код AS3:

setInterval(richText.invalidateSize, 1000);


kelod 31.03.2012 18:35

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


Часовой пояс GMT +4, время: 11:40.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.