mirror of
https://github.com/danog/telegram-tt.git
synced 2024-11-27 04:45:08 +01:00
[Perf] Animated Emoji: Dispatch heavy animation event, better interaction animation
This commit is contained in:
parent
42745ea024
commit
b6c80b5236
@ -1,4 +1,5 @@
|
||||
.AnimatedEmoji {
|
||||
cursor: pointer;
|
||||
margin-bottom: 0.75rem;
|
||||
|
||||
img {
|
||||
|
@ -93,6 +93,7 @@ const AnimatedEmoji: FC<OwnProps> = ({
|
||||
size={width}
|
||||
quality={QUALITY}
|
||||
play={isIntersecting && playKey}
|
||||
forceOnHeavyAnimation
|
||||
noLoop
|
||||
onLoad={markAnimationLoaded}
|
||||
/>
|
||||
|
@ -19,6 +19,7 @@ type OwnProps = {
|
||||
quality?: number;
|
||||
isLowPriority?: boolean;
|
||||
onLoad?: NoneToVoidFunction;
|
||||
forceOnHeavyAnimation?: boolean;
|
||||
color?: [number, number, number];
|
||||
onEnded?: NoneToVoidFunction;
|
||||
};
|
||||
@ -53,8 +54,9 @@ const AnimatedSticker: FC<OwnProps> = ({
|
||||
size,
|
||||
quality,
|
||||
isLowPriority,
|
||||
onLoad,
|
||||
color,
|
||||
forceOnHeavyAnimation,
|
||||
onLoad,
|
||||
onEnded,
|
||||
}) => {
|
||||
const [animation, setAnimation] = useState<RLottieInstance>();
|
||||
@ -207,7 +209,7 @@ const AnimatedSticker: FC<OwnProps> = ({
|
||||
}
|
||||
}, [playAnimation, animation, animationData]);
|
||||
|
||||
useHeavyAnimationCheck(freezeAnimation, unfreezeAnimation);
|
||||
useHeavyAnimationCheck(freezeAnimation, unfreezeAnimation, forceOnHeavyAnimation);
|
||||
// Pausing frame may not happen in background
|
||||
// so we need to make sure it happens right after focusing,
|
||||
// then we can play again.
|
||||
|
@ -74,6 +74,7 @@ const LocalAnimatedEmoji: FC<OwnProps> = ({
|
||||
size={width}
|
||||
quality={QUALITY}
|
||||
play={isIntersecting && playKey}
|
||||
forceOnHeavyAnimation
|
||||
noLoop
|
||||
onLoad={markAnimationLoaded}
|
||||
/>
|
||||
|
@ -2,7 +2,6 @@
|
||||
--start-x: 0;
|
||||
--start-y: 0;
|
||||
--scale: 0;
|
||||
--end-scale: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@ -11,42 +10,7 @@
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
|
||||
@keyframes hide-reaction-reversed {
|
||||
from {
|
||||
transform: translate(100%, -50%) scaleX(-1) scale(1);
|
||||
}
|
||||
|
||||
to {
|
||||
left: var(--end-x, var(--start-x));
|
||||
top: var(--end-y, var(--start-y));
|
||||
transform: translate(50%, 0) scale(var(--end-scale, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show-reaction-reversed {
|
||||
from {
|
||||
transform: translate(50%, 0) scaleX(-1) scale(var(--scale, 0));
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate(100%, -50%) scaleX(-1) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes hide-reaction {
|
||||
from {
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
|
||||
to {
|
||||
left: var(--end-x, var(--start-x));
|
||||
top: var(--end-y, var(--start-y));
|
||||
transform: translate(0, 0) scale(var(--end-scale, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show-reaction {
|
||||
@keyframes show-interaction {
|
||||
from {
|
||||
transform: translate(0, 0) scale(var(--scale, 0));
|
||||
}
|
||||
@ -56,13 +20,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show-interaction-reversed {
|
||||
from {
|
||||
transform: translate(50%, 0) scaleX(-1) scale(var(--scale, 0));
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate(100%, -50%) scaleX(-1) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.AnimatedSticker {
|
||||
position: absolute;
|
||||
top: var(--start-y);
|
||||
left: var(--start-x);
|
||||
transform: scale(var(--scale), 0);
|
||||
transform-origin: left top;
|
||||
|
||||
transition: 0.25s cubic-bezier(.29,.81,.27,.99) opacity;
|
||||
}
|
||||
|
||||
@ -71,19 +44,18 @@
|
||||
}
|
||||
|
||||
&.playing .AnimatedSticker {
|
||||
animation: show-reaction forwards 0.25s cubic-bezier(.29,.81,.27,.99);
|
||||
animation: show-interaction forwards 0.25s cubic-bezier(.29,.81,.27,.99);
|
||||
}
|
||||
|
||||
&.reversed.playing .AnimatedSticker {
|
||||
animation: show-reaction-reversed forwards 0.25s cubic-bezier(.29,.81,.27,.99);
|
||||
animation: show-interaction-reversed forwards 0.25s cubic-bezier(.29,.81,.27,.99);
|
||||
}
|
||||
|
||||
&.hiding .AnimatedSticker {
|
||||
opacity: 0;
|
||||
animation: hide-reaction forwards 0.25s cubic-bezier(.29,.81,.27,.99);
|
||||
}
|
||||
|
||||
&.reversed.hiding .AnimatedSticker {
|
||||
animation: hide-reaction-reversed forwards 0.25s cubic-bezier(.29,.81,.27,.99);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,20 @@
|
||||
import React, {
|
||||
FC, memo, useCallback, useEffect, useState,
|
||||
FC, memo, useCallback, useEffect, useLayoutEffect, useState,
|
||||
} from '../../lib/teact/teact';
|
||||
import { getDispatch, withGlobal } from '../../lib/teact/teactn';
|
||||
|
||||
import { ActiveEmojiInteraction } from '../../global/types';
|
||||
import { ApiMediaFormat } from '../../api/types';
|
||||
|
||||
import { IS_ANDROID } from '../../util/environment';
|
||||
import useFlag from '../../hooks/useFlag';
|
||||
import useMedia from '../../hooks/useMedia';
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
import {
|
||||
selectAnimatedEmojiEffect,
|
||||
} from '../../modules/selectors';
|
||||
import { REM } from '../common/helpers/mediaDimensions';
|
||||
import getAnimationData, { ANIMATED_STICKERS_PATHS } from '../common/helpers/animatedAssets';
|
||||
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
||||
|
||||
import AnimatedSticker from '../common/AnimatedSticker';
|
||||
|
||||
@ -31,7 +32,6 @@ type StateProps = {
|
||||
|
||||
const HIDE_ANIMATION_DURATION = 250;
|
||||
const PLAYING_DURATION = 3000;
|
||||
const END_SIZE = 1.125 * REM;
|
||||
const EFFECT_SIZE = 240;
|
||||
|
||||
const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
||||
@ -66,8 +66,13 @@ const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
||||
};
|
||||
}, [stop]);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(stop, PLAYING_DURATION);
|
||||
useLayoutEffect(() => {
|
||||
const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent();
|
||||
|
||||
setTimeout(() => {
|
||||
stop();
|
||||
dispatchHeavyAnimationStop();
|
||||
}, PLAYING_DURATION);
|
||||
}, [stop]);
|
||||
|
||||
const mediaDataEffect = useMedia(`sticker${effectAnimationId}`, !effectAnimationId, ApiMediaFormat.Lottie);
|
||||
@ -82,7 +87,6 @@ const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
||||
}, [localEffectAnimation]);
|
||||
|
||||
const scale = (emojiInteraction.startSize || 0) / EFFECT_SIZE;
|
||||
const endScale = END_SIZE / EFFECT_SIZE;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -90,16 +94,15 @@ const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
||||
'EmojiInteractionAnimation', isHiding && 'hiding', isPlaying && 'playing', isReversed && 'reversed',
|
||||
)}
|
||||
// @ts-ignore teact feature
|
||||
style={`--end-scale: ${endScale}; --scale: ${scale}; --start-x: ${emojiInteraction.x}px;`
|
||||
+ `--start-y: ${emojiInteraction.y}px;${
|
||||
emojiInteraction.endX
|
||||
&& emojiInteraction.endY ? `--end-x: ${emojiInteraction.endX}px; --end-y: ${emojiInteraction.endY}px;` : ''}`}
|
||||
style={`--scale: ${scale}; --start-x: ${emojiInteraction.x}px; --start-y: ${emojiInteraction.y}px;`}
|
||||
>
|
||||
<AnimatedSticker
|
||||
id={`effect_${effectAnimationId}`}
|
||||
size={EFFECT_SIZE}
|
||||
animationData={(localEffectAnimationData || mediaDataEffect) as AnyLiteral}
|
||||
play={isPlaying}
|
||||
isLowPriority={IS_ANDROID}
|
||||
forceOnHeavyAnimation
|
||||
noLoop
|
||||
onLoad={startPlaying}
|
||||
/>
|
||||
|
@ -12,8 +12,13 @@ const AUTO_END_TIMEOUT = 1000;
|
||||
export default (
|
||||
handleAnimationStart: AnyToVoidFunction,
|
||||
handleAnimationEnd: AnyToVoidFunction,
|
||||
isDisabled = false,
|
||||
) => {
|
||||
useEffect(() => {
|
||||
if (isDisabled) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (isAnimating) {
|
||||
handleAnimationStart();
|
||||
}
|
||||
@ -25,7 +30,7 @@ export default (
|
||||
document.removeEventListener(ANIMATION_END_EVENT, handleAnimationEnd);
|
||||
document.removeEventListener(ANIMATION_START_EVENT, handleAnimationStart);
|
||||
};
|
||||
}, [handleAnimationEnd, handleAnimationStart]);
|
||||
}, [isDisabled, handleAnimationEnd, handleAnimationStart]);
|
||||
};
|
||||
|
||||
export function isHeavyAnimating() {
|
||||
|
Loading…
Reference in New Issue
Block a user