Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   чат со смайлами AS 3.0 (http://www.flasher.ru/forum/showthread.php?t=88524)

ALiЕN2006 24.11.2006 22:57

чат со смайлами AS 3.0
 
Есть идеи?

MerlinTwi 25.11.2006 01:39

Есть :)
 
В AS3 в классе TextField добавились новые методы типа getCharBoundaries, что значительно упрощает подстановку смайликов на свои места.
Технология прежняя, в тексте заменяем смайлик на пробел, а поверх текста в нужное место аттачим мувик со смайлом.
Ниже код основного класса, когда я проводил эксперименты с этим. Что он делает:
1. Получает текст одной мессаги в которой смайлы заменены на спецсимвол за которым идет номер смайла, типа: "test :bigsmile: end" --> "test @01 end"
2. Составляется таблица стилей под каждый смайлик
setStyle(".smile"+i, {letterSpacing:smile_mc.width});
т.о. один символ такого стиля будет шириной в мувик смайла.
3. Выводим в текстовое поле текст по частям до каждого смайлика
3.1. htmlText+="test "
3.2. вместо смайла ставим пробел со стилем смайла. htmlText+='<SPAN class="smile'+smileNum+'"> </SPAN>';
3.3. вычисляем прямоугольник этого пробела. getCharBoundaries( tf.text.length-1 );
3.4. аттачим мувик смайла точно поверх пробела.
3.5. повторить... htmlText+=" end"

Собственно все.
По результатам тестов, лучше выводить не весь текст чата в одно текстовое поле (чат в 20кб. парсился более 3х секунд), а каждую мессагу в отдельный мувик с текстом и смайлами (теже 20кб. парсились 300мс.)

Код:

/**
* Одна строка чата
* @author Merlin
* @version 1.0
*/
package com.chat {
        import flash.display.Sprite;
        import flash.display.DisplayObject;
        import flash.utils.getDefinitionByName;
        import flash.text.TextField;
        import flash.text.StyleSheet;
        import flash.geom.Rectangle;
        import com.controls.Skin;
        import com.chat.ChatConstants;

        public class ChatOneLine extends Sprite {
                /** html-текст */
                public var text:String;
                /** ник отправителя */
                public var from:String;
                /** ник отправителя в нижнем регистре*/
                public var from_lc:String;
                /** сообщение для меня или от меня (нужно подсветить) */
                public var me:Boolean;
                /** кому адресовано "[ник1][ник2]..." */
                public var to:String;
               
                /**
                * Одна строка в чате
                * @param        text        html-текст
                * @param        from        от кого
                * @param        to                к кому
                * @param        me                подсветить
                */
                function ChatOneLine(text:String, from:String="", to:String="", me:Boolean=false) {
                        this.text=text;
                        this.from=from;
                        if (from) this.from_lc=from.toLowerCase();
                        this.to=to;
                        this.me=me;
                }
               
                /** Удалить все нарисованное */
                public function clear():void {
                        while (numChildren>0) removeChildAt(0);
                }
               
                /**
                * Рисует строку чата
                * @param        width                ширина окна чата
                */
                public function draw(width:Number):void {
                        if (numChildren>0) { // текст уже был отображен.
                                if (oldWidth == width) return; // ширина такая же, ничего не трогаем
                                // ширина изменилась, удаляем старое и выводим все заново
                                clear();
                        }
                        // аттачим скин
                        var bg:DisplayObject = addChild( Skin.getSkinElement(me?"skin_chat_message_selected":"skin_chat_message") );
                        var i:Number, j:Number, c:Number, txt2:String;
                        var smileCnt:Number = 0;        // счетчик смайлов
                        var s:String = text;
                        var smile_mc:DisplayObject;
                        var r:Rectangle;

                        // Создаем стиль текста
                        if (!textStyle) {
                                textStyle = new StyleSheet();
                                textStyle.setStyle("body", ChatConstants.stylesText);
                                textStyle.setStyle(".dt", ChatConstants.stylesDate);
                                textStyle.setStyle(".to", ChatConstants.stylesTo);
                                textStyle.setStyle(".private", ChatConstants.stylesPrivate);
                                textStyle.setStyle("a", ChatConstants.stylesHref);
                                textStyle.setStyle("a:hover", ChatConstants.stylesHrefHover);
                                // создадим стили под все смайлы
                                for (i=0; i<=ChatConstants.smileMaxNum; i++) {
                                        smile_mc = Skin.getSkinElement(ChatConstants.smilePrefix+i);
                                        textStyle.setStyle(".smile"+i, {letterSpacing:smile_mc.width});
                                }
                        }

                        // выводим текст
                        var tf:TextField = bg.label;
                        i = width - this.width;
                        tf.width += i;
                        bg.bg.width += i;
                        tf.height = 200;
                        tf.styleSheet = textStyle;
                        tf.htmlText = "<body>";
                       
                        // Теперь добавляем текст по частям, до смайла
                        while ((i=s.indexOf(ChatConstants.smileSymbol))>=0) { // нашли очередной смайл
                                // вычислим что за смайлик
                                var smileNum:Number = Math.max(0, Math.min(ChatConstants.smileMaxNum, parseInt(s.substr(i+1,2), 10)));
                                txt2 = s.substr(i+3);
                                if (smileCnt < ChatConstants.smileMaxCount) {
                                        // Приаттачим
                                        smile_mc = addChild( Skin.getSkinElement(ChatConstants.smilePrefix+smileNum) );
                                        // ставим вместо смайла пробел шириной с мувик смайла
                                        tf.htmlText += s.substring(0, i)+'<SPAN class="smile'+smileNum+'"> </SPAN>';
                                        // смещаем мувик смайла
                                        r = tf.getCharBoundaries( tf.text.length-1 );
                                        smile_mc.y = r.top + r.height/2;
                                        smile_mc.x = 2 + r.left;
                                } else { // уже максимально смайлов
                                        tf.htmlText += s.substring(0, i)+' ';
                                }
                                s = txt2;
                                smileCnt++;
                        }
                        // и добавляем оставшийся текст
                        tf.htmlText += s;
                        // ограничим размер мувика по высоте текста
                        tf.height = (bg.bg.height = tf.textHeight+4) + ChatConstants.spaceBetweenMessages;
                        oldWidth = width;
                }
               
                /**
                * -----------------------------------------------
                * private
                * -----------------------------------------------
                */
                // при изменении стилей в ChatConstants нужно будет обнулить эту переменную
                // чтобы стили пересоздались
                private static var textStyle:StyleSheet;
                private var oldWidth:Number;
               
               
        }

}


Nirth 25.11.2006 11:30

По моему я вас забанил, наверное нужно будет банить по всему диапазону.

etc 25.11.2006 14:42

MerlinTwi, браво!

miramax 25.11.2006 16:46

MerlinTwi, очень, очень полезный пост :)

artcraft 25.11.2006 17:25

ценная информация

ALiEN_2OO6 12.12.2006 20:56

Очень полезный пост, на основе него сделал чат. Немного доработал, т.к. хотел что бы весь текст можно было выделить мышкой и скопировать.

Я не стал разбивать весь текст на отдельные строки, а поступил так:

При добавлении строки со смайлами в текстовое поле, я точно так же заменяю смайлики на пробел со стилем, а вот сам порядковый номер смайла (от самого начала текста) добавляю в массив arrayIco. т.е. у меня получается массив координат смайлов - вычесленные всего один раз - при добавлении строки! Это - самая долгая операция.

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

Код:


function showPictures(e){
       
        clearPictures();

        // вычисление строки в скролленом тексте. tf - TextField
        var i = tf.getLineOffset(tf.scrollV-1);
        var b = tf.getCharBoundaries(i); // первый символ в строке (х, у)

        // определить выводить ли картинку или нет
        for(var k =0; k<arrayIco.length; k++){

                var z = tf.getCharBoundaries(arrayIco[k].x);

                if(z != null ){
                       
                        if(z.y >= b.y && (z.y < (b.y+tf.height))){
                               
                                showPicture(z.x, (z.y-b.y), arrayIco[k].type);
                               
                        }
                }
        }                               
}

function clearPictures(){
        while (pictures.numChildren>0) pictures.removeChildAt(0);
}

function showPicture(x, y, type){
       
        var pic:Sprite;
        switch (type){
                case "smile1":
                        pic = new smile1();
                        pic.x = x;
                        pic.y = y;
                        break;
                case "smile2":
                        pic = new smile2();
                        pic.x = x;
                        pic.y = y;
                        break;
                default:
                        pic = new smile_default();
                        pic.x = x+7;
                        pic.y = y+1;
                        break;
        }
        pictures.addChild(pic);
       
}


_Smirnoff 18.12.2007 17:08

Как я смотрю, здесь везде алгоритм отображения строки в чат.А нету алгоритма, когда пользователь формирует у себя на клиенте строку со смайлами, которую отсылает на сервер.Браво то браво, но на половину!

Если работать с полем для ввода, таким же текстфилдом, то к нему нельзя будет применить StyleSheet.

Note: A text field with a style sheet is not editable. In other words, a text field with the type property set to TextFieldType.INPUT applies the StyleSheet to the default text for the text field, but the content will no longer be editable by the user. Consider using the TextFormat class to assign styles to input text fields.

Вот так вот!Как быть то?

terbooter 20.12.2007 09:53

Цитата:

Сообщение от _Smirnoff
Вот так вот!Как быть то?

Где вопрос там и ответ
Цитата:

Сообщение от _Smirnoff
Consider using the TextFormat class to assign styles to input text fields.


ulik 29.01.2008 15:22

>> доработал. Не заменяю коды смайлов ":), ;) и т.д." на пробелы, а просто меняю их цвет в цвет фона (в моем случае фон монотонный) тем самым, пользователь при копировании сообщения копирует и код смайлов, в отличии от вашего случая. Но вариант не универсален. Думаю над этим...

зы: Нашел версию для as2.0,кому нужно: http://www.gchats.com/products/16_gc...component.html

Не совсем в тему, но, __etc, не охота тему новую ради ссылки создавать. Думаю, согласишься, что бессмысленно.

terbooter 30.01.2008 12:07

С заменой на пробелы у меня тоже косяк - автоформат начинает глючить.
Я тоже меняю цвет на цвет фона

ulik 30.01.2008 16:53

RE: молодец, конечно, но
код:
Код:

var st:String = "test\n\ntest";
txt.htmlText=st;
txt.multiline=true;
txt.autoSize=TextFieldAutoSize.LEFT;
for (var i=0; i<txt.text.length; i++) {
        trace(i,txt.text.charAt(i),txt.getCharBoundaries(i));
}

Получаем трейс вида:
Код:

0 t (x=2, y=2, w=5, h=13.9)
1 e (x=7, y=2, w=7, h=13.9)
2 s (x=14, y=2, w=5, h=13.9)
3 t (x=19, y=2, w=5, h=13.9)
4
 null
5
 null
6 t null
7 e null
8 s null
9 t null

getCharBoundaries умирает при виде \n,\r,<br/>,<p></p>... вобщем, при переносе строки. Этот баг исправлен лишь в плеере 9.0.r115.

DRAGOnoid 30.01.2008 23:15

MerlinTwi - всегда рад твоим поставм =) и за этот огромное пасибо!

люди не ленитесь исходники оставлять - так возьни с копи паст кодом меньше.

_Smirnoff 31.01.2008 00:02

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

terbooter 31.01.2008 08:06

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

MerlinTwi 31.01.2008 13:39

Цитата:

Сообщение от terbooter
С заменой на пробелы у меня тоже косяк - автоформат начинает глючить.
Я тоже меняю цвет на цвет фона

При этом будут два новых косяка:
1. Графическая картинка смайлика должна не превышать по размерам текстовое написание смайла. Если картинка смайла длинная, а написать его надо типа :beer: то смайлик будет залезать на соседние буквы
2. Текстовое написание смайлика может разбиваться при переносе на другую строчку, а пробел (или другой невидимый спецсимвол) нет. И получите текст смайлика на двух строчках, а сама картинка висит за границей текстового поля.

ALiEN_ 31.01.2008 20:13

Цитата:

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

Что мешает сделать как я описал выше? Например есть смайл "=)))))))))))" Это картинка катающегося клобка. Не меняем нашу строку "=)))))))))))" ни на какой пробел, ни на точку, а оставляем как есть, НО! подбираем размер шрифта так, что бы эта строка была по ширине картинки нашего смайла и делаем эту строку цветом фона.

Спрашивается зачем такая сложность? Отвечу, например при выделении этого текста и копировании в буфер обмена - вся фраза включая смайл, сохранит свой первоначальный вид написанный автором, а не будет иметь что-то типа: "Хороший анекдот :lol: ржу!"
Будет как писал автор: "Хороший анекдот =))))))))))) ржу!"

Если интересно выше есть даже исходник как это сделать от автора ALiEN2006. Либо пиши на почту, постараюсь найти исходник целиком.

terbooter 13.02.2008 10:51

Вложений: 2
Цитата:

Сообщение от MerlinTwi
При этом будут два новых косяка:
1. Графическая картинка смайлика должна не превышать по размерам текстовое написание смайла. Если картинка смайла длинная, а написать его надо типа :beer: то смайлик будет залезать на соседние буквы
2. Текстовое написание смайлика может разбиваться при переносе на другую строчку, а пробел (или другой невидимый спецсимвол) нет. И получите текст смайлика на двух строчках, а сама картинка висит за границей текстового поля.

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

UP вот какая проблема есть:
Кусок кода к картинке где смайл НЕ выходит за границу текстового поля
Код:

return "<span class = '"+s+"' >_</span>" ;
Кусок кода к картинке где смайл выходит за границу текстового поля
Код:

return "<span class = '"+s+"' > </span>" ;

Akhmedov 22.03.2009 21:20

Добрый вечер!
в данной теме я выложил материал по поводу использования смайликов в чате. Чтобы не дублировать кидаю ссылку http://www.flasher.ru/forum/showthre...691#post807691


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

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