@vibecuting/video-project-core 0.1.27 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/base/BaseRemotionScene.tsx +4 -3
- package/src/core/index.test.ts +40 -0
- package/src/core/scene/2dscene/default-2d-scene-Horizontal.stories.tsx +1 -1
- package/src/core/scene/2dscene/default-2d-scene.stories.tsx +1 -1
- package/src/core/scene/3dscene/default-3d-scene-Horizontal.stories.tsx +1 -1
- package/src/core/scene/3dscene/default-3d-scene.stories.tsx +1 -1
- package/src/core/scene/index.ts +3 -0
- package/src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene-Horizontal.stories.tsx +46 -0
- package/src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene-Horizontal.tsx +20 -0
- package/src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene-Landscape.tsx +20 -0
- package/src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene.stories.tsx +46 -0
- package/src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene.tsx +255 -0
- package/src/core/scene/photo/3dvr-photo/index.ts +3 -0
- package/src/core/scene/photo/default-live-photo-scene-Horizontal.stories.tsx +33 -0
- package/src/core/scene/photo/default-live-photo-scene-Horizontal.tsx +20 -0
- package/src/core/scene/photo/default-live-photo-scene-Landscape.tsx +20 -0
- package/src/core/scene/photo/default-live-photo-scene.stories.tsx +33 -0
- package/src/core/scene/photo/default-live-photo-scene.tsx +432 -0
- package/src/core/scene/photo/default-photo-strip-scene-Horizontal.tsx +20 -0
- package/src/core/scene/photo/default-photo-strip-scene-Landscape.tsx +20 -0
- package/src/core/scene/photo/default-photo-strip-scene.stories.tsx +38 -0
- package/src/core/scene/photo/default-photo-strip-scene.tsx +19 -0
- package/src/core/scene/photo/default-photo-wall-scene-Horizontal.tsx +20 -0
- package/src/core/scene/photo/default-photo-wall-scene-Landscape.tsx +20 -0
- package/src/core/scene/photo/default-photo-wall-scene.stories.tsx +38 -0
- package/src/core/scene/photo/default-photo-wall-scene.tsx +19 -0
- package/src/core/scene/photo/effects-photo/default-effects-photo-scene-Horizontal.stories.tsx +44 -0
- package/src/core/scene/photo/effects-photo/default-effects-photo-scene-Horizontal.tsx +20 -0
- package/src/core/scene/photo/effects-photo/default-effects-photo-scene-Landscape.tsx +20 -0
- package/src/core/scene/photo/effects-photo/default-effects-photo-scene.stories.tsx +44 -0
- package/src/core/scene/photo/effects-photo/default-effects-photo-scene.tsx +352 -0
- package/src/core/scene/photo/effects-photo/index.ts +3 -0
- package/src/core/scene/photo/index.ts +25 -0
- package/src/core/scene/photo/photo-storybook.test.tsx +112 -0
- package/src/core/scene/slide/default-slide-scene-Horizontal.animated.stories.tsx +1 -1
- package/src/core/scene/slide/default-slide-scene-Horizontal.stories.tsx +1 -1
- package/src/core/scene/slide/default-slide-scene.animated.stories.tsx +1 -1
- package/src/core/scene/slide/default-slide-scene.stories.tsx +1 -1
- package/src/core/scene/video/default-video-scene-Horizontal.stories.tsx +26 -0
- package/src/core/scene/video/default-video-scene-Horizontal.tsx +20 -0
- package/src/core/scene/video/default-video-scene-Landscape.tsx +20 -0
- package/src/core/scene/video/default-video-scene.stories.tsx +26 -0
- package/src/core/scene/video/default-video-scene.tsx +283 -0
- package/src/core/scene/video/default-video-split-scene-Horizontal.tsx +20 -0
- package/src/core/scene/video/default-video-split-scene-Landscape.tsx +20 -0
- package/src/core/scene/video/default-video-split-scene.stories.tsx +41 -0
- package/src/core/scene/video/default-video-split-scene.tsx +19 -0
- package/src/core/scene/video/default-video-wall-scene-Horizontal.tsx +20 -0
- package/src/core/scene/video/default-video-wall-scene-Landscape.tsx +20 -0
- package/src/core/scene/video/default-video-wall-scene.stories.tsx +40 -0
- package/src/core/scene/video/default-video-wall-scene.tsx +19 -0
- package/src/core/scene/video/index.ts +9 -0
- package/src/storybook/remotion-preview.tsx +112 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibecuting/video-project-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"test": "pnpm exec vitest run"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@vibecuting/component-project-helper": "0.1.
|
|
25
|
+
"@vibecuting/component-project-helper": "0.1.29",
|
|
26
26
|
"@remotion/transitions": "4.0.473",
|
|
27
27
|
"mermaid": "^11.12.2",
|
|
28
28
|
"react": "^19.0.0",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { CSSProperties, ReactNode } from 'react'
|
|
2
2
|
import { useId } from 'react'
|
|
3
|
-
import { AbsoluteFill } from 'remotion'
|
|
4
3
|
|
|
5
4
|
import { SceneMotionStack } from './use-scene-child-motion'
|
|
6
5
|
import { useResolvedSceneTheme, useSceneConfig } from './use-scene-config'
|
|
@@ -27,7 +26,7 @@ export function BaseRemotionScene({
|
|
|
27
26
|
const resolvedTheme = useResolvedSceneTheme()
|
|
28
27
|
|
|
29
28
|
return (
|
|
30
|
-
<
|
|
29
|
+
<div
|
|
31
30
|
id={resolvedId}
|
|
32
31
|
data-scene-name={name}
|
|
33
32
|
data-scene-display-mode={sceneConfig.sceneType}
|
|
@@ -37,11 +36,13 @@ export function BaseRemotionScene({
|
|
|
37
36
|
...(sceneConfig.sceneToken ? {} : (resolvedTheme?.variables ?? {})),
|
|
38
37
|
overflow: 'hidden',
|
|
39
38
|
position: 'relative',
|
|
39
|
+
width: '100%',
|
|
40
|
+
height: '100%',
|
|
40
41
|
isolation: 'isolate',
|
|
41
42
|
...style,
|
|
42
43
|
}}
|
|
43
44
|
>
|
|
44
45
|
<SceneMotionStack>{children}</SceneMotionStack>
|
|
45
|
-
</
|
|
46
|
+
</div>
|
|
46
47
|
)
|
|
47
48
|
}
|
package/src/core/index.test.ts
CHANGED
|
@@ -3,6 +3,14 @@ import { describe, expect, it } from 'vitest'
|
|
|
3
3
|
import {
|
|
4
4
|
Default2DScene,
|
|
5
5
|
Default3DScene,
|
|
6
|
+
DefaultLivePhotoScene,
|
|
7
|
+
DefaultEffectsPhotoScene,
|
|
8
|
+
Default3DVRPhotoScene,
|
|
9
|
+
DefaultPhotoStripScene,
|
|
10
|
+
DefaultPhotoWallScene,
|
|
11
|
+
DefaultVideoScene,
|
|
12
|
+
DefaultVideoSplitScene,
|
|
13
|
+
DefaultVideoWallScene,
|
|
6
14
|
componentMetadata as abstractBackgroundCoverMetadata,
|
|
7
15
|
componentMetadata as annotationMetadata,
|
|
8
16
|
componentMetadata as beforeAfterMetadata,
|
|
@@ -17,6 +25,18 @@ import {
|
|
|
17
25
|
componentMetadata as calloutMetadata,
|
|
18
26
|
componentMetadata as heroMetadata,
|
|
19
27
|
componentMetadata as imageHeroMetadata,
|
|
28
|
+
DefaultLivePhotoSceneMetadata,
|
|
29
|
+
DefaultEffectsPhotoSceneMetadata,
|
|
30
|
+
DefaultEffectsPhotoSceneLandscapeMetadata,
|
|
31
|
+
DefaultEffectsPhotoSceneHorizontalMetadata,
|
|
32
|
+
Default3DVRPhotoSceneMetadata,
|
|
33
|
+
Default3DVRPhotoSceneLandscapeMetadata,
|
|
34
|
+
Default3DVRPhotoSceneHorizontalMetadata,
|
|
35
|
+
DefaultPhotoStripSceneMetadata,
|
|
36
|
+
DefaultPhotoWallSceneMetadata,
|
|
37
|
+
DefaultVideoSceneMetadata,
|
|
38
|
+
DefaultVideoSplitSceneMetadata,
|
|
39
|
+
DefaultVideoWallSceneMetadata,
|
|
20
40
|
componentMetadata as comparisonMetadata,
|
|
21
41
|
DefaultComparisonSlide,
|
|
22
42
|
componentMetadata as codeSnippetMetadata,
|
|
@@ -104,9 +124,29 @@ describe('video-project-core demo exports', () => {
|
|
|
104
124
|
expect(DefaultOutroBumper).toBeTypeOf('function')
|
|
105
125
|
expect(Default2DScene).toBeTypeOf('function')
|
|
106
126
|
expect(Default3DScene).toBeTypeOf('function')
|
|
127
|
+
expect(DefaultLivePhotoScene).toBeTypeOf('function')
|
|
128
|
+
expect(DefaultEffectsPhotoScene).toBeTypeOf('function')
|
|
129
|
+
expect(Default3DVRPhotoScene).toBeTypeOf('function')
|
|
130
|
+
expect(DefaultEffectsPhotoSceneMetadata.sceneFamily).toBe('custom')
|
|
131
|
+
expect(DefaultEffectsPhotoSceneLandscapeMetadata.sceneFamily).toBe('custom')
|
|
132
|
+
expect(DefaultEffectsPhotoSceneHorizontalMetadata.sceneFamily).toBe('custom')
|
|
133
|
+
expect(Default3DVRPhotoSceneMetadata.sceneFamily).toBe('custom')
|
|
134
|
+
expect(Default3DVRPhotoSceneLandscapeMetadata.sceneFamily).toBe('custom')
|
|
135
|
+
expect(Default3DVRPhotoSceneHorizontalMetadata.sceneFamily).toBe('custom')
|
|
136
|
+
expect(DefaultPhotoWallScene).toBeTypeOf('function')
|
|
137
|
+
expect(DefaultPhotoStripScene).toBeTypeOf('function')
|
|
138
|
+
expect(DefaultVideoScene).toBeTypeOf('function')
|
|
139
|
+
expect(DefaultVideoSplitScene).toBeTypeOf('function')
|
|
140
|
+
expect(DefaultVideoWallScene).toBeTypeOf('function')
|
|
107
141
|
expect(DefaultSlideScene).toBeTypeOf('function')
|
|
108
142
|
expect(heroMetadata.sceneFamily).toBe('slide')
|
|
109
143
|
expect(imageHeroMetadata.sceneFamily).toBe('slide')
|
|
144
|
+
expect(DefaultLivePhotoSceneMetadata.sceneFamily).toBe('custom')
|
|
145
|
+
expect(DefaultPhotoWallSceneMetadata.sceneFamily).toBe('custom')
|
|
146
|
+
expect(DefaultPhotoStripSceneMetadata.sceneFamily).toBe('custom')
|
|
147
|
+
expect(DefaultVideoSceneMetadata.sceneFamily).toBe('custom')
|
|
148
|
+
expect(DefaultVideoSplitSceneMetadata.sceneFamily).toBe('custom')
|
|
149
|
+
expect(DefaultVideoWallSceneMetadata.sceneFamily).toBe('custom')
|
|
110
150
|
expect(splitMetadata.sceneFamily).toBe('slide')
|
|
111
151
|
expect(chapterMetadata.sceneFamily).toBe('slide')
|
|
112
152
|
expect(abstractBackgroundCoverMetadata.sceneFamily).toBe('slide')
|
package/src/core/scene/index.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export * from './2dscene'
|
|
2
2
|
export * from './3dscene'
|
|
3
|
+
export * from './photo'
|
|
4
|
+
export * from './video'
|
|
3
5
|
export * from './slide'
|
|
4
6
|
export * from './utils'
|
|
7
|
+
export { DefaultLivePhotoSceneMetadata, DefaultLivePhotoSceneLandscapeMetadata, DefaultLivePhotoSceneHorizontalMetadata } from './photo'
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Default3DVRPhotoSceneHorizontal } from './default-3dvr-photo-scene-Horizontal'
|
|
2
|
+
|
|
3
|
+
const photoUrl = 'https://heyaai-statics-1342239856.cos.ap-guangzhou.myqcloud.com/tmp/premium_photo-1779404552087-0f905162376f-121.jpeg'
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'core/scene/photo/3dvr-photo/Default3DVRPhotoSceneHorizontal',
|
|
7
|
+
component: Default3DVRPhotoSceneHorizontal,
|
|
8
|
+
args: {
|
|
9
|
+
title: 'Stereo Window',
|
|
10
|
+
subtitle: '3D camera controls over a still frame with subtle orbit, pitch and depth.',
|
|
11
|
+
badge: '3D VR Photo',
|
|
12
|
+
imageSrc: photoUrl,
|
|
13
|
+
yaw: 12,
|
|
14
|
+
pitch: 4,
|
|
15
|
+
roll: 0,
|
|
16
|
+
perspective: 980,
|
|
17
|
+
zoom: 1,
|
|
18
|
+
depth: 26,
|
|
19
|
+
focusX: 0.5,
|
|
20
|
+
focusY: 0.45,
|
|
21
|
+
accent: '#020617',
|
|
22
|
+
secondaryAccent: '#7c3aed',
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default meta
|
|
27
|
+
|
|
28
|
+
export const Default = {
|
|
29
|
+
parameters: {
|
|
30
|
+
scenePreviewAspectRatio: '9:16',
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const Animated = {
|
|
35
|
+
parameters: {
|
|
36
|
+
scenePreviewAspectRatio: '9:16',
|
|
37
|
+
scenePreviewMode: 'animation',
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const Both = {
|
|
42
|
+
parameters: {
|
|
43
|
+
scenePreviewAspectRatio: '9:16',
|
|
44
|
+
scenePreviewMode: 'both',
|
|
45
|
+
},
|
|
46
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react'
|
|
2
|
+
|
|
3
|
+
import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
|
|
4
|
+
|
|
5
|
+
import { Default3DVRPhotoScene, componentMetadata as baseComponentMetadata } from './default-3dvr-photo-scene'
|
|
6
|
+
|
|
7
|
+
export const componentMetadata: ScenePluginMetadata = {
|
|
8
|
+
...baseComponentMetadata,
|
|
9
|
+
name: 'Default3DVRPhotoSceneHorizontal',
|
|
10
|
+
description: '3D VR photo scene for 9:16 portrait previews with a vertical layout',
|
|
11
|
+
sourceFile: 'src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene-Horizontal.tsx',
|
|
12
|
+
aspectRatio: '9:16',
|
|
13
|
+
tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'horizontal'])),
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const Default3DVRPhotoSceneHorizontal = VideoComponent(componentMetadata)(function Default3DVRPhotoSceneHorizontal(
|
|
17
|
+
props: ComponentProps<typeof Default3DVRPhotoScene>,
|
|
18
|
+
) {
|
|
19
|
+
return <Default3DVRPhotoScene {...props} />
|
|
20
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react'
|
|
2
|
+
|
|
3
|
+
import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
|
|
4
|
+
|
|
5
|
+
import { Default3DVRPhotoScene, componentMetadata as baseComponentMetadata } from './default-3dvr-photo-scene'
|
|
6
|
+
|
|
7
|
+
export const componentMetadata: ScenePluginMetadata = {
|
|
8
|
+
...baseComponentMetadata,
|
|
9
|
+
name: 'Default3DVRPhotoSceneLandscape',
|
|
10
|
+
description: '3D VR photo scene for 16:9 landscape previews with a wide cinematic layout',
|
|
11
|
+
sourceFile: 'src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene-Landscape.tsx',
|
|
12
|
+
aspectRatio: '16:9',
|
|
13
|
+
tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'landscape'])),
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const Default3DVRPhotoSceneLandscape = VideoComponent(componentMetadata)(function Default3DVRPhotoSceneLandscape(
|
|
17
|
+
props: ComponentProps<typeof Default3DVRPhotoScene>,
|
|
18
|
+
) {
|
|
19
|
+
return <Default3DVRPhotoScene {...props} />
|
|
20
|
+
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Default3DVRPhotoSceneLandscape } from './default-3dvr-photo-scene-Landscape'
|
|
2
|
+
|
|
3
|
+
const photoUrl = 'https://heyaai-statics-1342239856.cos.ap-guangzhou.myqcloud.com/tmp/premium_photo-1779404552087-0f905162376f-121.jpeg'
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'core/scene/photo/3dvr-photo/Default3DVRPhotoSceneLandscape',
|
|
7
|
+
component: Default3DVRPhotoSceneLandscape,
|
|
8
|
+
args: {
|
|
9
|
+
title: 'Stereo Window',
|
|
10
|
+
subtitle: '3D camera controls over a still frame with subtle orbit, pitch and depth.',
|
|
11
|
+
badge: '3D VR Photo',
|
|
12
|
+
imageSrc: photoUrl,
|
|
13
|
+
yaw: 12,
|
|
14
|
+
pitch: 4,
|
|
15
|
+
roll: 0,
|
|
16
|
+
perspective: 980,
|
|
17
|
+
zoom: 1,
|
|
18
|
+
depth: 26,
|
|
19
|
+
focusX: 0.5,
|
|
20
|
+
focusY: 0.45,
|
|
21
|
+
accent: '#020617',
|
|
22
|
+
secondaryAccent: '#1d4ed8',
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default meta
|
|
27
|
+
|
|
28
|
+
export const Default = {
|
|
29
|
+
parameters: {
|
|
30
|
+
scenePreviewAspectRatio: '16:9',
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const Animated = {
|
|
35
|
+
parameters: {
|
|
36
|
+
scenePreviewAspectRatio: '16:9',
|
|
37
|
+
scenePreviewMode: 'animation',
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const Both = {
|
|
42
|
+
parameters: {
|
|
43
|
+
scenePreviewAspectRatio: '16:9',
|
|
44
|
+
scenePreviewMode: 'both',
|
|
45
|
+
},
|
|
46
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { VideoComponent, defineScenePluginMetadata } from '@vibecuting/component-project-helper'
|
|
4
|
+
import { Img, interpolate, spring, useCurrentFrame, useVideoConfig } from 'remotion'
|
|
5
|
+
|
|
6
|
+
import { BaseRemotionScene, type BaseRemotionSceneProps, useRemotionSceneRuntime, useSceneConfig } from '../../../../base'
|
|
7
|
+
import { defineSceneComponent } from '../../../../plugins/scene-component'
|
|
8
|
+
|
|
9
|
+
export interface Default3DVRPhotoSceneProps extends BaseRemotionSceneProps {
|
|
10
|
+
sceneId?: string
|
|
11
|
+
sceneName?: string
|
|
12
|
+
title?: string
|
|
13
|
+
subtitle?: string
|
|
14
|
+
badge?: string
|
|
15
|
+
imageSrc: string
|
|
16
|
+
yaw?: number
|
|
17
|
+
pitch?: number
|
|
18
|
+
roll?: number
|
|
19
|
+
perspective?: number
|
|
20
|
+
zoom?: number
|
|
21
|
+
depth?: number
|
|
22
|
+
focusX?: number
|
|
23
|
+
focusY?: number
|
|
24
|
+
accent?: string
|
|
25
|
+
secondaryAccent?: string
|
|
26
|
+
textColor?: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const componentMetadata = defineScenePluginMetadata({
|
|
30
|
+
resourceKind: 'scene',
|
|
31
|
+
name: 'Default3DVRPhotoScene',
|
|
32
|
+
description: 'Photo scene with 3D VR camera controls and perspective motion',
|
|
33
|
+
sourceFile: 'src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene.tsx',
|
|
34
|
+
pluginKey: 'core.photo.3dvr-photo',
|
|
35
|
+
tags: ['scene', 'photo', '3d', 'vr', 'perspective'],
|
|
36
|
+
aspectRatio: '16:9',
|
|
37
|
+
sceneType: 'scene',
|
|
38
|
+
sceneFamily: 'custom',
|
|
39
|
+
rootLayout: 'absolute-fill',
|
|
40
|
+
propsTypeName: 'Default3DVRPhotoSceneProps',
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
export const Default3DVRPhotoScene = VideoComponent(componentMetadata)(
|
|
44
|
+
defineSceneComponent({
|
|
45
|
+
family: 'custom',
|
|
46
|
+
propsSchema: z.object({
|
|
47
|
+
sceneId: z.string().optional(),
|
|
48
|
+
sceneName: z.string().optional(),
|
|
49
|
+
title: z.string().optional(),
|
|
50
|
+
subtitle: z.string().optional(),
|
|
51
|
+
badge: z.string().optional(),
|
|
52
|
+
imageSrc: z.string(),
|
|
53
|
+
yaw: z.number().optional(),
|
|
54
|
+
pitch: z.number().optional(),
|
|
55
|
+
roll: z.number().optional(),
|
|
56
|
+
perspective: z.number().optional(),
|
|
57
|
+
zoom: z.number().optional(),
|
|
58
|
+
depth: z.number().optional(),
|
|
59
|
+
focusX: z.number().min(0).max(1).optional(),
|
|
60
|
+
focusY: z.number().min(0).max(1).optional(),
|
|
61
|
+
accent: z.string().optional(),
|
|
62
|
+
secondaryAccent: z.string().optional(),
|
|
63
|
+
textColor: z.string().optional(),
|
|
64
|
+
}),
|
|
65
|
+
component: function Default3DVRPhotoScene({
|
|
66
|
+
id,
|
|
67
|
+
name,
|
|
68
|
+
sceneId,
|
|
69
|
+
sceneName,
|
|
70
|
+
title,
|
|
71
|
+
subtitle,
|
|
72
|
+
badge,
|
|
73
|
+
imageSrc,
|
|
74
|
+
yaw = 12,
|
|
75
|
+
pitch = 4,
|
|
76
|
+
roll = 0,
|
|
77
|
+
perspective = 980,
|
|
78
|
+
zoom = 1,
|
|
79
|
+
depth = 24,
|
|
80
|
+
focusX = 0.5,
|
|
81
|
+
focusY = 0.5,
|
|
82
|
+
accent,
|
|
83
|
+
secondaryAccent,
|
|
84
|
+
textColor,
|
|
85
|
+
}: Default3DVRPhotoSceneProps) {
|
|
86
|
+
const runtime = useRemotionSceneRuntime()
|
|
87
|
+
const sceneConfig = useSceneConfig()
|
|
88
|
+
const frame = useCurrentFrame()
|
|
89
|
+
const { fps } = useVideoConfig()
|
|
90
|
+
const portrait = runtime.height > runtime.width
|
|
91
|
+
const animated = sceneConfig.sceneType === 'animation'
|
|
92
|
+
const entrance = sceneConfig.sceneType === 'animation' ? spring({ frame, fps, delay: 4, config: { damping: 18, mass: 0.8, stiffness: 120 } }) : 1
|
|
93
|
+
const orbit = animated ? Math.sin((frame / fps) * Math.PI * 0.55) : 0
|
|
94
|
+
const cameraYaw = yaw + orbit * 4 + (1 - entrance) * (portrait ? -3 : -4)
|
|
95
|
+
const cameraPitch = pitch + Math.sin((frame / fps) * Math.PI * 0.35) * 1.5 + (1 - entrance) * 1.6
|
|
96
|
+
const cameraRoll = roll + Math.sin((frame / fps) * Math.PI * 0.25) * 0.45
|
|
97
|
+
const cameraZoom = zoom + entrance * 0.06 + (1 - entrance) * 0.02
|
|
98
|
+
const titleSize = Math.round(runtime.height * (portrait ? 0.034 : 0.04))
|
|
99
|
+
const subtitleSize = Math.round(runtime.height * 0.017)
|
|
100
|
+
const focusOffsetX = interpolate(focusX, [0, 1], [-12, 12])
|
|
101
|
+
const focusOffsetY = interpolate(focusY, [0, 1], [12, -12])
|
|
102
|
+
const imageFilter = animated ? 'brightness(1.08) contrast(1.04) saturate(1.08)' : 'brightness(2.05) contrast(1.22) saturate(1.3)'
|
|
103
|
+
const framePaddingX = Math.round(runtime.width * (portrait ? 0.025 : 0.02))
|
|
104
|
+
const framePaddingY = Math.round(runtime.height * (portrait ? 0.02 : 0.018))
|
|
105
|
+
const mainFrameLeft = framePaddingX
|
|
106
|
+
const mainFrameTop = framePaddingY
|
|
107
|
+
const mainFrameWidth = Math.max(1, runtime.width - framePaddingX * 2)
|
|
108
|
+
const mainFrameHeight = Math.max(1, runtime.height - framePaddingY * 2)
|
|
109
|
+
const mainFrameShadow = portrait
|
|
110
|
+
? '0 26px 90px rgba(0,0,0,0.38)'
|
|
111
|
+
: '0 34px 110px rgba(0,0,0,0.42)'
|
|
112
|
+
const imageTransform = animated
|
|
113
|
+
? `translate3d(${focusOffsetX}px, ${focusOffsetY}px, ${depth}px) rotateX(${cameraPitch}deg) rotateY(${cameraYaw}deg) rotateZ(${cameraRoll}deg) scale(${cameraZoom})`
|
|
114
|
+
: `translate3d(${focusOffsetX * 0.4}px, ${focusOffsetY * 0.35}px, ${depth * 0.45}px) rotateX(${pitch * 0.15}deg) rotateY(${yaw * 0.12}deg) rotateZ(${roll * 0.08}deg) scale(${1.01 + (zoom - 1) * 0.4})`
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<BaseRemotionScene
|
|
118
|
+
id={id ?? sceneId}
|
|
119
|
+
name={name ?? sceneName ?? title}
|
|
120
|
+
style={{
|
|
121
|
+
background:
|
|
122
|
+
portrait
|
|
123
|
+
? `linear-gradient(180deg, ${accent ?? '#020617'} 0%, #000000 100%)`
|
|
124
|
+
: `radial-gradient(circle at 50% 20%, ${secondaryAccent ?? 'rgba(255,255,255,0.08)'} 0%, ${accent ?? '#020617'} 52%, #000000 100%)`,
|
|
125
|
+
color: textColor ?? '#f8fafc',
|
|
126
|
+
padding: Math.round(runtime.height * (portrait ? 0.02 : 0.03)),
|
|
127
|
+
}}
|
|
128
|
+
>
|
|
129
|
+
<div
|
|
130
|
+
style={{
|
|
131
|
+
position: 'absolute',
|
|
132
|
+
inset: 0,
|
|
133
|
+
overflow: 'hidden',
|
|
134
|
+
border: '1px solid rgba(255,255,255,0.12)',
|
|
135
|
+
background: 'rgba(2,6,23,0.84)',
|
|
136
|
+
perspective: `${perspective}px`,
|
|
137
|
+
transformStyle: 'preserve-3d',
|
|
138
|
+
isolation: 'isolate',
|
|
139
|
+
}}
|
|
140
|
+
>
|
|
141
|
+
<div
|
|
142
|
+
aria-hidden="true"
|
|
143
|
+
style={{
|
|
144
|
+
position: 'absolute',
|
|
145
|
+
top: Math.max(0, mainFrameTop - 18),
|
|
146
|
+
left: Math.max(0, mainFrameLeft - 18),
|
|
147
|
+
width: Math.max(1, mainFrameWidth + 36),
|
|
148
|
+
height: Math.max(1, mainFrameHeight + 36),
|
|
149
|
+
opacity: animated ? 0.2 + entrance * 0.08 : 0.04,
|
|
150
|
+
filter: animated ? 'blur(18px) saturate(1.12) brightness(0.95)' : 'blur(10px) saturate(1.05) brightness(1.05)',
|
|
151
|
+
transform: `translate3d(${focusOffsetX * 0.3}px, ${focusOffsetY * 0.22}px, -20px) scale(${1.05 + entrance * 0.04})`,
|
|
152
|
+
}}
|
|
153
|
+
>
|
|
154
|
+
<Img
|
|
155
|
+
src={imageSrc}
|
|
156
|
+
alt={title ?? '3D VR photo'}
|
|
157
|
+
style={{
|
|
158
|
+
width: '100%',
|
|
159
|
+
height: '100%',
|
|
160
|
+
objectFit: 'cover',
|
|
161
|
+
}}
|
|
162
|
+
/>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<div
|
|
166
|
+
style={{
|
|
167
|
+
position: 'absolute',
|
|
168
|
+
top: mainFrameTop,
|
|
169
|
+
left: mainFrameLeft,
|
|
170
|
+
width: mainFrameWidth,
|
|
171
|
+
height: mainFrameHeight,
|
|
172
|
+
transformStyle: 'preserve-3d',
|
|
173
|
+
transform: imageTransform,
|
|
174
|
+
border: animated ? '1px solid rgba(255,255,255,0.12)' : '1px solid rgba(255,255,255,0.2)',
|
|
175
|
+
backgroundColor: animated ? 'rgba(2,6,23,0.2)' : 'rgba(248,250,252,0.08)',
|
|
176
|
+
backgroundImage: `url(${imageSrc})`,
|
|
177
|
+
backgroundSize: 'cover',
|
|
178
|
+
backgroundPosition: `${Math.round(focusX * 100)}% ${Math.round((1 - focusY) * 100)}%`,
|
|
179
|
+
backgroundRepeat: 'no-repeat',
|
|
180
|
+
boxShadow: animated ? '0 22px 70px rgba(0,0,0,0.32)' : '0 14px 42px rgba(0,0,0,0.2)',
|
|
181
|
+
overflow: 'hidden',
|
|
182
|
+
borderRadius: 0,
|
|
183
|
+
filter: imageFilter,
|
|
184
|
+
}}
|
|
185
|
+
>
|
|
186
|
+
</div>
|
|
187
|
+
|
|
188
|
+
<div
|
|
189
|
+
aria-hidden="true"
|
|
190
|
+
style={{
|
|
191
|
+
position: 'absolute',
|
|
192
|
+
inset: 0,
|
|
193
|
+
background:
|
|
194
|
+
animated
|
|
195
|
+
? 'radial-gradient(circle at center, rgba(255,255,255,0.06) 0%, rgba(255,255,255,0.01) 26%, rgba(2,6,23,0.14) 52%, rgba(2,6,23,0.46) 100%)'
|
|
196
|
+
: 'radial-gradient(circle at center, rgba(255,255,255,0.00) 0%, rgba(255,255,255,0.00) 44%, rgba(2,6,23,0.01) 76%, rgba(2,6,23,0.04) 100%)',
|
|
197
|
+
pointerEvents: 'none',
|
|
198
|
+
}}
|
|
199
|
+
/>
|
|
200
|
+
|
|
201
|
+
<div
|
|
202
|
+
aria-hidden="true"
|
|
203
|
+
style={{
|
|
204
|
+
position: 'absolute',
|
|
205
|
+
top: mainFrameTop,
|
|
206
|
+
left: mainFrameLeft,
|
|
207
|
+
width: mainFrameWidth,
|
|
208
|
+
height: mainFrameHeight,
|
|
209
|
+
border: '1px solid rgba(255,255,255,0.18)',
|
|
210
|
+
pointerEvents: 'none',
|
|
211
|
+
}}
|
|
212
|
+
/>
|
|
213
|
+
|
|
214
|
+
<div
|
|
215
|
+
style={{
|
|
216
|
+
position: 'absolute',
|
|
217
|
+
inset: 0,
|
|
218
|
+
display: 'grid',
|
|
219
|
+
alignContent: 'space-between',
|
|
220
|
+
padding: Math.round(runtime.height * (portrait ? 0.02 : 0.03)),
|
|
221
|
+
zIndex: 2,
|
|
222
|
+
pointerEvents: 'none',
|
|
223
|
+
}}
|
|
224
|
+
>
|
|
225
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start', gap: 12 }}>
|
|
226
|
+
<div
|
|
227
|
+
style={{
|
|
228
|
+
display: 'inline-flex',
|
|
229
|
+
alignItems: 'center',
|
|
230
|
+
gap: 8,
|
|
231
|
+
border: '1px solid rgba(255,255,255,0.18)',
|
|
232
|
+
background: 'rgba(2,6,23,0.6)',
|
|
233
|
+
color: '#f8fafc',
|
|
234
|
+
padding: '8px 12px',
|
|
235
|
+
letterSpacing: '0.22em',
|
|
236
|
+
textTransform: 'uppercase',
|
|
237
|
+
fontSize: 11,
|
|
238
|
+
lineHeight: 1,
|
|
239
|
+
}}
|
|
240
|
+
>
|
|
241
|
+
{badge ?? '3D VR Photo'}
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
|
|
245
|
+
<div style={{ display: 'grid', gap: 8, maxWidth: portrait ? '86%' : '58%' }}>
|
|
246
|
+
{title ? <div style={{ fontSize: titleSize, fontWeight: 800, letterSpacing: '-0.06em', lineHeight: 0.94 }}>{title}</div> : null}
|
|
247
|
+
{subtitle ? <div style={{ fontSize: subtitleSize, lineHeight: 1.45, opacity: 0.84 }}>{subtitle}</div> : null}
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
</BaseRemotionScene>
|
|
252
|
+
)
|
|
253
|
+
},
|
|
254
|
+
}),
|
|
255
|
+
)
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { Default3DVRPhotoScene, componentMetadata as Default3DVRPhotoSceneMetadata } from './default-3dvr-photo-scene'
|
|
2
|
+
export { Default3DVRPhotoSceneLandscape, componentMetadata as Default3DVRPhotoSceneLandscapeMetadata } from './default-3dvr-photo-scene-Landscape'
|
|
3
|
+
export { Default3DVRPhotoSceneHorizontal, componentMetadata as Default3DVRPhotoSceneHorizontalMetadata } from './default-3dvr-photo-scene-Horizontal'
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DefaultLivePhotoSceneHorizontal } from './default-live-photo-scene-Horizontal'
|
|
2
|
+
|
|
3
|
+
const photoUrl = 'https://heyaai-statics-1342239856.cos.ap-guangzhou.myqcloud.com/tmp/premium_photo-1779404552087-0f905162376f-121.jpeg'
|
|
4
|
+
const photo = <img src={photoUrl} alt="Night Street" />
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'core/scene/photo/DefaultLivePhotoSceneHorizontal',
|
|
8
|
+
component: DefaultLivePhotoSceneHorizontal,
|
|
9
|
+
args: {
|
|
10
|
+
title: 'Night Street',
|
|
11
|
+
subtitle: 'Portrait live-photo treatment with a tighter frame and the same subtle motion language.',
|
|
12
|
+
badge: 'Live Photo',
|
|
13
|
+
accent: '#020617',
|
|
14
|
+
secondaryAccent: '#7c3aed',
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default meta
|
|
19
|
+
|
|
20
|
+
export const Default = {
|
|
21
|
+
render: (storyArgs: (typeof meta)['args']) => <DefaultLivePhotoSceneHorizontal {...storyArgs} image={photo} />,
|
|
22
|
+
parameters: {
|
|
23
|
+
scenePreviewAspectRatio: '9:16',
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const Animated = {
|
|
28
|
+
render: (storyArgs: (typeof meta)['args']) => <DefaultLivePhotoSceneHorizontal {...storyArgs} image={photo} />,
|
|
29
|
+
parameters: {
|
|
30
|
+
scenePreviewAspectRatio: '9:16',
|
|
31
|
+
scenePreviewMode: 'animation',
|
|
32
|
+
},
|
|
33
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react'
|
|
2
|
+
|
|
3
|
+
import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
|
|
4
|
+
|
|
5
|
+
import { DefaultLivePhotoScene, componentMetadata as baseComponentMetadata } from './default-live-photo-scene'
|
|
6
|
+
|
|
7
|
+
export const componentMetadata: ScenePluginMetadata = {
|
|
8
|
+
...baseComponentMetadata,
|
|
9
|
+
name: 'DefaultLivePhotoSceneHorizontal',
|
|
10
|
+
description: 'Apple-style live photo scene for 9:16 portrait previews with a tighter vertical crop',
|
|
11
|
+
sourceFile: 'src/core/scene/photo/default-live-photo-scene-Horizontal.tsx',
|
|
12
|
+
aspectRatio: '9:16',
|
|
13
|
+
tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'horizontal'])),
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const DefaultLivePhotoSceneHorizontal = VideoComponent(componentMetadata)(function DefaultLivePhotoSceneHorizontal(
|
|
17
|
+
props: ComponentProps<typeof DefaultLivePhotoScene>,
|
|
18
|
+
) {
|
|
19
|
+
return <DefaultLivePhotoScene {...props} />
|
|
20
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react'
|
|
2
|
+
|
|
3
|
+
import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
|
|
4
|
+
|
|
5
|
+
import { DefaultLivePhotoScene, componentMetadata as baseComponentMetadata } from './default-live-photo-scene'
|
|
6
|
+
|
|
7
|
+
export const componentMetadata: ScenePluginMetadata = {
|
|
8
|
+
...baseComponentMetadata,
|
|
9
|
+
name: 'DefaultLivePhotoSceneLandscape',
|
|
10
|
+
description: 'Apple-style live photo scene for 16:9 landscape previews with a wider cinematic crop',
|
|
11
|
+
sourceFile: 'src/core/scene/photo/default-live-photo-scene-Landscape.tsx',
|
|
12
|
+
aspectRatio: '16:9',
|
|
13
|
+
tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'landscape'])),
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const DefaultLivePhotoSceneLandscape = VideoComponent(componentMetadata)(function DefaultLivePhotoSceneLandscape(
|
|
17
|
+
props: ComponentProps<typeof DefaultLivePhotoScene>,
|
|
18
|
+
) {
|
|
19
|
+
return <DefaultLivePhotoScene {...props} />
|
|
20
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DefaultLivePhotoSceneLandscape } from './default-live-photo-scene-Landscape'
|
|
2
|
+
|
|
3
|
+
const photoUrl = 'https://heyaai-statics-1342239856.cos.ap-guangzhou.myqcloud.com/tmp/premium_photo-1779404552087-0f905162376f-121.jpeg'
|
|
4
|
+
const photo = <img src={photoUrl} alt="Summer Harbor" />
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'core/scene/photo/DefaultLivePhotoSceneLandscape',
|
|
8
|
+
component: DefaultLivePhotoSceneLandscape,
|
|
9
|
+
args: {
|
|
10
|
+
title: 'Summer Harbor',
|
|
11
|
+
subtitle: 'A single image scene with an Apple-style live push-in and luminous framing.',
|
|
12
|
+
badge: 'Live Photo',
|
|
13
|
+
accent: '#020617',
|
|
14
|
+
secondaryAccent: '#1d4ed8',
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default meta
|
|
19
|
+
|
|
20
|
+
export const Default = {
|
|
21
|
+
render: (storyArgs: (typeof meta)['args']) => <DefaultLivePhotoSceneLandscape {...storyArgs} image={photo} />,
|
|
22
|
+
parameters: {
|
|
23
|
+
scenePreviewAspectRatio: '16:9',
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const Animated = {
|
|
28
|
+
render: (storyArgs: (typeof meta)['args']) => <DefaultLivePhotoSceneLandscape {...storyArgs} image={photo} />,
|
|
29
|
+
parameters: {
|
|
30
|
+
scenePreviewAspectRatio: '16:9',
|
|
31
|
+
scenePreviewMode: 'animation',
|
|
32
|
+
},
|
|
33
|
+
}
|