Split renderer bundles by feature
This commit is contained in:
1 parent
7bf18636d6
commit
fa8c52b239
3 files changed
+85
-15
No files matched your search
+2
-2
@@ -28,7 +28,6 @@ import ClipartDrawer from './components/ClipartDrawer.vue'
|
||||
import SceneDrawer from './components/SceneDrawer.vue'
|
||||
import DocumentDrawer from './components/DocumentDrawer.vue'
|
||||
import DocumentSettings from './components/DocumentSettings.vue'
|
||||
import ExportDialog from './components/ExportDialog.vue'
|
||||
import FullscreenPreview from './components/FullscreenPreview.vue'
|
||||
import PropertiesPanel from './components/PropertiesPanel.vue'
|
||||
import SvgLayerPanel from './components/SvgLayerPanel.vue'
|
||||
@@ -46,7 +45,6 @@ import { usePlaybackLoop } from './composables/usePlaybackLoop'
|
||||
import { useTimeFormat } from './composables/useTimeFormat'
|
||||
import { useProjectName } from './composables/useProjectName'
|
||||
import { shouldChromeClickDeselect } from './lib/chromeClick'
|
||||
import { renderSceneToStillImage } from './lib/stillImageExport'
|
||||
import { ProjectFileError, pickProjectFile } from './lib/projectFile'
|
||||
import { readAnyProjectFile } from './lib/ruwFile'
|
||||
import {
|
||||
@@ -73,6 +71,7 @@ const helpOpen = ref(false)
|
||||
const TestOverlay = import.meta.env.DEV
|
||||
? defineAsyncComponent(() => import('./devtools/TestOverlay.vue'))
|
||||
: null
|
||||
const ExportDialog = defineAsyncComponent(() => import('./components/ExportDialog.vue'))
|
||||
const TIMELINE_HEIGHT_KEY = 'animatr:timelineHeight'
|
||||
const DEFAULT_TIMELINE_HEIGHT = 220
|
||||
const MIN_TIMELINE_HEIGHT = 120
|
||||
@@ -313,6 +312,7 @@ async function copyStillToClipboard() {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const { renderSceneToStillImage } = await import('./lib/stillImageExport')
|
||||
const scene = JSON.parse(JSON.stringify(store.scene))
|
||||
const blob = await renderSceneToStillImage(scene, store.playhead, 'png')
|
||||
// ClipboardItem is widely available in modern Chromium / Firefox
|
||||
|
||||
@@ -12,14 +12,6 @@ import {
|
||||
PhGif,
|
||||
} from '@phosphor-icons/vue'
|
||||
import { useSceneStore } from '@/stores/scene'
|
||||
import { downloadExampleHtml, downloadRuntime, downloadSceneExport } from '@/lib/exportPlayer'
|
||||
import { downloadSceneAsVideo, pickMimeType } from '@/lib/videoExport'
|
||||
import { downloadSceneAsGif } from '@/lib/gifExport'
|
||||
import { downloadSceneAsApng, downloadSceneAsApngPreview } from '@/lib/apngExport'
|
||||
import { hasDesktopRender, renderMp4OnDesktop } from '@/lib/desktopRenderExport'
|
||||
import { downloadFromServer } from '@/lib/serverExport'
|
||||
import { downloadRuwFile } from '@/lib/ruwFile'
|
||||
import { downloadSceneAsStillImage } from '@/lib/stillImageExport'
|
||||
import { useProjectName } from '@/composables/useProjectName'
|
||||
import type { ButtonAsset, Layer } from '@/types/scene'
|
||||
import { Modal } from '@/components/ui'
|
||||
@@ -39,7 +31,20 @@ interface ProgressState {
|
||||
}
|
||||
const progress = ref<ProgressState | null>(null)
|
||||
|
||||
const videoSupported = pickMimeType() !== null
|
||||
const VIDEO_MIME_CANDIDATES = [
|
||||
'video/webm;codecs=vp9',
|
||||
'video/webm;codecs=vp8',
|
||||
'video/webm',
|
||||
'video/mp4;codecs=h264',
|
||||
'video/mp4',
|
||||
]
|
||||
|
||||
function canRecordVideo(): boolean {
|
||||
if (typeof MediaRecorder === 'undefined') return false
|
||||
return VIDEO_MIME_CANDIDATES.some((mime) => MediaRecorder.isTypeSupported?.(mime))
|
||||
}
|
||||
|
||||
const videoSupported = canRecordVideo()
|
||||
|
||||
// Opt-in: strip layers that are hidden in the editor (`editorHidden`)
|
||||
// from the exported scene. Default off — editor-hide is a workflow
|
||||
@@ -198,17 +203,20 @@ function activeSceneClone() {
|
||||
return scene
|
||||
}
|
||||
|
||||
function exportScene() {
|
||||
async function exportScene() {
|
||||
const { downloadSceneExport } = await import('@/lib/exportPlayer')
|
||||
downloadSceneExport(projectClone())
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
|
||||
function exportRuntime() {
|
||||
async function exportRuntime() {
|
||||
const { downloadRuntime } = await import('@/lib/exportPlayer')
|
||||
downloadRuntime()
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
|
||||
function exportRuwBundle() {
|
||||
async function exportRuwBundle() {
|
||||
const { downloadRuwFile } = await import('@/lib/ruwFile')
|
||||
// Re-import target: .ruw is the round-trippable format the welcome
|
||||
// dialog + file-picker accept. Pull the project via projectForSave
|
||||
// so the editor-session UI state (zoom, toggles, …) rides along.
|
||||
@@ -219,7 +227,8 @@ function exportRuwBundle() {
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
|
||||
function exportHtml() {
|
||||
async function exportHtml() {
|
||||
const { downloadExampleHtml } = await import('@/lib/exportPlayer')
|
||||
downloadExampleHtml(projectClone())
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
@@ -234,6 +243,7 @@ async function exportStillImage(format: 'png' | 'jpg') {
|
||||
const opts = targetSizeChanged.value
|
||||
? { targetWidth: targetWidth.value, targetHeight: targetHeight.value }
|
||||
: undefined
|
||||
const { downloadSceneAsStillImage } = await import('@/lib/stillImageExport')
|
||||
await downloadSceneAsStillImage(
|
||||
activeSceneClone(),
|
||||
store.playhead,
|
||||
@@ -255,6 +265,7 @@ async function exportWebm() {
|
||||
}
|
||||
store.pause()
|
||||
try {
|
||||
const { downloadSceneAsVideo } = await import('@/lib/videoExport')
|
||||
await downloadSceneAsVideo(activeSceneClone(), {
|
||||
signal: controller.signal,
|
||||
onProgress: (p) => {
|
||||
@@ -283,6 +294,7 @@ async function exportGif() {
|
||||
}
|
||||
store.pause()
|
||||
try {
|
||||
const { downloadSceneAsGif } = await import('@/lib/gifExport')
|
||||
await downloadSceneAsGif(
|
||||
activeSceneClone(),
|
||||
frameExportOpts(controller, (p) => {
|
||||
@@ -311,6 +323,7 @@ async function exportApng() {
|
||||
}
|
||||
store.pause()
|
||||
try {
|
||||
const { downloadSceneAsApng } = await import('@/lib/apngExport')
|
||||
await downloadSceneAsApng(
|
||||
activeSceneClone(),
|
||||
frameExportOpts(controller, (p) => {
|
||||
@@ -339,6 +352,7 @@ async function exportApngPreview() {
|
||||
}
|
||||
store.pause()
|
||||
try {
|
||||
const { downloadSceneAsApngPreview } = await import('@/lib/apngExport')
|
||||
await downloadSceneAsApngPreview(
|
||||
activeSceneClone(),
|
||||
frameExportOpts(controller, (p) => {
|
||||
@@ -370,6 +384,7 @@ async function exportMp4Server() {
|
||||
store.pause()
|
||||
try {
|
||||
const scene = activeSceneClone()
|
||||
const { hasDesktopRender, renderMp4OnDesktop } = await import('@/lib/desktopRenderExport')
|
||||
if (hasDesktopRender()) {
|
||||
const result = await renderMp4OnDesktop(scene, {
|
||||
signal: controller.signal,
|
||||
@@ -384,6 +399,7 @@ async function exportMp4Server() {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
const { downloadFromServer } = await import('@/lib/serverExport')
|
||||
await downloadFromServer(scene, {
|
||||
signal: controller.signal,
|
||||
fps: targetFps.value,
|
||||
|
||||
@@ -5,6 +5,60 @@ import { fileURLToPath, URL } from 'node:url'
|
||||
export default defineConfig({
|
||||
base: './',
|
||||
plugins: [vue()],
|
||||
build: {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks(id) {
|
||||
if (id.includes('/src/i18n/')) return 'i18n'
|
||||
if (
|
||||
id.includes('/src/components/CanvasStage.vue') ||
|
||||
id.includes('/src/components/AssetSidebar.vue') ||
|
||||
id.includes('/src/components/PropertiesPanel.vue') ||
|
||||
id.includes('/src/components/ActionEditor.vue') ||
|
||||
id.includes('/src/components/FontPicker.vue') ||
|
||||
id.includes('/src/components/RangeSlider.vue') ||
|
||||
id.includes('/src/components/SvgLayerPanel.vue') ||
|
||||
id.includes('/src/stores/scene.ts') ||
|
||||
id.includes('/src/types/scene.ts') ||
|
||||
id.includes('/src/lib/render.ts') ||
|
||||
id.includes('/src/lib/interpolate.ts') ||
|
||||
id.includes('/src/lib/wiggle.ts') ||
|
||||
id.includes('/src/lib/kaleido.ts') ||
|
||||
id.includes('/src/lib/clipBounds.ts') ||
|
||||
id.includes('/src/lib/actions.ts') ||
|
||||
id.includes('/src/lib/sceneOrder.ts') ||
|
||||
id.includes('/src/composables/useButtonRuntime.ts')
|
||||
) {
|
||||
return 'editor'
|
||||
}
|
||||
if (
|
||||
id.includes('/src/components/Timeline.vue') ||
|
||||
id.includes('/src/lib/timelineSnap.ts') ||
|
||||
id.includes('/src/composables/useAudioWaveform.ts')
|
||||
) {
|
||||
return 'timeline'
|
||||
}
|
||||
if (!id.includes('/node_modules/')) return undefined
|
||||
if (id.includes('/@phosphor-icons/vue/')) return 'icons'
|
||||
if (id.includes('/konva/') || id.includes('/vue-konva/')) return 'canvas'
|
||||
if (
|
||||
id.includes('/gifenc/') ||
|
||||
id.includes('/upng-js/')
|
||||
) {
|
||||
return 'encoders'
|
||||
}
|
||||
if (
|
||||
id.includes('/vue/') ||
|
||||
id.includes('/@vue/') ||
|
||||
id.includes('/pinia/')
|
||||
) {
|
||||
return 'framework'
|
||||
}
|
||||
return 'vendor'
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
server: {
|
||||
port: 5200,
|
||||
|
||||
Reference in new issue
Block a user