Use individual images in emoji picker rather than a spritesheet
This commit is contained in:
parent
cc7b9da0cf
commit
dcf6a5f59c
5 changed files with 80 additions and 36 deletions
|
@ -276,8 +276,7 @@
|
||||||
"!node_modules/emoji-datasource/emoji_pretty.json",
|
"!node_modules/emoji-datasource/emoji_pretty.json",
|
||||||
"!node_modules/emoji-datasource/*.png",
|
"!node_modules/emoji-datasource/*.png",
|
||||||
"!node_modules/emoji-datasource-apple/emoji_pretty.json",
|
"!node_modules/emoji-datasource-apple/emoji_pretty.json",
|
||||||
"!node_modules/emoji-datasource-apple/img/apple/{sheets,sheets-128}/*.png",
|
"!node_modules/emoji-datasource-apple/img/apple/sheets*",
|
||||||
"!node_modules/emoji-datasource-apple/img/apple/sheets-256/{16,20,32}.png",
|
|
||||||
"!node_modules/spellchecker/vendor/hunspell/**/*",
|
"!node_modules/spellchecker/vendor/hunspell/**/*",
|
||||||
"!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme,test,__tests__,tests,powered-test,example,examples,*.d.ts}",
|
"!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme,test,__tests__,tests,powered-test,example,examples,*.d.ts}",
|
||||||
"!**/node_modules/.bin",
|
"!**/node_modules/.bin",
|
||||||
|
|
|
@ -4424,17 +4424,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module: Emoji
|
// Module: Emoji
|
||||||
@mixin emoji-size($size, $emoji-sheet-columns: 52) {
|
@mixin emoji-size($size) {
|
||||||
&--#{$size} {
|
&--#{$size} {
|
||||||
width: $size;
|
width: $size;
|
||||||
height: $size;
|
height: $size;
|
||||||
background-size: $emoji-sheet-columns * $size;
|
}
|
||||||
|
&__image--#{$size} {
|
||||||
|
width: $size;
|
||||||
|
height: $size;
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-emoji {
|
.module-emoji {
|
||||||
display: block;
|
display: block;
|
||||||
background-image: url('../node_modules/emoji-datasource-apple/img/apple/sheets-256/64.png');
|
|
||||||
|
|
||||||
@include emoji-size(16px);
|
@include emoji-size(16px);
|
||||||
@include emoji-size(20px);
|
@include emoji-size(20px);
|
||||||
|
|
|
@ -28,12 +28,19 @@ function getImageTag({
|
||||||
const result = getReplacementData(match[0], match[1], match[2]);
|
const result = getReplacementData(match[0], match[1], match[2]);
|
||||||
|
|
||||||
if (is.string(result)) {
|
if (is.string(result)) {
|
||||||
return <span key={key}>{match[0]}</span>;
|
return match[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const img = findImage(result.value, result.variation);
|
const img = findImage(result.value, result.variation);
|
||||||
const title = getTitle(result.value);
|
const title = getTitle(result.value);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!img.path ||
|
||||||
|
!img.path.startsWith('node_modules/emoji-datasource-apple')
|
||||||
|
) {
|
||||||
|
return match[0];
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// tslint:disable-next-line react-a11y-img-has-alt
|
// tslint:disable-next-line react-a11y-img-has-alt
|
||||||
<img
|
<img
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { getSheetCoordinates, SkinToneKey } from './lib';
|
import { getImagePath, SkinToneKey } from './lib';
|
||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
inline?: boolean;
|
inline?: boolean;
|
||||||
|
@ -18,9 +18,7 @@ export const Emoji = React.memo(
|
||||||
{ style = {}, size = 28, shortName, skinTone, inline, className }: Props,
|
{ style = {}, size = 28, shortName, skinTone, inline, className }: Props,
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const [sheetX, sheetY] = getSheetCoordinates(shortName, skinTone);
|
const image = getImagePath(shortName, skinTone);
|
||||||
const x = -(size * sheetX);
|
|
||||||
const y = -(size * sheetY);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -31,12 +29,14 @@ export const Emoji = React.memo(
|
||||||
inline ? 'module-emoji--inline' : null,
|
inline ? 'module-emoji--inline' : null,
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
style={{
|
style={style}
|
||||||
...style,
|
>
|
||||||
backgroundPositionX: `${x}px`,
|
<img
|
||||||
backgroundPositionY: `${y}px`,
|
className={`module-emoji__image--${size}px`}
|
||||||
}}
|
src={image}
|
||||||
/>
|
alt={shortName}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,6 +18,21 @@ export const skinTones = ['1F3FB', '1F3FC', '1F3FD', '1F3FE', '1F3FF'];
|
||||||
|
|
||||||
export type SkinToneKey = '1F3FB' | '1F3FC' | '1F3FD' | '1F3FE' | '1F3FF';
|
export type SkinToneKey = '1F3FB' | '1F3FC' | '1F3FD' | '1F3FE' | '1F3FF';
|
||||||
|
|
||||||
|
export type EmojiSkinVariation = {
|
||||||
|
unified: string;
|
||||||
|
non_qualified: null;
|
||||||
|
image: string;
|
||||||
|
sheet_x: number;
|
||||||
|
sheet_y: number;
|
||||||
|
added_in: string;
|
||||||
|
has_img_apple: boolean;
|
||||||
|
has_img_google: boolean;
|
||||||
|
has_img_twitter: boolean;
|
||||||
|
has_img_emojione: boolean;
|
||||||
|
has_img_facebook: boolean;
|
||||||
|
has_img_messenger: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type EmojiData = {
|
export type EmojiData = {
|
||||||
name: string;
|
name: string;
|
||||||
unified: string;
|
unified: string;
|
||||||
|
@ -43,24 +58,36 @@ export type EmojiData = {
|
||||||
has_img_facebook: boolean;
|
has_img_facebook: boolean;
|
||||||
has_img_messenger: boolean;
|
has_img_messenger: boolean;
|
||||||
skin_variations?: {
|
skin_variations?: {
|
||||||
[key: string]: {
|
[key: string]: EmojiSkinVariation;
|
||||||
unified: string;
|
|
||||||
non_qualified: null;
|
|
||||||
image: string;
|
|
||||||
sheet_x: number;
|
|
||||||
sheet_y: number;
|
|
||||||
added_in: string;
|
|
||||||
has_img_apple: boolean;
|
|
||||||
has_img_google: boolean;
|
|
||||||
has_img_twitter: boolean;
|
|
||||||
has_img_emojione: boolean;
|
|
||||||
has_img_facebook: boolean;
|
|
||||||
has_img_messenger: boolean;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const data: Array<EmojiData> = untypedData;
|
const data = (untypedData as Array<EmojiData>).filter(
|
||||||
|
emoji => emoji.has_img_apple
|
||||||
|
);
|
||||||
|
|
||||||
|
const makeImagePath = (src: string) => {
|
||||||
|
return `node_modules/emoji-datasource-apple/img/apple/64/${src}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const images = new Set();
|
||||||
|
|
||||||
|
// Preload images
|
||||||
|
const preload = (src: string) => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = src;
|
||||||
|
images.add(img);
|
||||||
|
};
|
||||||
|
|
||||||
|
data.forEach(emoji => {
|
||||||
|
preload(makeImagePath(emoji.image));
|
||||||
|
|
||||||
|
if (emoji.skin_variations) {
|
||||||
|
Object.values(emoji.skin_variations).forEach(variation => {
|
||||||
|
preload(makeImagePath(variation.image));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export const dataByShortName = keyBy(data, 'short_name');
|
export const dataByShortName = keyBy(data, 'short_name');
|
||||||
|
|
||||||
|
@ -112,20 +139,28 @@ export const dataByCategory = mapValues(
|
||||||
arr => sortBy(arr, 'sort_order')
|
arr => sortBy(arr, 'sort_order')
|
||||||
);
|
);
|
||||||
|
|
||||||
export function getSheetCoordinates(
|
export function getEmojiData(
|
||||||
shortName: keyof typeof dataByShortName,
|
shortName: keyof typeof dataByShortName,
|
||||||
skinTone?: SkinToneKey | number
|
skinTone?: SkinToneKey | number
|
||||||
): [number, number] {
|
): EmojiData | EmojiSkinVariation {
|
||||||
const base = dataByShortName[shortName];
|
const base = dataByShortName[shortName];
|
||||||
|
|
||||||
if (skinTone && base.skin_variations) {
|
if (skinTone && base.skin_variations) {
|
||||||
const variation = isNumber(skinTone) ? skinTones[skinTone - 1] : skinTone;
|
const variation = isNumber(skinTone) ? skinTones[skinTone - 1] : skinTone;
|
||||||
const { sheet_x, sheet_y } = base.skin_variations[variation];
|
|
||||||
|
|
||||||
return [sheet_x, sheet_y];
|
return base.skin_variations[variation];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [base.sheet_x, base.sheet_y];
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getImagePath(
|
||||||
|
shortName: keyof typeof dataByShortName,
|
||||||
|
skinTone?: SkinToneKey | number
|
||||||
|
): string {
|
||||||
|
const { image } = getEmojiData(shortName, skinTone);
|
||||||
|
|
||||||
|
return makeImagePath(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
const fuse = new Fuse(data, {
|
const fuse = new Fuse(data, {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue