268 lines
11 KiB
JavaScript
268 lines
11 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Canvas = void 0;
|
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
const react_1 = require("react");
|
|
const remotion_1 = require("remotion");
|
|
const colors_1 = require("../helpers/colors");
|
|
const get_asset_metadata_1 = require("../helpers/get-asset-metadata");
|
|
const get_effective_translation_1 = require("../helpers/get-effective-translation");
|
|
const smooth_zoom_1 = require("../helpers/smooth-zoom");
|
|
const use_keybinding_1 = require("../helpers/use-keybinding");
|
|
const canvas_ref_1 = require("../state/canvas-ref");
|
|
const editor_guides_1 = require("../state/editor-guides");
|
|
const editor_zoom_gestures_1 = require("../state/editor-zoom-gestures");
|
|
const EditorGuides_1 = __importDefault(require("./EditorGuides"));
|
|
const EditorRuler_1 = require("./EditorRuler");
|
|
const use_is_ruler_visible_1 = require("./EditorRuler/use-is-ruler-visible");
|
|
const Preview_1 = require("./Preview");
|
|
const ResetZoomButton_1 = require("./ResetZoomButton");
|
|
const layout_1 = require("./layout");
|
|
const container = {
|
|
flex: 1,
|
|
display: 'flex',
|
|
overflow: 'hidden',
|
|
position: 'relative',
|
|
backgroundColor: colors_1.BACKGROUND,
|
|
};
|
|
const resetZoom = {
|
|
position: 'absolute',
|
|
top: layout_1.SPACING_UNIT * 2,
|
|
right: layout_1.SPACING_UNIT * 2,
|
|
};
|
|
const ZOOM_PX_FACTOR = 0.003;
|
|
const Canvas = ({ canvasContent, size }) => {
|
|
const { setSize, size: previewSize } = (0, react_1.useContext)(remotion_1.Internals.PreviewSizeContext);
|
|
const { editorZoomGestures } = (0, react_1.useContext)(editor_zoom_gestures_1.EditorZoomGesturesContext);
|
|
const keybindings = (0, use_keybinding_1.useKeybinding)();
|
|
const config = remotion_1.Internals.useUnsafeVideoConfig();
|
|
const areRulersVisible = (0, use_is_ruler_visible_1.useIsRulerVisible)();
|
|
const { editorShowGuides } = (0, react_1.useContext)(editor_guides_1.EditorShowGuidesContext);
|
|
const [assetResolution, setAssetResolution] = (0, react_1.useState)(null);
|
|
const contentDimensions = (0, react_1.useMemo)(() => {
|
|
if ((canvasContent.type === 'asset' ||
|
|
canvasContent.type === 'output' ||
|
|
canvasContent.type === 'output-blob') &&
|
|
assetResolution &&
|
|
assetResolution.type === 'found') {
|
|
return assetResolution.dimensions;
|
|
}
|
|
if (config) {
|
|
return { width: config.width, height: config.height };
|
|
}
|
|
return null;
|
|
}, [assetResolution, config, canvasContent]);
|
|
const isFit = previewSize.size === 'auto';
|
|
const onWheel = (0, react_1.useCallback)((e) => {
|
|
if (!editorZoomGestures) {
|
|
return;
|
|
}
|
|
if (!size) {
|
|
return;
|
|
}
|
|
if (!contentDimensions || contentDimensions === 'none') {
|
|
return;
|
|
}
|
|
const wantsToZoom = e.ctrlKey || e.metaKey;
|
|
if (!wantsToZoom && isFit) {
|
|
return;
|
|
}
|
|
e.preventDefault();
|
|
setSize((prevSize) => {
|
|
const scale = remotion_1.Internals.calculateScale({
|
|
canvasSize: size,
|
|
compositionHeight: contentDimensions.height,
|
|
compositionWidth: contentDimensions.width,
|
|
previewSize: prevSize.size,
|
|
});
|
|
// Zoom in/out
|
|
if (wantsToZoom) {
|
|
const oldSize = prevSize.size === 'auto' ? scale : prevSize.size;
|
|
const smoothened = (0, smooth_zoom_1.smoothenZoom)(oldSize);
|
|
const added = smoothened + e.deltaY * ZOOM_PX_FACTOR;
|
|
const unsmoothened = (0, smooth_zoom_1.unsmoothenZoom)(added);
|
|
const { centerX, centerY } = (0, get_effective_translation_1.getCenterPointWhileScrolling)({
|
|
size,
|
|
clientX: e.clientX,
|
|
clientY: e.clientY,
|
|
compositionWidth: contentDimensions.width,
|
|
compositionHeight: contentDimensions.height,
|
|
scale,
|
|
translation: prevSize.translation,
|
|
});
|
|
const zoomDifference = unsmoothened - oldSize;
|
|
const uvCoordinatesX = centerX / contentDimensions.width;
|
|
const uvCoordinatesY = centerY / contentDimensions.height;
|
|
const correctionLeft = -uvCoordinatesX * (zoomDifference * contentDimensions.width) +
|
|
(1 - uvCoordinatesX) * zoomDifference * contentDimensions.width;
|
|
const correctionTop = -uvCoordinatesY * (zoomDifference * contentDimensions.height) +
|
|
(1 - uvCoordinatesY) * zoomDifference * contentDimensions.height;
|
|
return {
|
|
translation: (0, get_effective_translation_1.getEffectiveTranslation)({
|
|
translation: {
|
|
x: prevSize.translation.x - correctionLeft / 2,
|
|
y: prevSize.translation.y - correctionTop / 2,
|
|
},
|
|
canvasSize: size,
|
|
compositionHeight: contentDimensions.height,
|
|
compositionWidth: contentDimensions.width,
|
|
scale,
|
|
}),
|
|
size: unsmoothened,
|
|
};
|
|
}
|
|
const effectiveTranslation = (0, get_effective_translation_1.getEffectiveTranslation)({
|
|
translation: prevSize.translation,
|
|
canvasSize: size,
|
|
compositionHeight: contentDimensions.height,
|
|
compositionWidth: contentDimensions.width,
|
|
scale,
|
|
});
|
|
// Pan
|
|
return {
|
|
...prevSize,
|
|
translation: (0, get_effective_translation_1.getEffectiveTranslation)({
|
|
translation: {
|
|
x: effectiveTranslation.x + e.deltaX,
|
|
y: effectiveTranslation.y + e.deltaY,
|
|
},
|
|
canvasSize: size,
|
|
compositionHeight: contentDimensions.height,
|
|
compositionWidth: contentDimensions.width,
|
|
scale,
|
|
}),
|
|
};
|
|
});
|
|
}, [editorZoomGestures, contentDimensions, isFit, setSize, size]);
|
|
(0, react_1.useEffect)(() => {
|
|
const { current } = canvas_ref_1.canvasRef;
|
|
if (!current) {
|
|
return;
|
|
}
|
|
current.addEventListener('wheel', onWheel, { passive: false });
|
|
return () =>
|
|
// @ts-expect-error
|
|
current.removeEventListener('wheel', onWheel, {
|
|
passive: false,
|
|
});
|
|
}, [onWheel]);
|
|
const onReset = (0, react_1.useCallback)(() => {
|
|
setSize(() => {
|
|
return {
|
|
translation: {
|
|
x: 0,
|
|
y: 0,
|
|
},
|
|
size: 'auto',
|
|
};
|
|
});
|
|
}, [setSize]);
|
|
const onZoomIn = (0, react_1.useCallback)(() => {
|
|
if (!contentDimensions || contentDimensions === 'none') {
|
|
return;
|
|
}
|
|
if (!size) {
|
|
return;
|
|
}
|
|
setSize((prevSize) => {
|
|
const scale = remotion_1.Internals.calculateScale({
|
|
canvasSize: size,
|
|
compositionHeight: contentDimensions.height,
|
|
compositionWidth: contentDimensions.width,
|
|
previewSize: prevSize.size,
|
|
});
|
|
return {
|
|
translation: {
|
|
x: 0,
|
|
y: 0,
|
|
},
|
|
size: Math.min(smooth_zoom_1.MAX_ZOOM, scale * 2),
|
|
};
|
|
});
|
|
}, [contentDimensions, setSize, size]);
|
|
const onZoomOut = (0, react_1.useCallback)(() => {
|
|
if (!contentDimensions || contentDimensions === 'none') {
|
|
return;
|
|
}
|
|
if (!size) {
|
|
return;
|
|
}
|
|
setSize((prevSize) => {
|
|
const scale = remotion_1.Internals.calculateScale({
|
|
canvasSize: size,
|
|
compositionHeight: contentDimensions.height,
|
|
compositionWidth: contentDimensions.width,
|
|
previewSize: prevSize.size,
|
|
});
|
|
return {
|
|
translation: {
|
|
x: 0,
|
|
y: 0,
|
|
},
|
|
size: Math.max(smooth_zoom_1.MIN_ZOOM, scale / 2),
|
|
};
|
|
});
|
|
}, [contentDimensions, setSize, size]);
|
|
(0, react_1.useEffect)(() => {
|
|
const resetBinding = keybindings.registerKeybinding({
|
|
event: 'keydown',
|
|
key: '0',
|
|
commandCtrlKey: false,
|
|
callback: onReset,
|
|
preventDefault: true,
|
|
triggerIfInputFieldFocused: false,
|
|
keepRegisteredWhenNotHighestContext: false,
|
|
});
|
|
const zoomIn = keybindings.registerKeybinding({
|
|
event: 'keydown',
|
|
key: '+',
|
|
commandCtrlKey: false,
|
|
callback: onZoomIn,
|
|
preventDefault: true,
|
|
triggerIfInputFieldFocused: false,
|
|
keepRegisteredWhenNotHighestContext: false,
|
|
});
|
|
const zoomOut = keybindings.registerKeybinding({
|
|
event: 'keydown',
|
|
key: '-',
|
|
commandCtrlKey: false,
|
|
callback: onZoomOut,
|
|
preventDefault: true,
|
|
triggerIfInputFieldFocused: false,
|
|
keepRegisteredWhenNotHighestContext: false,
|
|
});
|
|
return () => {
|
|
resetBinding.unregister();
|
|
zoomIn.unregister();
|
|
zoomOut.unregister();
|
|
};
|
|
}, [keybindings, onReset, onZoomIn, onZoomOut]);
|
|
const fetchMetadata = (0, react_1.useCallback)(async () => {
|
|
setAssetResolution(null);
|
|
if (canvasContent.type === 'composition') {
|
|
return;
|
|
}
|
|
const metadata = await (0, get_asset_metadata_1.getAssetMetadata)(canvasContent, canvasContent.type === 'asset');
|
|
setAssetResolution(metadata);
|
|
}, [canvasContent]);
|
|
(0, react_1.useEffect)(() => {
|
|
if (canvasContent.type !== 'asset') {
|
|
return;
|
|
}
|
|
const file = (0, remotion_1.watchStaticFile)(canvasContent.asset, () => {
|
|
fetchMetadata();
|
|
});
|
|
return () => {
|
|
file.cancel();
|
|
};
|
|
}, [canvasContent, fetchMetadata]);
|
|
(0, react_1.useEffect)(() => {
|
|
fetchMetadata();
|
|
}, [fetchMetadata]);
|
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { ref: canvas_ref_1.canvasRef, style: container, children: [size ? ((0, jsx_runtime_1.jsx)(Preview_1.VideoPreview, { canvasContent: canvasContent, contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution })) : null, isFit ? null : ((0, jsx_runtime_1.jsx)("div", { style: resetZoom, className: "css-reset", children: (0, jsx_runtime_1.jsx)(ResetZoomButton_1.ResetZoomButton, { onClick: onReset }) })), editorShowGuides && canvasContent.type === 'composition' && ((0, jsx_runtime_1.jsx)(EditorGuides_1.default, { canvasSize: size, contentDimensions: contentDimensions, assetMetadata: assetResolution }))] }), areRulersVisible && ((0, jsx_runtime_1.jsx)(EditorRuler_1.EditorRulers, { contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, containerRef: canvas_ref_1.canvasRef }))] }));
|
|
};
|
|
exports.Canvas = Canvas;
|