Skip to content

Commit 293d8bd

Browse files
committed
feat: replace motion blur toggle with intensity slider
Motion blur was a boolean switch (on/off). This changes it to a slider from 0 (off) to 1 (full intensity), with 0.35 as the recommended sweet spot per feedback on PR siddharthvaddem#207. - EditorState/ProjectEditorState: motionBlurEnabled:bool → motionBlurAmount:number - SettingsPanel: Switch → Slider (0–1, step 0.01); shows 'off' or value - VideoPlayback/zoomTransform: scale blur by amount instead of boolean gate - FrameRenderer/VideoExporter/GifExporter: propagate numeric amount - projectPersistence: backward-compat loader (old true → 0.35, false → 0)
1 parent 56988e8 commit 293d8bd

9 files changed

Lines changed: 59 additions & 45 deletions

File tree

src/components/video-editor/SettingsPanel.tsx

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ interface SettingsPanelProps {
9090
onShadowCommit?: () => void;
9191
showBlur?: boolean;
9292
onBlurChange?: (showBlur: boolean) => void;
93-
motionBlurEnabled?: boolean;
94-
onMotionBlurChange?: (enabled: boolean) => void;
93+
motionBlurAmount?: number;
94+
onMotionBlurChange?: (amount: number) => void;
9595
borderRadius?: number;
9696
onBorderRadiusChange?: (radius: number) => void;
9797
onBorderRadiusCommit?: () => void;
@@ -155,7 +155,7 @@ export function SettingsPanel({
155155
onShadowCommit,
156156
showBlur,
157157
onBlurChange,
158-
motionBlurEnabled = false,
158+
motionBlurAmount = 0,
159159
onMotionBlurChange,
160160
borderRadius = 0,
161161
onBorderRadiusChange,
@@ -473,14 +473,6 @@ export function SettingsPanel({
473473
</AccordionTrigger>
474474
<AccordionContent className="pb-3">
475475
<div className="grid grid-cols-2 gap-2 mb-3">
476-
<div className="flex items-center justify-between p-2 rounded-lg bg-white/5 border border-white/5">
477-
<div className="text-[10px] font-medium text-slate-300">Motion Blur</div>
478-
<Switch
479-
checked={motionBlurEnabled}
480-
onCheckedChange={onMotionBlurChange}
481-
className="data-[state=checked]:bg-[#34B27B] scale-90"
482-
/>
483-
</div>
484476
<div className="flex items-center justify-between p-2 rounded-lg bg-white/5 border border-white/5">
485477
<div className="text-[10px] font-medium text-slate-300">Blur BG</div>
486478
<Switch
@@ -492,6 +484,23 @@ export function SettingsPanel({
492484
</div>
493485

494486
<div className="grid grid-cols-2 gap-2">
487+
<div className="p-2 rounded-lg bg-white/5 border border-white/5">
488+
<div className="flex items-center justify-between mb-1">
489+
<div className="text-[10px] font-medium text-slate-300">Motion Blur</div>
490+
<span className="text-[10px] text-slate-500 font-mono">
491+
{motionBlurAmount === 0 ? "off" : motionBlurAmount.toFixed(2)}
492+
</span>
493+
</div>
494+
<Slider
495+
value={[motionBlurAmount]}
496+
onValueChange={(values) => onMotionBlurChange?.(values[0])}
497+
onValueCommit={(values) => onMotionBlurChange?.(values[0])}
498+
min={0}
499+
max={1}
500+
step={0.01}
501+
className="w-full [&_[role=slider]]:bg-[#34B27B] [&_[role=slider]]:border-[#34B27B] [&_[role=slider]]:h-3 [&_[role=slider]]:w-3"
502+
/>
503+
</div>
495504
<div className="p-2 rounded-lg bg-white/5 border border-white/5">
496505
<div className="flex items-center justify-between mb-1">
497506
<div className="text-[10px] font-medium text-slate-300">Shadow</div>

src/components/video-editor/VideoEditor.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export default function VideoEditor() {
7070
wallpaper,
7171
shadowIntensity,
7272
showBlur,
73-
motionBlurEnabled,
73+
motionBlurAmount,
7474
borderRadius,
7575
padding,
7676
aspectRatio,
@@ -139,7 +139,7 @@ export default function VideoEditor() {
139139
wallpaper: normalizedEditor.wallpaper,
140140
shadowIntensity: normalizedEditor.shadowIntensity,
141141
showBlur: normalizedEditor.showBlur,
142-
motionBlurEnabled: normalizedEditor.motionBlurEnabled,
142+
motionBlurAmount: normalizedEditor.motionBlurAmount,
143143
borderRadius: normalizedEditor.borderRadius,
144144
padding: normalizedEditor.padding,
145145
cropRegion: normalizedEditor.cropRegion,
@@ -198,7 +198,7 @@ export default function VideoEditor() {
198198
wallpaper,
199199
shadowIntensity,
200200
showBlur,
201-
motionBlurEnabled,
201+
motionBlurAmount,
202202
borderRadius,
203203
padding,
204204
cropRegion,
@@ -220,7 +220,7 @@ export default function VideoEditor() {
220220
wallpaper,
221221
shadowIntensity,
222222
showBlur,
223-
motionBlurEnabled,
223+
motionBlurAmount,
224224
borderRadius,
225225
padding,
226226
cropRegion,
@@ -294,7 +294,7 @@ export default function VideoEditor() {
294294
wallpaper,
295295
shadowIntensity,
296296
showBlur,
297-
motionBlurEnabled,
297+
motionBlurAmount,
298298
borderRadius,
299299
padding,
300300
cropRegion,
@@ -347,7 +347,7 @@ export default function VideoEditor() {
347347
wallpaper,
348348
shadowIntensity,
349349
showBlur,
350-
motionBlurEnabled,
350+
motionBlurAmount,
351351
borderRadius,
352352
padding,
353353
cropRegion,
@@ -930,7 +930,7 @@ export default function VideoEditor() {
930930
showShadow: shadowIntensity > 0,
931931
shadowIntensity,
932932
showBlur,
933-
motionBlurEnabled,
933+
motionBlurAmount,
934934
borderRadius,
935935
padding,
936936
videoPadding: padding,
@@ -1057,7 +1057,7 @@ export default function VideoEditor() {
10571057
showShadow: shadowIntensity > 0,
10581058
shadowIntensity,
10591059
showBlur,
1060-
motionBlurEnabled,
1060+
motionBlurAmount,
10611061
borderRadius,
10621062
padding,
10631063
cropRegion,
@@ -1118,7 +1118,7 @@ export default function VideoEditor() {
11181118
speedRegions,
11191119
shadowIntensity,
11201120
showBlur,
1121-
motionBlurEnabled,
1121+
motionBlurAmount,
11221122
borderRadius,
11231123
padding,
11241124
cropRegion,
@@ -1260,7 +1260,7 @@ export default function VideoEditor() {
12601260
showShadow={shadowIntensity > 0}
12611261
shadowIntensity={shadowIntensity}
12621262
showBlur={showBlur}
1263-
motionBlurEnabled={motionBlurEnabled}
1263+
motionBlurAmount={motionBlurAmount}
12641264
borderRadius={borderRadius}
12651265
padding={padding}
12661266
cropRegion={cropRegion}
@@ -1359,8 +1359,8 @@ export default function VideoEditor() {
13591359
onShadowCommit={commitState}
13601360
showBlur={showBlur}
13611361
onBlurChange={(v) => pushState({ showBlur: v })}
1362-
motionBlurEnabled={motionBlurEnabled}
1363-
onMotionBlurChange={(v) => pushState({ motionBlurEnabled: v })}
1362+
motionBlurAmount={motionBlurAmount}
1363+
onMotionBlurChange={(v) => pushState({ motionBlurAmount: v })}
13641364
borderRadius={borderRadius}
13651365
onBorderRadiusChange={(v) => updateState({ borderRadius: v })}
13661366
onBorderRadiusCommit={commitState}

src/components/video-editor/VideoPlayback.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ interface VideoPlaybackProps {
5555
showShadow?: boolean;
5656
shadowIntensity?: number;
5757
showBlur?: boolean;
58-
motionBlurEnabled?: boolean;
58+
motionBlurAmount?: number;
5959
borderRadius?: number;
6060
padding?: number;
6161
cropRegion?: import("./types").CropRegion;
@@ -98,7 +98,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
9898
showShadow,
9999
shadowIntensity = 0,
100100
showBlur,
101-
motionBlurEnabled = false,
101+
motionBlurAmount = 0,
102102
borderRadius = 0,
103103
padding = 50,
104104
cropRegion,
@@ -148,7 +148,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
148148
const layoutVideoContentRef = useRef<(() => void) | null>(null);
149149
const trimRegionsRef = useRef<TrimRegion[]>([]);
150150
const speedRegionsRef = useRef<SpeedRegion[]>([]);
151-
const motionBlurEnabledRef = useRef(motionBlurEnabled);
151+
const motionBlurAmountRef = useRef(motionBlurAmount);
152152
const onTimeUpdateRef = useRef(onTimeUpdate);
153153
const onPlayStateChangeRef = useRef(onPlayStateChange);
154154
const videoReadyRafRef = useRef<number | null>(null);
@@ -378,8 +378,8 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
378378
}, [speedRegions]);
379379

380380
useEffect(() => {
381-
motionBlurEnabledRef.current = motionBlurEnabled;
382-
}, [motionBlurEnabled]);
381+
motionBlurAmountRef.current = motionBlurAmount;
382+
}, [motionBlurAmount]);
383383

384384
useEffect(() => {
385385
onTimeUpdateRef.current = onTimeUpdate;
@@ -446,7 +446,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
446446
focusY: DEFAULT_FOCUS.cy,
447447
motionIntensity: 0,
448448
isPlaying: false,
449-
motionBlurEnabled: motionBlurEnabledRef.current,
449+
motionBlurAmount: motionBlurAmountRef.current,
450450
});
451451

452452
requestAnimationFrame(() => {
@@ -692,7 +692,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
692692
focusY: state.focusY,
693693
motionIntensity,
694694
isPlaying: isPlayingRef.current,
695-
motionBlurEnabled: motionBlurEnabledRef.current,
695+
motionBlurAmount: motionBlurAmountRef.current,
696696
});
697697
};
698698

src/components/video-editor/projectPersistence.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export interface ProjectEditorState {
2828
wallpaper: string;
2929
shadowIntensity: number;
3030
showBlur: boolean;
31-
motionBlurEnabled: boolean;
31+
motionBlurAmount: number;
3232
borderRadius: number;
3333
padding: number;
3434
cropRegion: CropRegion;
@@ -302,8 +302,13 @@ export function normalizeProjectEditor(editor: Partial<ProjectEditorState>): Pro
302302
wallpaper: typeof editor.wallpaper === "string" ? editor.wallpaper : WALLPAPER_PATHS[0],
303303
shadowIntensity: typeof editor.shadowIntensity === "number" ? editor.shadowIntensity : 0,
304304
showBlur: typeof editor.showBlur === "boolean" ? editor.showBlur : false,
305-
motionBlurEnabled:
306-
typeof editor.motionBlurEnabled === "boolean" ? editor.motionBlurEnabled : false,
305+
motionBlurAmount: isFiniteNumber(editor.motionBlurAmount)
306+
? clamp(editor.motionBlurAmount, 0, 1)
307+
: typeof (editor as { motionBlurEnabled?: unknown }).motionBlurEnabled === "boolean"
308+
? (editor as { motionBlurEnabled?: boolean }).motionBlurEnabled
309+
? 0.35
310+
: 0
311+
: 0,
307312
borderRadius: typeof editor.borderRadius === "number" ? editor.borderRadius : 0,
308313
padding: isFiniteNumber(editor.padding) ? clamp(editor.padding, 0, 100) : 50,
309314
cropRegion: {

src/components/video-editor/videoPlayback/zoomTransform.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface TransformParams {
1010
focusY: number;
1111
motionIntensity: number;
1212
isPlaying: boolean;
13-
motionBlurEnabled?: boolean;
13+
motionBlurAmount?: number;
1414
}
1515

1616
export function applyZoomTransform({
@@ -23,7 +23,7 @@ export function applyZoomTransform({
2323
focusY,
2424
motionIntensity,
2525
isPlaying,
26-
motionBlurEnabled = false,
26+
motionBlurAmount = 0,
2727
}: TransformParams) {
2828
if (
2929
stageSize.width <= 0 ||
@@ -54,8 +54,8 @@ export function applyZoomTransform({
5454
cameraContainer.position.set(cameraX, cameraY);
5555

5656
if (blurFilter) {
57-
const shouldBlur = motionBlurEnabled && isPlaying && motionIntensity > 0.0005;
58-
const motionBlur = shouldBlur ? Math.min(6, motionIntensity * 120) : 0;
57+
const shouldBlur = motionBlurAmount > 0 && isPlaying && motionIntensity > 0.0005;
58+
const motionBlur = shouldBlur ? Math.min(6, motionIntensity * 120 * motionBlurAmount) : 0;
5959
blurFilter.blur = motionBlur;
6060
}
6161
}

src/hooks/useEditorHistory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface EditorState {
2020
wallpaper: string;
2121
shadowIntensity: number;
2222
showBlur: boolean;
23-
motionBlurEnabled: boolean;
23+
motionBlurAmount: number;
2424
borderRadius: number;
2525
padding: number;
2626
aspectRatio: AspectRatio;
@@ -35,7 +35,7 @@ export const INITIAL_EDITOR_STATE: EditorState = {
3535
wallpaper: "/wallpapers/wallpaper1.jpg",
3636
shadowIntensity: 0,
3737
showBlur: false,
38-
motionBlurEnabled: false,
38+
motionBlurAmount: 0,
3939
borderRadius: 0,
4040
padding: 50,
4141
aspectRatio: "16:9",

src/lib/exporter/frameRenderer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ interface FrameRenderConfig {
3434
showShadow: boolean;
3535
shadowIntensity: number;
3636
showBlur: boolean;
37-
motionBlurEnabled?: boolean;
37+
motionBlurAmount?: number;
3838
borderRadius?: number;
3939
padding?: number;
4040
cropRegion: CropRegion;
@@ -345,7 +345,7 @@ export class FrameRenderer {
345345
focusY: this.animationState.focusY,
346346
motionIntensity: maxMotionIntensity,
347347
isPlaying: true,
348-
motionBlurEnabled: this.config.motionBlurEnabled ?? false,
348+
motionBlurAmount: this.config.motionBlurAmount ?? 0,
349349
});
350350

351351
// Render the PixiJS stage to its canvas (video only, transparent background)

src/lib/exporter/gifExporter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ interface GifExporterConfig {
3232
showShadow: boolean;
3333
shadowIntensity: number;
3434
showBlur: boolean;
35-
motionBlurEnabled?: boolean;
35+
motionBlurAmount?: number;
3636
borderRadius?: number;
3737
padding?: number;
3838
videoPadding?: number;
@@ -106,7 +106,7 @@ export class GifExporter {
106106
showShadow: this.config.showShadow,
107107
shadowIntensity: this.config.shadowIntensity,
108108
showBlur: this.config.showBlur,
109-
motionBlurEnabled: this.config.motionBlurEnabled,
109+
motionBlurAmount: this.config.motionBlurAmount,
110110
borderRadius: this.config.borderRadius,
111111
padding: this.config.padding,
112112
cropRegion: this.config.cropRegion,

src/lib/exporter/videoExporter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ interface VideoExporterConfig extends ExportConfig {
2020
showShadow: boolean;
2121
shadowIntensity: number;
2222
showBlur: boolean;
23-
motionBlurEnabled?: boolean;
23+
motionBlurAmount?: number;
2424
borderRadius?: number;
2525
padding?: number;
2626
videoPadding?: number;
@@ -70,7 +70,7 @@ export class VideoExporter {
7070
showShadow: this.config.showShadow,
7171
shadowIntensity: this.config.shadowIntensity,
7272
showBlur: this.config.showBlur,
73-
motionBlurEnabled: this.config.motionBlurEnabled,
73+
motionBlurAmount: this.config.motionBlurAmount,
7474
borderRadius: this.config.borderRadius,
7575
padding: this.config.padding,
7676
cropRegion: this.config.cropRegion,

0 commit comments

Comments
 (0)