feat: implement automatic canvas size adjustment based on first media item aspect ratio

This commit is contained in:
Maze Winther
2025-06-30 23:19:37 +02:00
parent d50cd0b40d
commit 3e916f0f00
4 changed files with 107 additions and 10 deletions

View File

@ -1,20 +1,72 @@
import { create } from "zustand";
import { CanvasSize, CanvasPreset } from "@/types/editor";
interface EditorState {
// Loading states
isInitializing: boolean;
isPanelsReady: boolean;
// Canvas/Project settings
canvasSize: CanvasSize;
canvasPresets: CanvasPreset[];
// Actions
setInitializing: (loading: boolean) => void;
setPanelsReady: (ready: boolean) => void;
initializeApp: () => Promise<void>;
setCanvasSize: (size: CanvasSize) => void;
setCanvasSizeFromAspectRatio: (aspectRatio: number) => void;
}
const DEFAULT_CANVAS_PRESETS: CanvasPreset[] = [
{ name: "16:9 HD", width: 1920, height: 1080 },
{ name: "16:9 4K", width: 3840, height: 2160 },
{ name: "9:16 Mobile", width: 1080, height: 1920 },
{ name: "1:1 Square", width: 1080, height: 1080 },
{ name: "4:3 Standard", width: 1440, height: 1080 },
];
// Helper function to find the best matching canvas preset for an aspect ratio
const findBestCanvasPreset = (aspectRatio: number): CanvasSize => {
// Calculate aspect ratio for each preset and find the closest match
let bestMatch = DEFAULT_CANVAS_PRESETS[0]; // Default to 16:9 HD
let smallestDifference = Math.abs(
aspectRatio - bestMatch.width / bestMatch.height
);
for (const preset of DEFAULT_CANVAS_PRESETS) {
const presetAspectRatio = preset.width / preset.height;
const difference = Math.abs(aspectRatio - presetAspectRatio);
if (difference < smallestDifference) {
smallestDifference = difference;
bestMatch = preset;
}
}
// If the difference is still significant (> 0.1), create a custom size
// based on the media aspect ratio with a reasonable resolution
const bestAspectRatio = bestMatch.width / bestMatch.height;
if (Math.abs(aspectRatio - bestAspectRatio) > 0.1) {
// Create custom dimensions based on the aspect ratio
if (aspectRatio > 1) {
// Landscape - use 1920 width
return { width: 1920, height: Math.round(1920 / aspectRatio) };
} else {
// Portrait or square - use 1080 height
return { width: Math.round(1080 * aspectRatio), height: 1080 };
}
}
return { width: bestMatch.width, height: bestMatch.height };
};
export const useEditorStore = create<EditorState>((set, get) => ({
// Initial states
isInitializing: true,
isPanelsReady: false,
canvasSize: { width: 1920, height: 1080 }, // Default 16:9 HD
canvasPresets: DEFAULT_CANVAS_PRESETS,
// Actions
setInitializing: (loading) => {
@ -32,4 +84,17 @@ export const useEditorStore = create<EditorState>((set, get) => ({
set({ isPanelsReady: true, isInitializing: false });
console.log("Video editor ready");
},
setCanvasSize: (size) => {
set({ canvasSize: size });
},
setCanvasSizeFromAspectRatio: (aspectRatio) => {
const newCanvasSize = findBestCanvasPreset(aspectRatio);
console.log(
`Setting canvas size based on aspect ratio ${aspectRatio}:`,
newCanvasSize
);
set({ canvasSize: newCanvasSize });
},
}));