这是一种 JSX 方法(为此您需要 object-hash)。
以下示例展示了如何根据transform: scale(n) 定义具有各自唯一ID 的不同动画。为此,定义一个返回关键帧及其 ID 的函数。关键帧 ID 是一个自定义字符串,后缀为函数选项的哈希值(例如比例因子)。
(注意 CSS 自定义标识符,例如,不要在您的 ID 中包含 .。请参阅 MDN: < custom-ident >。)
import hash from "object-hash";
const keyFramesScale = (options = {}) => {
let { transforms, id, scale } = options;
transforms = transforms || "";
scale = scale || 1.25;
const keyFramesId = `scale${id ? "-" + id : ""}-${hash(options).substring(0, 6)}`;
const keyFrames = {
[`@keyframes ${keyFramesId}`]: {
"100%": {
transform: `scale(${scale}) ${transforms}`,
},
"0%": {
transform: `scale(1) ${transforms}`,
}
}
};
return [keyFramesId, keyFrames];
};
使用方法:
const [scaleUpId, keyFramesScaleUp] = keyFramesScale({ scale: 1.25, transforms: "rotate(-30deg)", id: "up" });
const [scaleDownId, keyFramesScaleDown] = keyFramesScale({ scale: 0.75, transforms: "rotate(-30deg)", id: "down" });
// scaleUpId = "scale-up-c61254"
// scaleDownId = "scale-down-6194d5"
// ...
<tag style={{
...keyFramesScaleUp,
...keyFramesScaleDown,
...(!hasTouchScreen && isActive && !isClicked && {
animation: `${scaleUpId} 0.5s infinite alternate linear`,
"&:hover": {
animation: "none",
},
}),
...(isClicked && {
animation: `${scaleDownId} .25s 1 linear`,
}),
}} />
当然,您可以编写一个更通用的函数,对整个关键帧进行哈希处理,并据此为其分配一个 ID。
编辑
为了具体化已经说过的话,这里是通用方法。我们首先定义一个通用函数,它接受动画名称(例如scale、pulse 等)、关键帧(可以是对象或函数)以及可选的关键帧参数及其默认值。
import hash from "object-hash";
const createKeyFramesId = (id, keyFrames) => {
return `${id}-${hash(keyFrames).substring(0, 6)}`;
};
const genericKeyFrames = (name, keyFrames, defaults = {}, options = {}) => {
if (typeof keyFrames === "function") {
// The order of defaults & options is important: the latter overrides the former.
keyFrames = keyFrames({ ...defaults, ...options });
}
const keyFramesId = createKeyFramesId(name, keyFrames);
const keyFramesObject = {
[`@keyframes ${keyFramesId}`]: keyFrames
};
return [keyFramesId, keyFramesObject];
};
从现在开始,我们可以定义各种动画。用法同上。
export const keyFramesPulse = () =>
genericKeyFrames("pulse", {
"100%": {
opacity: "1",
},
"0%": {
opacity: "0.5",
},
});
export const keyFramesRotate = (options = {}) => {
const defaults = {
rotate: 360,
transforms: "",
};
const rotateKeyFrames = ({ rotate, transforms }) => {
return {
"100%": {
transform: `rotate(${rotate}deg) ${transforms}`,
}
}
};
return genericKeyFrames(`rotate`, rotateKeyFrames, defaults, options);
};
export const keyFramesScale = (options = {}) => {
const defaults = {
scale: 1.25,
transforms: ""
};
const scaleKeyFrames = ({ scale, transforms }) => {
return {
"100%": {
transform: `scale(${scale}) ${transforms}`,
},
"0%": {
transform: `scale(1) ${transforms}`,
}
}
};
return genericKeyFrames(`scale`, scaleKeyFrames, defaults, options);
};
它在 DevTools 中的样子: