跳过主要内容

v3.11.0 版本新增

gsap.matchMedia()

快速入门

最简用法

// create
let mm = gsap.matchMedia();

// add a media query. When it matches, the associated function will run
mm.add("(min-width: 800px)", () => {

// this setup code only runs when viewport is at least 800px wide
gsap.to(...);
gsap.from(...);
ScrollTrigger.create({...});

return () => { // optional
// custom cleanup code here (runs when it STOPS matching)
};
});

// later, if we need to revert all the animations/ScrollTriggers...
mm.revert();

返回值:MatchMedia

详细讲解

响应式、无障碍的动画和 ScrollTriggers,欢迎你的到来!🥳gsap.matchMedia()允许你将初始化代码封装在一个函数中,该函数仅在特定媒体查询匹配时执行,而当不再匹配时,该函数执行期间创建的所有 GSAP 动画和ScrollTriggers都会自动恢复初始状态自定义移动端/桌面端或prefers-reduced-motion无障碍功能变得异常简单。

每个媒体查询字符串正是你传给浏览器原生window.matchMedia()

基本语法

// create
let mm = gsap.matchMedia();

// add a media query. When it matches, the associated function will run
mm.add("(min-width: 800px)", () => {

// this setup code only runs when viewport is at least 800px wide
gsap.to(...);
gsap.from(...);
ScrollTrigger.create({...});

return () => { // optional
// custom cleanup code here (runs when it STOPS matching)
};
});

// later, if we need to revert all the animations/ScrollTriggers...
mm.revert();

我们创建一个mmMatchMedia 的变量,以便我们可以add()向这个对象添加任意多个媒体查询。这样,我们就可以通过单个对象调用revert()来立即恢复该 MatchMedia 对象所有关联函数中创建的动画/ScrollTriggers。

当 MatchMedia 变为激活状态(匹配)时,函数就会被调用。因此,如果用户多次调整浏览器大小超过断点并返回,该函数会被调用多次。

.add() 参数

  1. 查询/条件—— 一个媒体查询字符串比如"(min-width: 800px)"-或者- a 或一个包含任意命名查询字符串的条件对象;你可以检查每个查询是否匹配(布尔值)。参见下方详细了解条件语法的内容。下文关于条件语法的详细信息。
  2. 处理函数—— 当匹配时调用的函数。在此函数执行期间创建的所有 GSAP 动画和 ScrollTriggers 将被收集到上下文中,以便在 MatchMedia 被恢复时也能一并恢复(比如当条件不再满足时)。
  3. scope(作用域) [可选]—— 此处理函数内的所有 GSAP 相关选择器文本都将限定在此 Element 或React Ref或者Angular ElementRef内。可以理解为在这个元素上调用querySelectorAll(),因此只允许选择其子元素。详情请参见下文了解详情。

所以它的结构如下:

mm.add("(min-width: 800px)", () => {...}, myElementOrRef);

简单的桌面/移动示例

let mm = gsap.matchMedia();

mm.add("(min-width: 800px)", () => {
// desktop setup code here...
});

mm.add("(max-width: 799px)", () => {
// mobile setup code here...
});

条件语法

如果各种媒体查询的设置代码大部分相同,只有几个关键值不同怎么办?如果你add()单独编写每个媒体查询,可能会出现大量冗余代码。这时只需要使用条件语法!第一个参数不要使用字符串,而是使用一个包含任意命名条件的对象,那么只要其中一个条件匹配,该函数就会被调用,并且你可以在函数内检查每个条件是否匹配(布尔值)。条件对象可能如下所示:任意 of those conditions match and you can check each condition as a boolean (matching or not). The conditions object could look like this:

{
isDesktop: "(min-width: 800px)",
isMobile: "(max-width: 799px)",
reduceMotion: "(prefers-reduced-motion: reduce)"
}

条件名称由你自定。

下面我们将断点设为 800px 宽度,并尊重用户的prefers-reduced-motion偏好设置,利用相同的设置代码并在适当的地方使用条件逻辑:

let mm = gsap.matchMedia(),
breakPoint = 800;

mm.add(
{
// set up any number of arbitrarily-named conditions. The function below will be called when ANY of them match.
isDesktop: `(min-width: ${breakPoint}px)`,
isMobile: `(max-width: ${breakPoint - 1}px)`,
reduceMotion: "(prefers-reduced-motion: reduce)",
},
(context) => {
// context.conditions has a boolean property for each condition defined above indicating if it's matched or not.
let { isDesktop, isMobile, reduceMotion } = context.conditions;

gsap.to(".box", {
rotation: isDesktop ? 360 : 180, // spin further if desktop
duration: reduceMotion ? 0 : 2, // skip to the end if prefers-reduced-motion
});

return () => {
// optionally return a cleanup function that will be called when none of the conditions match anymore (after having matched)
// it'll automatically call context.revert() - do NOT do that here . Only put custom cleanup code here.
};
}
);

整洁又简洁!🎉

如果/当其中任何一个条件发生变化(当然,如果没有条件匹配,它不会再次运行)。例如,如果你有三个条件,其中两个匹配了,函数就会运行。接着,如果其中一个匹配的查询任意其中之一发生更改停止匹配(切换为不匹配)false不匹配

注意到上下文作为一个参数传递进来。当你需要稍后创建事件监听器或其他代码来生成应该在调用revert()时也被恢复的动画/ScrollTriggers 时,这将非常有用。

使用条件语法的演示

加载中...

交互性和清理

函数执行期间创建的 GSAP 动画和 ScrollTriggers 会被记录在上下文中,但如果你设置了事件监听器,比如“click”事件,在 MatchMedia 函数执行完成后才运行,之后该怎么办呢?你可以向 Context 对象本身添加() 一个带名称的函数,这样当它运行时,该函数创建的任何动画/ScrollTriggers 都会被收集到上下文中,例如:

let mm = gsap.matchMedia();

mm.add("(min-width: 800px)", (context) => {
context.add("onClick", () => {
gsap.to(".box", { rotation: 360 }); // <- now it gets recorded in the Context
});

myButton.addEventListener("click", context.onClick);

return () => {
// make sure to clean up event listeners in the cleanup function!
myButton.removeEventListener("click", context.onClick);
};
});

限制选择器文本的作用域

你可以选择性地传入一个 Element 或者React Ref或者Angular ElementRef作为第三个参数,然后所有在所提供的函数中的选择器文本将限制在这个特定的 Element/Ref 内(就像在该 Element/Ref 上调用querySelectorAll()一样)。

let mm = gsap.matchMedia();

mm.add("(min-width: 800px)", () => {

gsap.to(".box", {...}) // <- normal selector text, automatically scoped to myRefOrElement

}, myRefOrElement); // <- scope!!!

这个scope可以是选择器文本本身如".myClass",或者是一个 Element、React Ref 或 Angular ElementRef。

设置一个默认作用域创建 MatchMedia 时将其作为唯一参数传入:

let mm = gsap.matchMedia(myRefOrElement);

mm.add("(min-width: 800px)", () => {

// selector text scoped to myRefOrElement
gsap.to(".class", {...});

});

mm.add("(max-width: 799px)", () => {

// selector text scoped to myOtherElement
gsap.to(".class", {...});

}, myOtherElement); // <- overrides default scope!!!

刷新所有匹配项

使用gsap.matchMediaRefresh()立即恢复所有正在匹配的 MatchMedia 对象,然后重新运行当前匹配的那些对象。例如,如果你需要支持一个切换减少动画偏好的 UI 开关框,这将非常有用。

支持减少动画偏好的可访问动画

我们都喜欢动画,但它们可能会让一些前庭系统障碍用户感到恶心。尊重他们的偏好非常重要,要提供极简甚至完全无动画的体验。我们可以借助 prefers reduced motion 媒体查询来实现这一点

简单演示

加载中...

复选框切换

加载中...

更多信息请查看 CSS tricks 的这篇文章

我需要使用 gsap.context() 吗?

不需要!内部 gsap.matchMedia() 已经创建了一个gsap.context(),所以同时使用两者将是多余且完全没有必要的。你可以将 gsap.matchMedia() 视为对gsap.context()的特别封装。因此当你在 gsap.matchMedia() 对象上调用revert()时,其效果等同于在gsap.context().

示例

参考CodePen 集合

移动设备似乎不起作用?

尝试在你的代码中添加以下内容:<head></head>:

<meta name="viewport" content="width=device-width, initial-scale=1" />

gsap.matchMedia() 是在 GSAP 版本3.11.0

无噪 Logo
无噪文档
中文文档 · 复刻官网
查看所有 ↗