动画化背景大小:"cover" 或 "contain"
有人问我关于使用GSAP将背景尺寸backgroundSize
id 为"cover"
或者"contain"
从或到"cover"或"contain"的动画效果的问题。问题在于:GSAP在数字之间进行插值,但是如何在类似"300px 250px"和"contain"(不是一个数字)之间进行插值呢?所以我快速编写了一个函数,基本上是将"contain"或"cover"转换为对应于该元素当前具体尺寸的像素值表达方式。一旦完成这个转换,做动画就变得非常简单了。
/*
config is optional and can have any of the following properties:
- size [string] - the size to set and convert into px before it gets returned, like "cover" or "150% auto".
- nativeWidth [number] - native width of the image (in pixels)
- nativeHeight [number] - native height of the image (in pixels)
Simple example:
// returns current backgroundSize in px
bgSize(".class");
Advanced example:
// sets the backgroundSize to "cover" and returns it in the equivalent px-based amount assuming the image's native width is 600px and height is 400px.
bgSize(".class", {size: "cover", nativeWidth: 600, nativeHeight: 400});
Note: if you can define the nativeWidth and nativeHeight, it helps becaues it can skip tasks like creating
an Image and loading the URL to detect the native size automatically. Sometimes images don't load fast enough,
so skipping that step avoids the whole issue.
*/
function bgSize(element, config) {
config = config || {};
let e = gsap.utils.toArray(element)[0],
cs = window.getComputedStyle(e),
imageUrl = cs.backgroundImage,
{ nativeWidth, nativeHeight } = config,
size = config.size || cs.backgroundSize,
image,
w,
h,
ew,
eh,
ratio;
if (imageUrl && (!/\d/g.test(size) || size.indexOf("%") > -1)) {
if (!nativeWidth || !nativeHeight) {
image = new Image();
image.setAttribute(
"src",
imageUrl.replace(/(^url\("|^url\('|^url\(|"\)$|'\)$|\)$)/gi, "")
);
nativeWidth = image.naturalWidth;
nativeHeight = image.naturalHeight;
}
ew = e.offsetWidth;
eh = e.offsetHeight;
if (!nativeWidth || !nativeHeight) {
console.log("bgSize() failed;", imageUrl, "hasn't loaded yet.");
nativeWidth = ew;
nativeHeight = eh;
}
ratio = nativeWidth / nativeHeight;
if (size === "cover" || size === "contain") {
if ((size === "cover") === nativeWidth / ew > nativeHeight / eh) {
h = eh;
w = eh * ratio;
} else {
w = ew;
h = ew / ratio;
}
} else {
// "auto" or %
size = size.split(" ");
size.push("");
w = ~size[0].indexOf("%")
? (ew * parseFloat(size[0])) / 100
: nativeWidth;
h = ~size[1].indexOf("%")
? (eh * parseFloat(size[1])) / 100
: nativeHeight;
}
size = Math.ceil(w) + "px " + Math.ceil(h) + "px";
config.size && (e.style.backgroundSize = size);
}
return size;
}
演示
加载中...
BackgroundSizePlugin
为了获得更大的灵活性,您可以使用这个非官方插件来对backgroundSize到"cover"或"contain"进行动画处理,它甚至允许您应用一个缩放比例到该值上。此外,如果您动画到"cover"或"contain",它实际上会将值设为这些关键字(而不是基于像素的等价值),以便在补间后保持响应性: