mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-24 14:55:37 +00:00
Keep cursor size and sharpness consistent in previews
This commit is contained in:
@@ -1084,6 +1084,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
|
||||
|
||||
motionBlurFilter.resolution = filterResolution;
|
||||
zoomBlurFilter.resolution = filterResolution;
|
||||
cursorOverlayRef.current?.setFilterResolution(filterResolution);
|
||||
videoEffectsContainer.filterArea = new Rectangle(0, 0, stageWidth, stageHeight);
|
||||
}, []);
|
||||
|
||||
@@ -2173,6 +2174,9 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
|
||||
sway: cursorSwayRef.current,
|
||||
});
|
||||
cursorOverlayRef.current = cursorOverlay;
|
||||
cursorOverlay.setFilterResolution(
|
||||
app.renderer.resolution || window.devicePixelRatio || 1,
|
||||
);
|
||||
cursorContainer.addChild(cursorOverlay.container);
|
||||
} else {
|
||||
cursorOverlayRef.current = null;
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
DEFAULT_CURSOR_STYLE,
|
||||
normalizeCursorClickEffectColor,
|
||||
} from "../types";
|
||||
import { getCursorViewportScale } from "./cursorScale";
|
||||
import { computeCursorSwayRotation } from "./cursorSway";
|
||||
import { type CursorViewportRect, projectCursorPositionToViewport } from "./cursorViewport";
|
||||
import {
|
||||
@@ -110,8 +111,7 @@ export interface CursorRenderConfig {
|
||||
style: CursorStyle;
|
||||
}
|
||||
|
||||
const REFERENCE_WIDTH = 1920;
|
||||
const MIN_CURSOR_VIEWPORT_SCALE = 0.55;
|
||||
const MIN_CURSOR_VIEWPORT_SCALE = 0;
|
||||
const CURSOR_MOTION_BLUR_BASE_MULTIPLIER = 0.08;
|
||||
const CURSOR_TIME_DISCONTINUITY_MS = 100;
|
||||
const CURSOR_SWAY_SMOOTHING_MULTIPLIER = 0.7;
|
||||
@@ -807,13 +807,6 @@ function findLatestStableCursorType(samples: CursorTelemetryPoint[], timeMs: num
|
||||
return findLatestSample(samples, timeMs)?.cursorType ?? "arrow";
|
||||
}
|
||||
|
||||
function getCursorViewportScale(
|
||||
viewport: CursorViewportRect,
|
||||
minViewportScale = MIN_CURSOR_VIEWPORT_SCALE,
|
||||
) {
|
||||
return Math.max(minViewportScale, viewport.width / REFERENCE_WIDTH);
|
||||
}
|
||||
|
||||
function getCursorSwaySpringConfig(smoothingFactor: number, springTuning: CursorSpringTuning) {
|
||||
const baseConfig = getCursorSpringConfig(
|
||||
Math.min(
|
||||
@@ -1231,6 +1224,10 @@ export class PixiCursorOverlay {
|
||||
}
|
||||
}
|
||||
|
||||
setFilterResolution(resolution: number) {
|
||||
this.cursorMotionBlurFilter.resolution = Math.max(1, resolution);
|
||||
}
|
||||
|
||||
setClickBounce(clickBounce: number) {
|
||||
this.config.clickBounce = Math.max(0, clickBounce);
|
||||
}
|
||||
@@ -1346,7 +1343,7 @@ export class PixiCursorOverlay {
|
||||
|
||||
const h =
|
||||
this.config.dotRadius *
|
||||
getCursorViewportScale(viewport, this.config.minViewportScale);
|
||||
getCursorViewportScale(viewport.width, this.config.minViewportScale);
|
||||
const { cursorType, clickSample, clickBounceProgress, clickProgress } =
|
||||
getCursorVisualState(
|
||||
samples,
|
||||
@@ -1642,7 +1639,7 @@ export function drawCursorOnCanvas(
|
||||
|
||||
const px = viewport.x + smoothedState.x * viewport.width;
|
||||
const py = viewport.y + smoothedState.y * viewport.height;
|
||||
const h = config.dotRadius * getCursorViewportScale(viewport, config.minViewportScale);
|
||||
const h = config.dotRadius * getCursorViewportScale(viewport.width, config.minViewportScale);
|
||||
const { cursorType, clickSample, clickBounceProgress, clickProgress } = getCursorVisualState(
|
||||
samples,
|
||||
timeMs,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { getCursorViewportScale } from "./cursorScale";
|
||||
|
||||
describe("cursor preview/export scale", () => {
|
||||
it("preserves the same cursor-to-video ratio at preview and export sizes", () => {
|
||||
const baseCursorHeight = 28 * 2.5;
|
||||
const previewWidth = 720;
|
||||
const exportWidth = 2940;
|
||||
const previewCursorHeight = baseCursorHeight * getCursorViewportScale(previewWidth);
|
||||
const exportCursorHeight = baseCursorHeight * getCursorViewportScale(exportWidth);
|
||||
|
||||
expect(previewCursorHeight / previewWidth).toBeCloseTo(exportCursorHeight / exportWidth, 8);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
export const CURSOR_REFERENCE_VIEWPORT_WIDTH = 1920;
|
||||
|
||||
export function getCursorViewportScale(viewportWidth: number, minimumScale = 0): number {
|
||||
return Math.max(minimumScale, Math.max(0, viewportWidth) / CURSOR_REFERENCE_VIEWPORT_WIDTH);
|
||||
}
|
||||
@@ -236,12 +236,12 @@ describe("ModernVideoExporter native static-layout eligibility", () => {
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("scales native static-layout cursor size with a minimum visible floor", () => {
|
||||
it("preserves the cursor-to-video ratio at every native static-layout size", () => {
|
||||
const exporter = createExporter({ cursorSize: 3, cursorStyle: "tahoe" });
|
||||
|
||||
expect(exporter.getNativeStaticLayoutCursorSize(1920)).toBeCloseTo(84, 6);
|
||||
expect(exporter.getNativeStaticLayoutCursorSize(960)).toBeCloseTo(46.2, 6);
|
||||
expect(exporter.getNativeStaticLayoutCursorSize(480)).toBeCloseTo(46.2, 6);
|
||||
expect(exporter.getNativeStaticLayoutCursorSize(960)).toBeCloseTo(42, 6);
|
||||
expect(exporter.getNativeStaticLayoutCursorSize(480)).toBeCloseTo(21, 6);
|
||||
});
|
||||
|
||||
it("skips native static-layout when cursor click effects are enabled", () => {
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
SNAP_TO_EDGES_RATIO_AUTO,
|
||||
} from "@/components/video-editor/videoPlayback/cursorFollowCamera";
|
||||
import { buildNativeCursorAtlas } from "@/components/video-editor/videoPlayback/cursorRenderer";
|
||||
import { getCursorViewportScale } from "@/components/video-editor/videoPlayback/cursorScale";
|
||||
import {
|
||||
computePaddedLayout,
|
||||
scalePreviewBorderRadius,
|
||||
@@ -2089,7 +2090,7 @@ export class ModernVideoExporter {
|
||||
|
||||
private getNativeStaticLayoutCursorSize(contentWidth: number) {
|
||||
const cursorStyle = this.config.cursorStyle ?? "tahoe";
|
||||
const viewportScale = Math.max(0.55, contentWidth / 1920);
|
||||
const viewportScale = getCursorViewportScale(contentWidth);
|
||||
return (
|
||||
28 *
|
||||
(this.config.cursorSize ?? 3) *
|
||||
|
||||
Reference in New Issue
Block a user