十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Remotion 画布裁剪(Cropping)完全指南:通过 cropLeft / cropRight / cropTop / cropBottom 精确控制画面内容

Remotion 画布裁剪(Cropping)完全指南:通过 cropLeft / cropRight / cropTop / cropBottom 精确控制画面内容 Remotion 画布裁剪Cropping完全指南通过 cropLeft / cropRight / cropTop / cropBottom 精确控制画面内容【免费下载链接】remotion Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion在 Remotion 中视频合成的每个帧本质上都是「React 组件渲染出的画面」。当需要隐藏画面边缘、裁掉多余内容、或在画布编辑器Canvas中交互式地调整一张图片、一段视频或一个Sequence的可见范围时最推荐的方式不是手写clipPath而是使用统一的裁剪属性组cropLeft、cropRight、cropTop、cropBottom。本文围绕 remotion-markup/cropping 的说明展开结合packages/core的裁剪实现源码与测试用例讲解这些裁剪属性的取值语义、适用组件、代码写法和编辑器中的交互行为读完即可在自己的视频合成里正确、可动画、可编辑地使用裁剪。裁剪的两种心智模型裁掉内容而非缩放画面在动手写代码前先明确裁剪语义crop*裁剪属性描述的是「把元素某一侧的内容裁掉多少比例」这与clipPath/object-fit的做法不同——裁剪不会重新排版、不会拉伸剩余内容剩余画面在原布局中的位置保持不变超出裁剪边缘的部分被直接隐藏。四个属性分别对应元素的四条边缘cropLeft从左边缘向内裁、cropRight从右边缘向内裁、cropTop从顶部向下裁、cropBottom从底部向上裁。取值规则0 到 1 之间的比例所有crop*属性的取值都是 0 到 1 之间的比例不是像素也不是百分比数值0表示该边缘不做任何裁剪1表示该边缘完全裁剪整条边的内容全部隐藏中间值如0.25表示裁掉该方向 25% 的内容。例如一张1920×1080的图片设置cropLeft{0.25}实际效果就是图片左侧约 480px 被隐藏。具体的边界钳制clamp、异常校验以及「裁剪比例如何换算成 CSS 裁剪路径」都在源码中有明确规定下文展开。支持裁剪属性的组件crop*属性并非所有组件通用它是一组在画布合成体系下刻意设计的 props。目前支持裁剪的组件如下组件来源包说明Sequenceremotion仅在layoutabsolute-fill时支持裁剪CanvasImageremotion画布专用图片组件Imgremotion普通图片组件AnimatedImageremotion动图/图片动画组件HtmlInCanvasremotion画布内渲染 HTML 的组件Solidremotion纯色块Videoremotion/media视频组件Gifremotion/gifGIF 组件RemotionRiveCanvasremotion/riveRive 动画画布除Sequence与上述 Remotion 核心组件外视频、GIF、Rive 等媒体组件也在各自的包中透传了裁剪属性说明裁剪语义被统一抽象为「组件接收crop*后按同一套规则裁剪自身内容」。Sequence的特殊限制对Sequence使用crop*时要求其layout必须是absolute-fill。在 Sequence.tsx 中可以看到组件会先判断是否存在裁剪属性再检查布局const cropProps {cropLeft, cropRight, cropTop, cropBottom}; const hasCropProp Object.values(cropProps).some( (value) value ! undefined, ); if (layout none hasCropProp) { throw new TypeError( The cropLeft, cropRight, cropTop and cropBottom props of Sequence / are only supported with layoutabsolute-fill., ); }也就是说一旦给Sequence传入任意裁剪属性而布局又是layoutnone会在运行期直接抛出TypeError。如果只想裁剪「某一段时长内的场景内容」最自然的做法正是让该Sequence以absolute-fill铺满画面再裁剪。裁剪的校验与数值解析源码里的完整规则Remotion 将裁剪逻辑集中实现在 sequence-crop.ts 中包含三个值得了解的机制校验validate、解析resolve、生成裁剪路径clip path。这些机制对所有支持crop*的组件通用。校验规则validateSequenceCrop对四个属性逐一校验规则如下sequence-crop.ts值为undefined时跳过校验未设置的边缘按不裁剪处理值必须是有限数字finite number否则抛TypeError值大于100时抛出RangeError错误信息里特别提示裁剪取值范围是 0 到 1而不是 0 到 100——这是新手最容易踩的坑误以为可以传入10代表 10%if (value 100) { throw new RangeError( The ${name} prop of ${componentName} must be between 0 and 1, but got ${value}. The crop range is 0 to 1, not 0 to 100., ); }数值钳制与重叠处理resolveSequenceCrop是数值解析的核心sequence-crop.ts。每个轴水平轴的cropLeft/cropRight垂直轴的cropTop/cropBottom分别处理单个值会先被clampCrop夹在[0, 1]之间Math.min(1, Math.max(0, value ?? 0))越界值不会崩溃而是自动收敛如果同一轴上的两个值相加超过 1例如cropLeft{0.6}且cropRight{0.6}意味着裁剪范围互相重叠、没有任何可见内容Remotion 不会报错而是把两个值都解析为0.5即左右各保留一半重叠区间的行为被修正为「从两端各裁一半、正中间剩不下」的稳定折中if (resolvedStart resolvedEnd 1) { return [0.5, 0.5]; }裁剪如何变成 CSSinset 裁剪路径解析后的裁剪最终被渲染成clip-path: inset(...)规则见getSequenceCropClipPathsequence-crop.ts四个方向都没有裁剪时返回null不产生任何clipPath避免多余开销否则生成形如inset(top% right% bottom% left%)的路径四个百分比依次为顶、右、底、左即inset(${top * 100}% ${right * 100}% ${bottom * 100}% ${left * 100}%)若元素原本带borderRadius含borderTopLeftRadius等四个独立角裁剪路径会追加round radius以保持圆角数值半径会序列化为px。使用裁剪的实际注入逻辑在 use-crop-style.ts 的useCropStyle中先校验、再解析若裁剪路径不为null则把clipPath合并进元素已有的style最终让单个元素同时保留原样式与裁剪结果。基础用法与关键帧动画示例把裁剪值看作普通的可插值数字就能非常自然地结合interpolate()做出动态的「开合裁剪」。以下是 cropping.md 中的标准示例一张照片在 0 到 30 帧之间从左边缘向内裁到 25%同时固定裁掉底部 10%CanvasImage src{staticFile(photo.png)} cropLeft{interpolate(frame, [0, 30], [0, 0.25], { extrapolateLeft: clamp, extrapolateRight: clamp, })} cropBottom{0.1} /需要注意两点interpolate(frame, [0, 30], [0, 0.25], ...)把帧号映射到裁剪比例配合extrapolateLeft/extrapolateRight: clamp确保动画开始前与结束后都钳制在目标裁剪值上不会越界固定值如这里的cropBottom{0.1}与动态值可以混用四个方向彼此独立。对Sequence的裁剪方式完全一致只是需要确保使用layoutabsolute-fillSequence layoutabsolute-fill cropTop{0.2} cropBottom{0.2} Video src{staticFile(clip.mp4)} / /Sequence编辑器内可交互、可打关键帧裁剪属性在设计上是可交互、可关键帧的。在 interactivity-schema.ts 中四个裁剪字段被定义为统一的数字型 schemaexport const cropSchema { cropLeft: { type: number, default: 0, description: Crop left, min: 0, max: 1, step: 0.01, hiddenFromList: false, keyframable: true, }, // cropRight / cropTop / cropBottom 结构一致 } as const satisfies InteractivitySchema;每个字段都标注了min: 0、max: 1、step: 0.01并且keyframable: true。这意味着在画布Canvas中这些裁剪属性会显示为可拖动的控制点拖动组件、裁剪边框实时更新属性面板中以 0.01 为步进调节并可沿时间轴打关键帧。这正是文档「优先使用crop*属性」的原因相比手写clipPath这套属性让裁剪在 Studio 里可直接编辑、可随帧号驱动。这正是本 skill 文档强调的要点——结合 Interactivity Best Practices对应仓库路径 remotion-interactivity skill一起使用让裁剪保持可编辑editable与可关键帧keyframable从而避免产物退化为无法在编辑器中还原的写死样式。为什么不要手写 clipPath 与 crop 混用文档明确给出一条约束不要在同一元素上把clipPath与crop*属性混用。从实现上看useCropStyle通过把解析出的clipPath合并进 style 来生效如果用户同时自己传入style.clipPath二者会互相覆盖或叠加出意料之外的效果——自定义的clipPath会被裁剪路径整体替换或与 inset 规则共同作用于元素结果都难以预测。同时手写clipPath无法被画布编辑器识别为裁剪操作拖动、关键帧、时间线还原都会失效。因此只要涉及可编辑、可动画的裁剪需求都应走crop*属性。从测试用例验证裁剪行为packages/core内置的测试完整验证了上述行为可作为理解裁剪语义的权威参考sequence-crop.test.tsx 验证Sequence cropLeft{0.1} cropRight{0.2} cropTop{0.3} cropBottom{0.4}最终生成的clip-path恰为inset(30% 20% 40% 10%)与resolveSequenceCrop的换算完全一致同一测试文件还验证了数字圆角borderRadius: 24→round 24px、字符串圆角20% / 10%以及四个独立圆角均能在裁剪路径中被保留其他覆盖裁剪的测试还包括use-crop-style、Img、HtmlInCanvas、Solid与CanvasImage等组件的裁剪渲染均位于 packages/core/src/test 目录下。这些测试说明裁剪不是某个组件各自实现的「局部 hack」而是整套组件体系共享的、由 sequence-crop.ts 统一负责的通用能力。裁剪使用要点速览取值必须为0 到 1的比例0不裁1全裁传大于100的值会直接抛错提醒取值范围四个方向相互独立可以只传一个或任意组合undefined视为0同一轴的裁剪相加超过1时会被自动解析为各0.5不会崩溃动态裁剪用interpolate(frame, ...)驱动静态裁剪直接传数字常量Sequence必须使用layoutabsolute-fill否则运行期抛TypeError不要把crop*与手写clipPath混用在同一元素上使用裁剪时遵循可编辑、可关键帧原则让裁剪结果能在画布中还原与继续调整。在 Remotion 的画布合成工作流中crop*系列属性提供的是「面向编辑器的声明式裁剪」把裁剪从 CSS 细节提升为可视化、可动画、可校验的一等公民能力。无论是裁掉素材边缘、制作画幅开合动画还是在画布上拖拽调整可见区域从本文列出的支持组件中任选其一并传入 0 到 1 的裁剪比例即可开始。【免费下载链接】remotion Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表