反应如何在本地指定动画@keyframes 和类

exe*_*ook 8 reactjs

function Loader() {
    var style = {
        border: '16px solid #eee',
        borderTop: '16px solid #3ae',
        borderRadius: '50%',
        width: '1cm',
        height: '1cm',
        animation: 'spin 2s linear infinite',
    }
    return (
        <div style={style}>
        <style>{`
            @keyframes spin {
                 0% { transform: rotate(0deg); }
                 100% { transform: rotate(360deg); }
            }
        `}</style>
        </div>
    )
}
Run Code Online (Sandbox Code Playgroud)

有没有办法@keyframes在不使用内联字符串的情况下在本地指定组件(本例中的组件函数)?

此外,如果您<style>在组件渲染函数中指定,如果有多个相同类的对象(或使用相同的@keyframes),它是否会降低性能?

这个想法是<style>在组件内部本地保留内容,我不想将它移动到.css文件中,但同时我不想要数百个重复的类/关键帧定义,而实际上只有一个就足够了。

Vla*_*hek 14

如果不编写辅助函数或使用一些可以注入关键帧的标准库,这是不可能的,因为用于此的浏览器选项仍处于试验阶段且未得到广泛支持,例如动画函数。

https://developer.mozilla.org/en-US/docs/Web/API/Element/animate

当通过使用 CSS 模块从另一个文件(例如 css 或 JS 文件)导入它们时,Webpack 通常会为您完成注入繁重的工作。

我建议您要么导入 CSS 文件,要么为此目的查看样式化组件辅助函数。

import React from "react";
import ReactDOM from "react-dom";
import { keyframes } from "styled-components";

function Loader() {
  var spin = keyframes`
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
`;

  var styles = {
    border: "16px solid #eee",
    borderTop: "16px solid #3ae",
    borderRadius: "50%",
    width: "1cm",
    height: "1cm",
    animation: `${spin} 2s linear infinite`
  };

  return <div style={styles} />;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Loader />, rootElement);
Run Code Online (Sandbox Code Playgroud)


Ron*_*omb 14

您可以按照与现有方式基本相同的方式进行操作,只需声明一个Keyframes组件来整理您的客户端代码。一些用法:

<Keyframes name="oscillate" from={{ opacity: 0.9 }} to={{ opacity: 0.2 }} />
Run Code Online (Sandbox Code Playgroud)

或者

<Keyframes name="oscillate" _0={{ opacity: 0.9 }} _100={{ opacity: 0.2 }} />
Run Code Online (Sandbox Code Playgroud)

您需要在百分比值前面添加下划线或其他字母,但其他方面是相同的。该组件循环遍历其所有 props,输出格式化的 css。使用 jsx,React 有一个特殊的 CSS 对象类型,需要将其转换为字符串,但否则它只是一个组件。

import * as React from "react";

interface IProps {
  name: string;
  [key: string]: React.CSSProperties | string;
}

export const Keyframes = (props: IProps) => {
  const toCss = (cssObject: React.CSSProperties | string) =>
    typeof cssObject === "string"
      ? cssObject
      : Object.keys(cssObject).reduce((accumulator, key) => {
          const cssKey = key.replace(/[A-Z]/g, v => `-${v.toLowerCase()}`);
          const cssValue = (cssObject as any)[key].toString().replace("'", "");
          return `${accumulator}${cssKey}:${cssValue};`;
        }, "");

  return (
    <style>
      {`@keyframes ${props.name} {
        ${Object.keys(props)
          .map(key => {
            return ["from", "to"].includes(key)
              ? `${key} { ${toCss(props[key])} }`
              : /^_[0-9]+$/.test(key)
              ? `${key.replace("_", "")}% { ${toCss(props[key])} }`
              : "";
          })
          .join(" ")}
      }`}
    </style>
  );
};
Run Code Online (Sandbox Code Playgroud)

  • 这是天才...我希望我能投票 100 次 (2认同)