[Refactoring] RLottie: Make size required
This commit is contained in:
parent
cfc71da0c1
commit
649fb46777
@ -28,7 +28,7 @@ export type OwnProps = {
|
|||||||
playSegment?: [number, number];
|
playSegment?: [number, number];
|
||||||
speed?: number;
|
speed?: number;
|
||||||
noLoop?: boolean;
|
noLoop?: boolean;
|
||||||
size?: number;
|
size: number;
|
||||||
quality?: number;
|
quality?: number;
|
||||||
color?: [number, number, number];
|
color?: [number, number, number];
|
||||||
isLowPriority?: boolean;
|
isLowPriority?: boolean;
|
||||||
@ -126,14 +126,14 @@ const AnimatedSticker: FC<OwnProps> = ({
|
|||||||
tgsUrl,
|
tgsUrl,
|
||||||
container,
|
container,
|
||||||
renderId || generateIdFor(ID_STORE, true),
|
renderId || generateIdFor(ID_STORE, true),
|
||||||
viewId,
|
|
||||||
{
|
{
|
||||||
noLoop,
|
|
||||||
size,
|
size,
|
||||||
|
noLoop,
|
||||||
quality,
|
quality,
|
||||||
isLowPriority,
|
isLowPriority,
|
||||||
coords: sharedCanvasCoords,
|
coords: sharedCanvasCoords,
|
||||||
},
|
},
|
||||||
|
viewId,
|
||||||
color,
|
color,
|
||||||
onLoad,
|
onLoad,
|
||||||
onEnded,
|
onEnded,
|
||||||
@ -152,18 +152,12 @@ const AnimatedSticker: FC<OwnProps> = ({
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (animation || !tgsUrl || (sharedCanvas && !sharedCanvasCoords)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RLottie) {
|
if (RLottie) {
|
||||||
init();
|
init();
|
||||||
} else {
|
} else {
|
||||||
ensureLottie().then(() => {
|
ensureLottie().then(init);
|
||||||
requestMeasure(init);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, [animation, init, sharedCanvas, sharedCanvasCoords, tgsUrl]);
|
}, [init]);
|
||||||
|
|
||||||
const throttledInit = useThrottledCallback(init, [init], THROTTLE_MS);
|
const throttledInit = useThrottledCallback(init, [init], THROTTLE_MS);
|
||||||
useSharedIntersectionObserver(sharedCanvas, throttledInit);
|
useSharedIntersectionObserver(sharedCanvas, throttledInit);
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { EMOJI_SIZE_PICKER } from '../../config';
|
|||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import { getDocumentMediaHash, isSameReaction } from '../../global/helpers';
|
import { getDocumentMediaHash, isSameReaction } from '../../global/helpers';
|
||||||
|
|
||||||
import useBoundsInSharedCanvas from '../../hooks/useBoundsInSharedCanvas';
|
import useCoordsInSharedCanvas from '../../hooks/useCoordsInSharedCanvas';
|
||||||
import useMediaTransition from '../../hooks/useMediaTransition';
|
import useMediaTransition from '../../hooks/useMediaTransition';
|
||||||
import useMedia from '../../hooks/useMedia';
|
import useMedia from '../../hooks/useMedia';
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ const ReactionEmoji: FC<OwnProps> = ({
|
|||||||
), [availableReactions, reaction]);
|
), [availableReactions, reaction]);
|
||||||
const thumbDataUri = availableReaction?.staticIcon?.thumbnail?.dataUri;
|
const thumbDataUri = availableReaction?.staticIcon?.thumbnail?.dataUri;
|
||||||
const animationId = availableReaction?.selectAnimation?.id;
|
const animationId = availableReaction?.selectAnimation?.id;
|
||||||
const bounds = useBoundsInSharedCanvas(ref, sharedCanvasHqRef);
|
const coords = useCoordsInSharedCanvas(ref, sharedCanvasHqRef);
|
||||||
const mediaData = useMedia(
|
const mediaData = useMedia(
|
||||||
availableReaction?.selectAnimation ? getDocumentMediaHash(availableReaction.selectAnimation) : undefined,
|
availableReaction?.selectAnimation ? getDocumentMediaHash(availableReaction.selectAnimation) : undefined,
|
||||||
!animationId,
|
!animationId,
|
||||||
@ -91,7 +91,7 @@ const ReactionEmoji: FC<OwnProps> = ({
|
|||||||
size={EMOJI_SIZE_PICKER}
|
size={EMOJI_SIZE_PICKER}
|
||||||
className={transitionClassNames}
|
className={transitionClassNames}
|
||||||
sharedCanvas={sharedCanvasHqRef!.current || undefined}
|
sharedCanvas={sharedCanvasHqRef!.current || undefined}
|
||||||
sharedCanvasCoords={bounds.coords}
|
sharedCanvasCoords={coords}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import { useIsIntersecting } from '../../hooks/useIntersectionObserver';
|
|||||||
import useThumbnail from '../../hooks/useThumbnail';
|
import useThumbnail from '../../hooks/useThumbnail';
|
||||||
import useMediaTransition from '../../hooks/useMediaTransition';
|
import useMediaTransition from '../../hooks/useMediaTransition';
|
||||||
import useFlag from '../../hooks/useFlag';
|
import useFlag from '../../hooks/useFlag';
|
||||||
import useBoundsInSharedCanvas from '../../hooks/useBoundsInSharedCanvas';
|
import useCoordsInSharedCanvas from '../../hooks/useCoordsInSharedCanvas';
|
||||||
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
|
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
|
||||||
|
|
||||||
import AnimatedSticker from './AnimatedSticker';
|
import AnimatedSticker from './AnimatedSticker';
|
||||||
@ -118,7 +118,7 @@ const StickerView: FC<OwnProps> = ({
|
|||||||
const fullMediaClassNames = useMediaTransition(isFullMediaReady);
|
const fullMediaClassNames = useMediaTransition(isFullMediaReady);
|
||||||
const noTransition = isLottie && preloadedPreviewData;
|
const noTransition = isLottie && preloadedPreviewData;
|
||||||
|
|
||||||
const bounds = useBoundsInSharedCanvas(containerRef, sharedCanvasRef);
|
const coords = useCoordsInSharedCanvas(containerRef, sharedCanvasRef);
|
||||||
|
|
||||||
// Preload preview for Message Input and local message
|
// Preload preview for Message Input and local message
|
||||||
useMedia(previewMediaHash, !shouldLoad || !shouldPreloadPreview, undefined, cacheBuster);
|
useMedia(previewMediaHash, !shouldLoad || !shouldPreloadPreview, undefined, cacheBuster);
|
||||||
@ -160,7 +160,7 @@ const StickerView: FC<OwnProps> = ({
|
|||||||
forceOnHeavyAnimation={forceOnHeavyAnimation}
|
forceOnHeavyAnimation={forceOnHeavyAnimation}
|
||||||
isLowPriority={isSmall && !selectIsAlwaysHighPriorityEmoji(getGlobal(), stickerSetInfo)}
|
isLowPriority={isSmall && !selectIsAlwaysHighPriorityEmoji(getGlobal(), stickerSetInfo)}
|
||||||
sharedCanvas={sharedCanvasRef?.current || undefined}
|
sharedCanvas={sharedCanvasRef?.current || undefined}
|
||||||
sharedCanvasCoords={bounds.coords}
|
sharedCanvasCoords={coords}
|
||||||
onLoad={markPlayerReady}
|
onLoad={markPlayerReady}
|
||||||
onLoop={onAnimatedStickerLoop}
|
onLoop={onAnimatedStickerLoop}
|
||||||
onEnded={onAnimatedStickerLoop}
|
onEnded={onAnimatedStickerLoop}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import { getStickerPreviewHash } from '../../../global/helpers';
|
|||||||
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
||||||
import useMedia from '../../../hooks/useMedia';
|
import useMedia from '../../../hooks/useMedia';
|
||||||
import useMediaTransition from '../../../hooks/useMediaTransition';
|
import useMediaTransition from '../../../hooks/useMediaTransition';
|
||||||
import useBoundsInSharedCanvas from '../../../hooks/useBoundsInSharedCanvas';
|
import useCoordsInSharedCanvas from '../../../hooks/useCoordsInSharedCanvas';
|
||||||
|
|
||||||
import AnimatedSticker from '../../common/AnimatedSticker';
|
import AnimatedSticker from '../../common/AnimatedSticker';
|
||||||
import OptimizedVideo from '../../ui/OptimizedVideo';
|
import OptimizedVideo from '../../ui/OptimizedVideo';
|
||||||
@ -54,7 +54,7 @@ const StickerSetCover: FC<OwnProps> = ({
|
|||||||
const isReady = mediaData || staticMediaData;
|
const isReady = mediaData || staticMediaData;
|
||||||
const transitionClassNames = useMediaTransition(isReady);
|
const transitionClassNames = useMediaTransition(isReady);
|
||||||
|
|
||||||
const bounds = useBoundsInSharedCanvas(containerRef, sharedCanvasRef);
|
const coords = useCoordsInSharedCanvas(containerRef, sharedCanvasRef);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isIntersecting && !stickerSet.stickers?.length) {
|
if (isIntersecting && !stickerSet.stickers?.length) {
|
||||||
@ -74,11 +74,11 @@ const StickerSetCover: FC<OwnProps> = ({
|
|||||||
<AnimatedSticker
|
<AnimatedSticker
|
||||||
className={transitionClassNames}
|
className={transitionClassNames}
|
||||||
tgsUrl={mediaData}
|
tgsUrl={mediaData}
|
||||||
size={size || bounds.size}
|
size={size}
|
||||||
play={isIntersecting && !noAnimate}
|
play={isIntersecting && !noAnimate}
|
||||||
isLowPriority={!selectIsAlwaysHighPriorityEmoji(getGlobal(), stickerSet)}
|
isLowPriority={!selectIsAlwaysHighPriorityEmoji(getGlobal(), stickerSet)}
|
||||||
sharedCanvas={sharedCanvasRef?.current || undefined}
|
sharedCanvas={sharedCanvasRef?.current || undefined}
|
||||||
sharedCanvasCoords={bounds.coords}
|
sharedCanvasCoords={coords}
|
||||||
/>
|
/>
|
||||||
) : (isVideo && !shouldFallbackToStatic) ? (
|
) : (isVideo && !shouldFallbackToStatic) ? (
|
||||||
<OptimizedVideo
|
<OptimizedVideo
|
||||||
|
|||||||
@ -200,12 +200,12 @@ function createPlayer({
|
|||||||
mediaUrl,
|
mediaUrl,
|
||||||
isHq ? sharedCanvasHqRef.current! : sharedCanvasRef.current!,
|
isHq ? sharedCanvasHqRef.current! : sharedCanvasRef.current!,
|
||||||
renderId,
|
renderId,
|
||||||
viewId,
|
|
||||||
{
|
{
|
||||||
size: SIZE,
|
size: SIZE,
|
||||||
coords: position,
|
coords: position,
|
||||||
isLowPriority: !isHq,
|
isLowPriority: !isHq,
|
||||||
},
|
},
|
||||||
|
viewId,
|
||||||
customEmoji.shouldUseTextColor ? textColor : undefined,
|
customEmoji.shouldUseTextColor ? textColor : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -10,13 +10,12 @@ import useSharedIntersectionObserver from './useSharedIntersectionObserver';
|
|||||||
|
|
||||||
const THROTTLE_MS = 150;
|
const THROTTLE_MS = 150;
|
||||||
|
|
||||||
export default function useBoundsInSharedCanvas(
|
export default function useCoordsInSharedCanvas(
|
||||||
containerRef: React.RefObject<HTMLDivElement>,
|
containerRef: React.RefObject<HTMLDivElement>,
|
||||||
sharedCanvasRef?: React.RefObject<HTMLCanvasElement>,
|
sharedCanvasRef?: React.RefObject<HTMLCanvasElement>,
|
||||||
) {
|
) {
|
||||||
const [x, setX] = useState<number>();
|
const [x, setX] = useState<number>();
|
||||||
const [y, setY] = useState<number>();
|
const [y, setY] = useState<number>();
|
||||||
const [size, setSize] = useState<number>();
|
|
||||||
|
|
||||||
const recalculate = useCallback(() => {
|
const recalculate = useCallback(() => {
|
||||||
const container = containerRef.current;
|
const container = containerRef.current;
|
||||||
@ -43,7 +42,6 @@ export default function useBoundsInSharedCanvas(
|
|||||||
// Factor coords are used to support rendering while being rescaled (e.g. message appearance animation)
|
// Factor coords are used to support rendering while being rescaled (e.g. message appearance animation)
|
||||||
setX(round((targetBounds.left - canvasBounds.left) / canvasBounds.width, 4) || 0);
|
setX(round((targetBounds.left - canvasBounds.left) / canvasBounds.width, 4) || 0);
|
||||||
setY(round((targetBounds.top - canvasBounds.top) / canvasBounds.height, 4) || 0);
|
setY(round((targetBounds.top - canvasBounds.top) / canvasBounds.height, 4) || 0);
|
||||||
setSize(Math.round(targetBounds.width));
|
|
||||||
}, [containerRef, sharedCanvasRef]);
|
}, [containerRef, sharedCanvasRef]);
|
||||||
|
|
||||||
useEffect(recalculate, [recalculate]);
|
useEffect(recalculate, [recalculate]);
|
||||||
@ -52,7 +50,5 @@ export default function useBoundsInSharedCanvas(
|
|||||||
useResizeObserver(sharedCanvasRef, throttledRecalculate);
|
useResizeObserver(sharedCanvasRef, throttledRecalculate);
|
||||||
useSharedIntersectionObserver(sharedCanvasRef, throttledRecalculate);
|
useSharedIntersectionObserver(sharedCanvasRef, throttledRecalculate);
|
||||||
|
|
||||||
const coords = useMemo(() => (x !== undefined && y !== undefined ? { x, y } : undefined), [x, y]);
|
return useMemo(() => (x !== undefined && y !== undefined ? { x, y } : undefined), [x, y]);
|
||||||
|
|
||||||
return { coords, size };
|
|
||||||
}
|
}
|
||||||
@ -11,8 +11,8 @@ import cycleRestrict from '../../util/cycleRestrict';
|
|||||||
import generateIdFor from '../../util/generateIdFor';
|
import generateIdFor from '../../util/generateIdFor';
|
||||||
|
|
||||||
interface Params {
|
interface Params {
|
||||||
|
size: number;
|
||||||
noLoop?: boolean;
|
noLoop?: boolean;
|
||||||
size?: number;
|
|
||||||
quality?: number;
|
quality?: number;
|
||||||
isLowPriority?: boolean;
|
isLowPriority?: boolean;
|
||||||
coords?: { x: number; y: number };
|
coords?: { x: number; y: number };
|
||||||
@ -96,8 +96,8 @@ class RLottie {
|
|||||||
const [
|
const [
|
||||||
, canvas,
|
, canvas,
|
||||||
renderId,
|
renderId,
|
||||||
viewId = generateIdFor(ID_STORE, true),
|
params,
|
||||||
params, ,
|
viewId = generateIdFor(ID_STORE, true), ,
|
||||||
onLoad,
|
onLoad,
|
||||||
] = args;
|
] = args;
|
||||||
let instance = instancesByRenderId.get(renderId);
|
let instance = instancesByRenderId.get(renderId);
|
||||||
@ -117,8 +117,8 @@ class RLottie {
|
|||||||
private tgsUrl: string,
|
private tgsUrl: string,
|
||||||
private container: HTMLDivElement | HTMLCanvasElement,
|
private container: HTMLDivElement | HTMLCanvasElement,
|
||||||
private renderId: string,
|
private renderId: string,
|
||||||
|
private params: Params,
|
||||||
viewId: string = generateIdFor(ID_STORE, true),
|
viewId: string = generateIdFor(ID_STORE, true),
|
||||||
private params: Params = {},
|
|
||||||
private customColor?: [number, number, number],
|
private customColor?: [number, number, number],
|
||||||
private onLoad?: NoneToVoidFunction | undefined,
|
private onLoad?: NoneToVoidFunction | undefined,
|
||||||
private onEnded?: (isDestroyed?: boolean) => void,
|
private onEnded?: (isDestroyed?: boolean) => void,
|
||||||
@ -264,19 +264,7 @@ class RLottie {
|
|||||||
throw new Error('[RLottie] Container is not mounted');
|
throw new Error('[RLottie] Container is not mounted');
|
||||||
}
|
}
|
||||||
|
|
||||||
let { size } = this.params;
|
const { size } = this.params;
|
||||||
|
|
||||||
if (!size) {
|
|
||||||
size = (
|
|
||||||
container.offsetWidth
|
|
||||||
|| parseInt(container.style.width, 10)
|
|
||||||
|| container.parentNode.offsetWidth
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!size) {
|
|
||||||
throw new Error('[RLottie] Failed to detect width from container');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
imgSize = Math.round(size * sizeFactor);
|
imgSize = Math.round(size * sizeFactor);
|
||||||
|
|
||||||
@ -309,7 +297,7 @@ class RLottie {
|
|||||||
const canvas = container;
|
const canvas = container;
|
||||||
const ctx = canvas.getContext('2d')!;
|
const ctx = canvas.getContext('2d')!;
|
||||||
|
|
||||||
imgSize = Math.round(this.params.size! * sizeFactor);
|
imgSize = Math.round(this.params.size * sizeFactor);
|
||||||
|
|
||||||
if (!this.imgSize) {
|
if (!this.imgSize) {
|
||||||
this.imgSize = imgSize;
|
this.imgSize = imgSize;
|
||||||
@ -323,8 +311,8 @@ class RLottie {
|
|||||||
ctx,
|
ctx,
|
||||||
isSharedCanvas: true,
|
isSharedCanvas: true,
|
||||||
coords: {
|
coords: {
|
||||||
x: Math.round((coords?.x || 0) * canvasWidth),
|
x: Math.round(coords!.x * canvasWidth),
|
||||||
y: Math.round((coords?.y || 0) * canvasHeight),
|
y: Math.round(coords!.y * canvasHeight),
|
||||||
},
|
},
|
||||||
onLoad,
|
onLoad,
|
||||||
});
|
});
|
||||||
@ -337,8 +325,8 @@ class RLottie {
|
|||||||
|
|
||||||
private calcSizeFactor() {
|
private calcSizeFactor() {
|
||||||
const {
|
const {
|
||||||
isLowPriority,
|
|
||||||
size,
|
size,
|
||||||
|
isLowPriority,
|
||||||
// Reduced quality only looks acceptable on big enough images
|
// Reduced quality only looks acceptable on big enough images
|
||||||
quality = isLowPriority && (!size || size > LOW_PRIORITY_QUALITY_SIZE_THRESHOLD)
|
quality = isLowPriority && (!size || size > LOW_PRIORITY_QUALITY_SIZE_THRESHOLD)
|
||||||
? LOW_PRIORITY_QUALITY : HIGH_PRIORITY_QUALITY,
|
? LOW_PRIORITY_QUALITY : HIGH_PRIORITY_QUALITY,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user