css 边距过渡在反应中没有动画

css margin transition doesnt animate in react

我正在尝试创建一个可以平滑移动的简单反应开关组件

这是反应代码

export function Switch({callBackOn, callBackOff}){
    const [switchState, setState] = useState("");

    function callback(){
        if(switchState == ""){
            setState("switch-on")
        }
        else{
            setState("")
        }
    }
    return(
      <div onClick={callback} className={"switch " + switchState}>
        <div></div>
      </div>
    )
  }

这是我的 css

.switch {
  background-color: red;
  height: 5rem;
  width: 10rem;
  border-radius: 2.5rem;
  border: 5px solid;
  transition: 1s;
  position: relative;
}

.switch-on {
  background-color: green !important;
}

.switch div {
  height: 5rem;
  width: 5rem;
  border-radius: 2.5rem;
  background-color: white;
  transition: margin-left 1s;
}

.switch-on div {
  margin-left: auto;
}

背景颜色变化过渡有效,但页边距变化根本没有动画效果。我也尝试过使用关键帧和动画属性,但它也没有用

您无法真正在 auto 和固定值之间转换。 既然你知道开关有多宽,我建议只添加正确的值:

document.querySelector('.switch').addEventListener('click', function(event) {
  event.currentTarget.classList.toggle('switch-on')
})
.switch {
  background-color: red;
  height: 5rem;
  width: 10rem;
  border-radius: 2.5rem;
  border: 5px solid;
  transition: 1s;
  position: relative;
}

.switch-on {
  background-color: green !important;
}

.switch div {
  height: 5rem;
  width: 5rem;
  border-radius: 2.5rem;
  background-color: white;
  transition: margin-left 1s;
}

.switch-on div {
  margin-left: 5rem;
}
<div class="switch">
  <div></div>
</div>

注:read more on the subject here.

正如 Barthy 提到的,你不能 animate/transition margin: automagrin 也不是 的最佳方式 animate/transition。为此,最好使用 transform 属性。 How to create high-performance CSS animations

有保证金的解决方案

function Switch({ callBackOn, callBackOff }) {
  const [switchState, setState] = React.useState("");

  function callback() {
    if (switchState == "") {
      setState("switch-on");
    } else {
      setState("");
    }
  }
  return (
    <div onClick={callback} className={"switch " + switchState}>
      <div></div>
    </div>
  );
}

function App() {
  return (
    <div className="App">
      <Switch />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
    <App />,
  rootElement
);
.App {
  font-family: sans-serif;
  text-align: center;
}

.switch {
  background-color: red;
  height: 5rem;
  width: 10rem;
  border-radius: 2.5rem;
  border: 5px solid;
  transition: 1s;
  position: relative;
}

.switch-on {
  background-color: green;
}

.switch div {
  height: 5rem;
  width: 5rem;
  border-radius: 2.5rem;
  background-color: white;
  transition: margin-left 1s;
}

.switch-on div {
  margin-left: 5em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

转换解决方案

function Switch({ callBackOn, callBackOff }) {
  const [switchState, setState] = React.useState("");

  function callback() {
    if (switchState == "") {
      setState("switch-on");
    } else {
      setState("");
    }
  }
  return (
    <div onClick={callback} className={"switch " + switchState}>
      <div></div>
    </div>
  );
}

function App() {
  return (
    <div className="App">
      <Switch />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
    <App />,
  rootElement
);
.App {
  font-family: sans-serif;
  text-align: center;
}

.switch {
  background-color: red;
  height: 5rem;
  width: 10rem;
  border-radius: 2.5rem;
  border: 5px solid;
  transition: 1s;
  position: relative;
}

.switch-on {
  background-color: green;
}

.switch div {
  height: 5rem;
  width: 5rem;
  border-radius: 2.5rem;
  background-color: white;
  transition: transform 1s;
}

.switch-on div {
  transform: translateX(5em);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>