扩展 motion-anything 这类动效插件,核心不是修改源码,而是找到插件对外暴露的配置接口和生命周期钩子。未知内部 API 时,先在浏览器控制台检查插件实例,再对三个扩展点逐一尝试:初始化配置、事件回调、自定义动画函数。下面给出可复制的接入骨架。
自定义扩展的有效路径取决于插件是否开放实例对象和配置方法。通常可以从增删配置项、注册自定义动效、监听生命周期回调三个方向切入。操作前先确认实例可用方法,并在单独页面中做最小化测试,避免覆盖默认行为后无法回退。
第一步:确认插件实例和可用接口
没有统一的 API,但动效插件通常会在全局挂载一个构造函数,或在初始化时返回实例。先执行下面代码,确认扩展入口是否存在。
// 在浏览器控制台执行
console.log(window.MotionAnything);
// 如果配置了模块化引入,检查 import 的返回值
// 一般会有 init、setOption、on、destroy 等方法
如果没有任何输出,可以查看页面加载的脚本文件,搜索实例化代码。拿到实例后,继续执行:
const motion = new MotionAnything({ target: '.stage' });
console.log(Object.keys(motion));
console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(motion)));
这样能看出插件是否开放 addEffect、on、setOption 等接口。没有这些接口时,依然可以通过包装原始实例来扩展。
扩展方式一:配置参数覆盖与自定义动效注册
多数插件允许在初始化时传入配置对象,也允许后续动态修改。以下骨架展示了两种情况。
// 初始化时传入基础配置
const motion = new MotionAnything({
selector: '.animate-me',
duration: 800,
easing: 'ease-out'
});
// 动态覆盖参数
motion.setOption({
duration: 1200,
delay: 200
});
// 部分插件支持注册自定义动效
motion.addEffect('glitch', (el, params) => {
el.style.setProperty('`--glitch-x`', params.x || '2px');
return () => {
el.style.removeProperty('`--glitch-x`');
};
});
// 使用刚注册的动效
motion.play('.animate-me', { effect: 'glitch', x: '4px' });
如果插件没有 setOption 或 addEffect,可以退而求其次,直接替换实例上暴露的配置对象,但要注意替换前保留默认配置,方便回滚。
扩展方式二:生命周期回调与事件监听
动效的扩展往往不只是改动画本身,而是要在动画开始、更新、结束时联动其他逻辑。常见做法是传入回调,或监听事件。这里给出两种写法。
// 写法一:初始化时传入回调
const motion = new MotionAnything({
onStart: (el) => {
el.classList.add('is-animating');
},
onUpdate: (el, progress) => {
el.style.opacity = progress;
},
onComplete: (el) => {
el.classList.remove('is-animating');
}
});
// 写法二:使用事件监听
motion.on('start', (el) => {
console.log('start', el);
});
motion.on('complete', (el) => {
console.log('complete', el);
});
需要注意:有些插件只支持其中一种方式,且回调函数里的 this 指向不一定是你期望的实例。建议在回调开头用 console.log 打印参数,确认结构后再写具体逻辑。
扩展方式三:自定义 easing 与动画曲线
如果默认缓动函数不够用,可以注册自定义 easing。多数插件支持数组形式的三次贝塞尔参数,也支持传入函数。
// 自定义贝塞尔曲线,参数为四个值
const customEase = [0.25, 0.1, 0.25, 1];
motion.addEasing('custom-ease', customEase);
// 使用函数形式,t 是 0 到 1 的进度,返回 0 到 1 的结果
function bounceOut(t) {
if (t < 1 / 2.75) {
return 7.5625 * t * t;
} else if (t < 2 / 2.75) {
t -= 1.5 / 2.75;
return 7.5625 * t * t + 0.75;
} else if (t < 2.5 / 2.75) {
t -= 2.25 / 2.75;
return 7.5625 * t * t + 0.9375;
} else {
t -= 2.625 / 2.75;
return 7.5625 * t * t + 0.984375;
}
}
motion.addEasing('bounceOut', bounceOut);
如果插件不支持 addEasing,可以在配置里直接传入函数,或在动画执行前通过 wrap 方式包裹原生方法实现。
验证扩展是否生效
自定义扩展不生效时,按下面顺序排查:
- 在控制台执行 Object.keys(motion),确认插件实例存在且包含你调用的方法。
- 重新初始化插件,避免前一次动画的配置残留在实例上。
- 给元素加临时的 transitionend 或 animationend 监听,确认自定义回调真的被触发。
- 检查插件的 CSS 是否因为优先级覆盖了内联样式,必要时增加 !important 或提升选择器权重。
扩展前最好把默认配置和回调函数单独存一份,这样遇到问题可以快速还原,不会影响页面其他动效。