Показать сообщение отдельно
Старый 25.11.2006, 01:39
MerlinTwi вне форума Посмотреть профиль Отправить личное сообщение для MerlinTwi Посетить домашнюю страницу MerlinTwi Найти все сообщения от MerlinTwi
  № 2  
Ответить с цитированием
MerlinTwi
 
Аватар для MerlinTwi

Регистрация: 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;
		
		
	}

}
__________________
Создатель: Бойцовский клуб | TimeZero | Sky2Fly
Я возьму сам.