КОВАРНЫЕ УЛЫБКИ

ИЛИ НЕ АНГУЛЯРОМ ЕДИНЫМ

КОВАРНЫЕ УЛЫБКИ

Коротаев Александр

  1. Активно участвую в жизни сообщества
  2. Посещаю и создаю митапы 🤓
  3. Делаю SPB-Frontend Drinkcast
    Подкаст o фронтенде за кружкой пива

🦊 Только нативные emoji


😀 Ввод emoji пользователями


😷 Использовать fallback, если нужно

Emoji в web

...это не только Emoji




googlei18n / color-emoji

colorfonts.wtf

ОС Mac OS >= Windows 8 <= Windows 7 Linux
Chrome 😀 😀 😡 ¯\_(ツ)_/¯
Firefox 😀 😀 😀!!! 😀!!!
Edge 😀
IE 😀 😡






Twem❤ji

https://twitter.github.io/twemoji/

Twem❤ji

			Twem❤️ji
		

			Twem
			<img src="https://.../2/72x72/2764.png" alt="❤️">
			ji
		

Обернем это в директиву

			@Directive({selector: '[emojiText]'})
			class EmojiTextDirective {
				constructor(ref: ElementRef) {}
				@Input() set emojiText(input: string) {
					const text = twemoji(input)
					this.ref.nativeElement.innerHTML = text
				}
			}
		

Добавим ее повсюду

			<message-header [emojiText]="header"></message-header>
			<message [emojiText]="text"></message>
		

Даже в Emoji-picker

Миссия выполнена:


👍 это нативные emoji


👍 кроссбраузерно

Twemoji — тормозит!

А нативные emoji — нет

Но как определить поддержку?


ОС Mac OS >= Windows 8 <= Windows 7 Linux
Chrome 😀 😀 😡 ¯\_(ツ)_/¯
Firefox 😀 😀 😀!!! 😀!!!
Edge 😀
IE 😀 😡

Нарисовать красный зеленым!


🔴

Нарисовать красный зеленым!

  1. <canvas>;
  2. Рисуем 🔴;
  3. Задаем цвет текста: зеленый;
  4. Проверяем цвет в центральной точке;
  5. Если там что-то кроме белого и зеленого — поддержка есть 😀.

Много кода

			const ctx = canvas.getContext('2d');
			// smile - red circle
			const smile = '🔴';
			// font-color - green
			const greenRGB = '0,255,0';
			 
			 
			 
			 
			ctx.textBaseline = 'top';
			ctx.fillStyle = `rgb(${greenRGB})`;
			ctx.font = '32px Arial';
			 
			 
			 
			 
			ctx.fillText(smile, 0, 0);
			 
			const {data} = ctx.getImageData(16, 16, 1, 1);
			 
			 
			const rgb = data.slice(0, 3)
			const isGreen = rgb.toString() === greenRGB
			const isTransparent = data[3] === 0
			return !(isGreen || isTransparent);
		

Код целиком

			const ctx = document.createElement('canvas').getContext('2d');
			// smile - red circle
			const smile = '🔴';
			// font-color - green
			const greenRGB = '0,255,0';
			 

			ctx.textBaseline = 'top';
			ctx.fillStyle = `rgb(${greenRGB})`;
			ctx.font = '32px Arial';
			 

			ctx.fillText(smile, 0, 0);
			 
			const {data} = ctx.getImageData(16, 16, 1, 1);
			 

			return !(data.slice(0, 3).toString() === greenRGB || data[3] === 0);
		

Тормозит отрисовка

Спрайты — быстрее

			<span class="icon icon-🐹">🐹</span>
		
			.icon {
				background: url(sprite.png)
			}
			.icon-🐹 {
				background-position-y: -240px
			}
		

Как итог ресерча

Директива для отображения emoji

			<div [emojiText]="Всем привет 😀!"></div>
		

			<div>
				Всем привет<span class="icon icon-😀">😀</span>!
			</div>
		

Fallback только по необходимости

			@Directive({selector: '[emojiText]'})
			class EmojiTextDirective {
				@Input() set emojiText(input: string) {
					const text = isColorEmojiSupports()
						? emojiText
						: emojiText.replace(EMOJI_REGEXP, ...);
				}
			}
		

Осталось найти регулярку

mathiasbynens / emoji-regex

Снова пришлось писать самому 😡

			/[\u2139-\u303d\uD83C-\uDBFF\uDC00-\uDFFF]/gu
		

U – значит Unicode

https://mothereff.in/regexpu

Ввод emoji пользователями

<textarea> с картинками?

			<div contenteditable>
				Всем привет <img src="...">! А что вы тут ...
			</div>
		

Но есть и обходные маневры

Директива для <textarea>

			<textarea [(emojiTextArea)]="text"></textarea>
		

			@Input() emojiTextArea: string
			@Output() emojiTextAreaChange: EventEmitter<string>
		

Директива для <textarea>

			@Directive({selector: 'textarea[emojiTextArea]'})
			export class EmojiTextAreaDirective {
				// при смене значения извне – обновляем textarea
				@Input() set emojiTextArea(value: string) {
					this.updateInput(value)
				}
				@Output() emojiTextAreaChange 
						= new EventEmitter<string>()
				
				
				
				
				// получаем textarea
				constructor(private ref: ElementRef) {}
				
				
				
				
				// реакция на событие ввода
				@HostListener('input')
				onInput() {
					const {value} = this.ref.nativeElement;
					this.updateInput(value);
					this.updateOutput(value);
				}
				
				
				
				
				// обновление textarea
				private updateInput(value: string) {
					this.ref.nativeElement.value 
						// 'Привет 😀!' -> 'Привет :smile:!'
						= this.getCodesValue(value);
				}

				
				
				
				
				// обновление output
				private updateOutput(value: string) {
					this.emojiTextAreaChange.emit(
						// 'Привет :smile:!' -> 'Привет 😀!'
						this.getEmojiValue(value)
					);
				}
			}
		

Итоговая реализация



Emoji — это весело


* но не в вебе

Ссылки

Вопросы?

http://lekzd.ru/presentations/emoji