Elementor Atomic Builder Interactions 交互系统全解析:从编辑器配置到 Motion.js 前端执行
【免费下载链接】elementorThe most advanced frontend drag & drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design.项目地址: https://gitcode.com/GitHub_Trending/el/elementor
导读
本文以 Elementor 开源仓库(el/elementor)中 docs/atomic-builder/interactions/overview.md 为骨架,结合modules/interactions/的 PHP 保存管线与@elementor/editor-interactions编辑器包源码,系统讲解 Atomic(v4)元素上的交互(Interactions)功能:数据模型(interaction item 与 PropValue 结构)、保存时的校验与稳定 ID 分配、postmeta 缓存、前端经 Motion.js 执行,以及面向设计师、插件作者和内部贡献者的扩展方式。读完后你将掌握该交互子系统的完整链路,并能基于公共 API 二次开发。
一、Interactions 是什么
Interactions 为 Atomic(v4)元素添加动效能力。每个元素持有interactionsprop——它是一个带版本的交互条目列表,每条交互条目(interaction item)由"触发器(trigger)+ 动画预设(animation preset)+ 可选的断点排除(breakpoint exclusions)"组成。
数据的生命周期贯穿三层:
| 层级 | 位置 |
|---|---|
| PHP 模块 | modules/interactions/ |
| 编辑器包 | packages/packages/core/editor-interactions/ |
| 前端脚本 | modules/interactions/assets/js/ |
| 动画库 | Motion.js(lib/motion/motion.js,版本 v11.13.5) |
从源码实现看,数据在保存时被校验(Validation)、由Parser分配稳定 ID,随后写入 postmeta 作为前端读取的缓存,最终由浏览器端 Motion.js 执行动画。
二、什么时候使用它
- 设计师:在编辑器 Interactions 标签页为元素配置入场(entrance)与滚动(scroll)动画,无需写代码。
- 插件/附加组件作者:通过
elementor/atomic-widgets/interactions/schema过滤器扩展 schema,通过registerInteractionsControl注册编辑器控件,可以引入自定义触发器与动画效果。 - 内部贡献者:在 modules/interactions/(保存管线、校验、前端)或
editor-interactions(标签页 UI、预览)中工作。
功能门控(Gate):Module::is_experiment_active()要求启用e_atomic_elements实验(即 AtomicWidgetsModule::EXPERIMENT_NAME)。在 module.php 中可以看到,若实验未激活,__construct()会直接返回、不注册任何钩子。
三、核心概念
3.1 Interaction item 数据结构
交互条目是一个PropValue,其$$type为"interaction-item",包含四个字段:
interaction_id:稳定且唯一的交互 ID(保存时由 Parser 生成);trigger:触发器枚举(load、scrollIn、scrollOut、scrollOn、hover、click);animation:animation-preset-props类型的动画预设;breakpoints:interaction-breakpoints类型的断点配置(可选)。
其类型定义见 props/interaction-item-prop-type.php:Interaction_Item_Prop_Type extends Object_Prop_Type,trigger字段通过meta( 'enum', Presets::triggers_options() )标注可选枚举,并通过meta( 'pro', Presets::ADDITIONAL_TRIGGERS )标注哪些属于 Pro 能力。
3.2 文档中的数据结构示例
{ "version": 1, "items": [ { "$$type": "interaction-item", "value": { "interaction_id": { "$$type": "string", "value": "hero-fade-in" }, "trigger": { "$$type": "string", "value": "scrollIn" }, "animation": { "$$type": "animation-preset-props", "value": { "...": "..." } } } } ] }schema 的根定义位于 schema/interactions-schema.php:Interactions_Schema::get()返回经过apply_filters( 'elementor/atomic-widgets/interactions/schema', ... )过滤后的 canonical prop-type 树,目前固定为version: 1与items数组。
3.3 保存管线(Save pipeline)
保存流程在 module.php 中由两个钩子驱动:
elementor/document/save/data→handle_interactions():先Validation::sanitize()清洗并校验数据(非法条目会被剔除),随后validate()检查每个元素最多 5 条交互(超出抛异常:Element %s has more than %d interactions,见 validation.php);最后Parser::assign_interaction_ids()为缺少 ID 或temp-临时 ID 的条目分配稳定 ID。elementor/document/after_save→handle_interactions_cache():Interactions_Postmeta将每个元素与交互的映射写入 postmeta 缓存,供前端读取。
Parser(parser.php)会递归遍历elements树:对每个interactions字段解码后,若interaction_id存在且以temp-开头(临时 ID)或缺失,则调用Utils::generate_id()生成"{post_id}-{element_id}-"前缀的稳定 ID,并把已用 ID 记入ids_lookup防止冲突。
校验器(validation.php)对每个条目逐层验证:
- 顶层必须为
{ $$type: 'interaction-item', value: {...} }; trigger必须通过 Trigger_Value 校验;animation必须为animation-preset-props,其effect仅允许fade / slide / scale / custom,type仅允许in / out,direction允许空字符串或 8 个方向;timing_config的duration/delay支持number与size两种格式,且非负;config中的start/end(0–100)、repeat(''、loop、times)、times(≥1)、replay(布尔)、easing、relativeTo均做类型与范围校验;breakpoints通过 Breakpoints_Value 校验;- 自定义效果通过 Custom_Effect_Value 校验。
3.4 运行时配置(Config)
Module::get_config()(module.php)暴露给 JS 的配置对象ElementorInteractionsConfig(常量JS_CONFIG_OBJECT)包含两部分:
constants:来自Presets::defaults()的预设默认值;breakpoints:当前激活的响应式断点配置(由Plugin::$instance->breakpoints读取)。
编辑器侧通过wp_add_inline_script注入window.ElementorInteractionsConfig,预览 iframe 通过wp_localize_script注入。
3.5 预设值与枚举
presets.php 定义了所有允许的枚举与默认值,是校验与编辑器控件的单一事实来源:
| 类别 | 值 |
|---|---|
| 触发器 | 基础:load、scrollIn;附加(Pro):scrollOut、scrollOn、hover、click |
| 效果 | 基础:fade、slide、scale;附加:custom |
| 类型 | in、out |
| 方向 | left、right、top、bottom、top-left、top-right、bottom-left、bottom-right、'' |
| 缓动 | 基础:easeIn;附加:easeOut、easeInOut、backIn、backInOut、backOut、linear |
| 重复模式 | ''、loop、times |
| 默认值 | defaultDuration: 600(ms)、defaultDelay: 0、slideDistance: 100、scaleStart: 0、relativeTo: 'viewport'、start: 85、end: 15、defaultEasing: 'easeIn'、repeat: '' |
四、前端执行:从 postmeta 到 Motion.js
4.1 数据收集(Collector + Frontend Handler)
interactions-frontend-handler.php 通过两个钩子完成前端管线:
elementor/frontend/builder_content_data→collect_document_interactions():在编辑模式下直接跳过;否则优先从Interactions_Postmeta读取该文档的缓存,缓存为空时现场process_content()生成,再逐条注册进单例 Interactions_Collector(请求级聚合,register()/get_all())。wp_footer(优先级 1)→print_interactions_data():若无交互数据则直接返回;否则按需加载 Motion.js 与前端交互脚本,并以<script type="application/json" id="elementor-interactions-data">的形式集中输出 JSON,每条记录为{ elementId, dataId, interactions }。
4.2 前端脚本执行
assets/js/interactions.js 是前端入口,流程清晰:
- 等待 Motion.js 的
animate与inView函数就绪(waitForAnimateFunction); - 读取
#elementor-interactions-data脚本标签中的集中式 JSON; - 按
elementId通过[data-interaction-id="..."]选择器找到目标 DOM 元素; - 对每条交互调用
applyAnimation():先读取元素计算样式中的 transform 基线(getTransformBaselineFromComputedStyle)、用preserveTransformKeyframes保留已有 transform 关键帧,再按效果/类型/方向生成关键帧;动画期间临时将element.style.transition置为none以免 CSS transition 破坏动画; - 按触发器分支执行:
scrollOut使用amount: 0.85的视口阈值并在播放后(replay === false时)停止监听;scrollIn使用amount: 0阈值;其余(load、hover、click等)走默认动画分支。
前端脚本的注册与依赖关系见 module.php:motion-js(v11.13.5)→elementor-interactions-shared-utils→elementor-interactions/elementor-editor-interactions,均在elementor/frontend/after_register_scripts中注册。
五、扩展(Extension)
扩展入口有两个,详见 docs/atomic-builder/interactions/schema.md 与 docs/atomic-builder/interactions/editor.md:
- Schema 层:使用过滤器
elementor/atomic-widgets/interactions/schema扩展Interactions_Schema::get()返回的 prop-type 树(新增自定义 prop type 或修改现有枚举)。 - 编辑器控件层:使用
registerInteractionsControl注册自定义控件,编辑器 UI 会自动渲染。
需要注意:新增触发器(trigger)或效果(effect)需要在PHP 与 JS 两侧同步实现——PHP 侧修改Validation(枚举白名单)与Presets(新增枚举与默认值),JS 侧修改interactions.js(动画执行逻辑)与interactions-utils.js(配置解析)。目前没有公开的前端注册钩子,即前端执行逻辑暂不支持无侵入扩展。
六、公共 API 一览
| 符号 | 签名 | 用途 | 源码 |
|---|---|---|---|
Interactions_Schema | ::get(): array | 返回(经过滤的)canonical prop-type 树 | schema/interactions-schema.php |
Parser | assign_interaction_ids( $data ): array | 保存时分配稳定 ID | parser.php |
Presets | triggers_options()、effects_options()、easing_options()、defaults() | 允许的枚举值与默认值 | presets.php |
Validation | sanitize( $document )、validate() | 保存时清洗与校验 | validation.php |
Interactions_Frontend_Handler | collect_document_interactions()、print_interactions_data() | 前端收集与页脚输出 | interactions-frontend-handler.php |
Interactions_Collector | ::instance()、register()、get_all() | 请求级数据聚合(单例) | interactions-collector.php |
registerInteractionsControl | ( { type, component, options? } ) | 注册编辑器控件 | interactions-controls-registry.ts |
interactionsRepository | .register( provider )、.all() | 编辑器交互数据注册表 | interactions-repository.ts |
useElementInteractions | ( elementId ) | 编辑器内读写元素的交互 | use-element-interactions.ts |
关键过滤器:elementor/atomic-widgets/interactions/schema——用于扩展Interactions_Schema::get()返回的 schema。
七、内部钩子与集成点
| 钩子 / 集成点 | 角色 |
|---|---|
elementor/frontend/after_register_scripts | 注册 Motion.js 与交互相关脚本(module.php) |
elementor/document/save/data | 校验 + ID 分配 |
elementor/document/after_save | 写入 postmeta 缓存 |
elementor/frontend/builder_content_data | 调用collect_document_interactions收集数据 |
wp_footer | 调用print_interactions_data输出集中式 JSON |
editor-editing-panel | 挂载InteractionsTab(interactions-tab.tsx) |
从源码结构看,导入/导出(import/export)流程通过Interactions_Schema::get()解析交互条目,保证与 schema 的 canonical 形态一致。
八、延伸阅读
- schema.md — prop-type 树与预设
- editor.md — 编辑器控件注册
- frontend.md — Motion.js 运行时
- ../atomic-widgets/overview.md — Atomic 元素模型
- ../fundamentals/prop-value.md — PropValue 约定
- ../getting-started/experiments.md — 实验特性开关
【免费下载链接】elementorThe most advanced frontend drag & drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design.项目地址: https://gitcode.com/GitHub_Trending/el/elementor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考