![]() |
|
||||||||||
|
|||||
|
Регистрация: Nov 2006
Сообщений: 1
|
Есть идеи?
|
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В 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;
}
}
|
|
|||||
|
Et cetera
Регистрация: Sep 2002
Сообщений: 30,787
|
MerlinTwi, браво!
|
|
|||||
|
MerlinTwi, очень, очень полезный пост
![]() |
|
|||||
|
Очень полезный пост, на основе него сделал чат. Немного доработал, т.к. хотел что бы весь текст можно было выделить мышкой и скопировать.
Я не стал разбивать весь текст на отдельные строки, а поступил так: При добавлении строки со смайлами в текстовое поле, я точно так же заменяю смайлики на пробел со стилем, а вот сам порядковый номер смайла (от самого начала текста) добавляю в массив 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);
}
|
|
|||||
|
Как я смотрю, здесь везде алгоритм отображения строки в чат.А нету алгоритма, когда пользователь формирует у себя на клиенте строку со смайлами, которую отсылает на сервер.Браво то браво, но на половину!
Если работать с полем для ввода, таким же текстфилдом, то к нему нельзя будет применить 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. Вот так вот!Как быть то? Последний раз редактировалось _Smirnoff; 19.12.2007 в 10:59. |
|
|||||
|
Цитата:
Цитата:
|
|
|||||
|
>> доработал. Не заменяю коды смайлов "
, и т.д." на пробелы, а просто меняю их цвет в цвет фона (в моем случае фон монотонный) тем самым, пользователь при копировании сообщения копирует и код смайлов, в отличии от вашего случая. Но вариант не универсален. Думаю над этим...зы: Нашел версию для as2.0,кому нужно: http://www.gchats.com/products/16_gc...component.html Не совсем в тему, но, __etc, не охота тему новую ради ссылки создавать. Думаю, согласишься, что бессмысленно. Последний раз редактировалось ulik; 29.01.2008 в 15:32. |
![]() |
![]() |
Часовой пояс GMT +4, время: 19:36. |
|
|
« Предыдущая тема | Следующая тема » |
|
|