matrix-animations/src/scenes/imageEvent.tsx

283 lines
10 KiB
TypeScript

import { makeScene2D } from '@motion-canvas/2d/lib/scenes';
import {
Rect,
Layout,
Circle,
Txt,
Img,
} from '@motion-canvas/2d/lib/components';
import {
CodeBlock,
edit,
lines,
} from '@motion-canvas/2d/lib/components/CodeBlock';
import { createRef } from '@motion-canvas/core/lib/utils';
import { all, delay, waitUntil } from '@motion-canvas/core/lib/flow';
import {
BG,
BOLD,
BOXLEFT,
BOXRIGHT,
HIGHLIGHT,
TEXTBOX,
} from '../utils/constants';
import contentImage from '../assets/image.jpg';
import contentBlurhash from '../assets/blurhash.png';
import { easeOutCubic } from '@motion-canvas/core/lib/tweening';
export const CODESIZE_DEFAULT = 33;
const CODESIZE_SMALLER = 16;
export const IMAGE_EVENT = `{
"room_id": "!def:matrix.org",
"origin_server_ts": 1679081573367,
"sender": "@example:matrix.org",
"event_id": "$abc",
"type": "m.room.message",
"content": {
"body": "image.png",
"info": {
"size": 12874,
"mimetype": "image/png",
"w": 344,
"h": 238,
"xyz.amorgan.blurhash": "UBQ+KisRozt7pfnhkWjEE5aeV@nNpdjYjYjs"
},
"msgtype": "m.image",
"url": "mxc://matrix.org/abcdef"
}
}`;
const NEXT_EVENT = `{}`;
export default makeScene2D(function* (view) {
const colLeft = createRef<Layout>();
const colRight = createRef<Layout>();
const colRightBG = createRef<Rect>();
const codeTextContainer = createRef<CodeBlock>();
const leftContainer = createRef<Rect>();
const textEvent = createRef<Rect>();
const eventContent = createRef<Rect>();
const contentImageRef = createRef<Img>();
const contentBlurhashRef = createRef<Img>();
view.add(
<>
<Layout layout padding={10} width={'100%'} height={'100%'}>
<Layout ref={colLeft} basis={0} width={0}>
<Rect
ref={leftContainer}
fill={BOXLEFT}
radius={2}
grow={1}
direction={'column'}
alignItems="center"
justifyContent="center"
gap={25}
padding={128}
>
<Rect
basis={0}
ref={textEvent}
fill={TEXTBOX}
radius={4}
lineWidth={2}
stroke={'#fff'}
direction={'row'}
gap={48}
padding={24}
opacity={0}
width="100%"
>
<Layout
direction={'column'}
gap={12}
alignItems="center"
>
<Rect
alignItems="center"
justifyContent="center"
fill={TEXTBOX}
>
<Circle size={80} fill={'#FD8A8A'} />
</Rect>
<Rect
alignItems="center"
justifyContent="center"
fill={TEXTBOX}
>
<Txt
fill={'#b9bec6'}
fontFamily="Inter"
fontSize={18}
text={'00:14'}
/>
</Rect>
</Layout>
<Layout
direction={'column'}
gap={12}
alignItems={'start'}
>
<Rect
alignItems="center"
justifyContent="center"
fill={TEXTBOX}
>
<Txt
fill={'#7286D3'}
fontFamily="Inter"
fontSize={32}
fontWeight={BOLD}
text={'Username'}
/>
</Rect>
<Rect
ref={eventContent}
alignItems="center"
justifyContent="center"
fill={TEXTBOX}
width={300}
height={300}
>
<Rect layout={false}>
<Img
ref={contentImageRef}
src={contentImage}
width={292}
height={292}
opacity={1}
/>
<Img
ref={contentBlurhashRef}
src={contentBlurhash}
width={292}
height={292}
opacity={1}
/>
</Rect>
</Rect>
</Layout>
</Rect>
<Txt
fill={'#fff'}
fontFamily="Inter"
fontSize={24}
text={'Image by Poppy Thomas-Hill'}
/>
</Rect>
</Layout>
<Rect ref={colRight} grow={1} fill={BG}>
<Rect
ref={colRightBG}
fill={BOXRIGHT}
grow={1}
radius={4}
direction={'column'}
alignItems="center"
justifyContent="center"
>
<Rect
fill={TEXTBOX}
radius={4}
stroke={'#fff'}
lineWidth={4}
padding={32}
width={'75%'}
>
<CodeBlock
ref={codeTextContainer}
fontSize={CODESIZE_DEFAULT}
language="json"
code={IMAGE_EVENT}
/>
,
</Rect>
</Rect>
</Rect>
</Layout>
</>
);
//yield* slideTransition(Direction.Right, 1);
const IMAGE_SMALL = 392;
const CONTAINER_IMAGE_SMALL = 400;
const IMAGE_EXPANDED = 400;
const CONTAINER_IMAGE_EXPANDED = 408;
let animation_length = easeOutCubic(0.8);
yield* waitUntil('Show Text Event');
colLeft().save();
colRight().save();
textEvent().save();
eventContent().save();
contentImageRef().save();
contentBlurhashRef().save();
yield* all(
colLeft().grow(4, animation_length),
colRight().grow(1, animation_length),
codeTextContainer().fontSize(CODESIZE_SMALLER, animation_length),
colRightBG().margin.left(10, 0.1),
eventContent().width(CONTAINER_IMAGE_SMALL, animation_length),
eventContent().height(CONTAINER_IMAGE_SMALL, animation_length),
contentImageRef().width(IMAGE_SMALL, animation_length),
contentImageRef().height(IMAGE_SMALL, animation_length),
contentBlurhashRef().width(IMAGE_SMALL, animation_length),
contentBlurhashRef().height(IMAGE_SMALL, animation_length),
delay(0.25, all(textEvent().opacity(1, 0.3)))
);
yield* waitUntil('Show Blurhash');
animation_length = easeOutCubic(1.5);
const radius = 5;
const padding = 8;
const fontSizeHighlighted = 32;
const dashes = [15, 15];
const dashSize = 4;
yield* all(
codeTextContainer().selection(lines(13), animation_length),
eventContent().stroke(HIGHLIGHT, animation_length),
eventContent().lineDash(dashes, animation_length),
eventContent().padding(padding, animation_length),
eventContent().radius(radius, animation_length),
eventContent().lineWidth(dashSize, animation_length),
eventContent().width(CONTAINER_IMAGE_EXPANDED, animation_length),
eventContent().height(CONTAINER_IMAGE_EXPANDED, animation_length),
contentImageRef().width(IMAGE_EXPANDED, animation_length),
contentImageRef().height(IMAGE_EXPANDED, animation_length),
contentBlurhashRef().width(IMAGE_EXPANDED, animation_length),
contentBlurhashRef().height(IMAGE_EXPANDED, animation_length)
);
yield* waitUntil('Show Content');
yield* all(
codeTextContainer().selection(lines(7, 16), animation_length),
//contentImageRef().opacity(0, animation_length),
contentBlurhashRef().opacity(0, animation_length)
);
yield* waitUntil('Back to Overview');
animation_length = 0.8;
yield* all(
colLeft().restore(animation_length),
colRight().restore(animation_length),
codeTextContainer().fontSize(33, animation_length),
textEvent().restore(animation_length),
codeTextContainer().selection(lines(0, 18), animation_length),
delay(animation_length - 0.1, colRightBG().margin.left(0, 0.1))
);
yield* waitUntil('Next Slide');
yield* codeTextContainer().edit(1.2)`${edit(IMAGE_EVENT, NEXT_EVENT)}`;
yield* waitUntil('Next');
});