利用tween 實現react 簡單transition 效果的代碼

效果還可以,使用很簡單

在線演示地址:https://codesandbox.io/s/cocky-leakey-9by5p?fontsize=14&hidenavigation=1&theme=dark

import React, { useRef, useEffect, useState, useCallback } from "react";
import styled from "styled-components";
import { isEqual } from "lodash";
import TWEEN from "@tweenjs/tween.js";
let { Group, Tween } = TWEEN;
let Div = styled.div`
  border: solid 1px red;
  height: 100px;
  width: 100px;
  position: absolute;
  top: 50px;
  background-color: red;
`;
Group.prototype.startAnimate = function() {
  var that = this;
  function step(timestamp) {
    if (that.update(timestamp) === false) {
      return;
    }
    requestAnimationFrame(step);
  }
  requestAnimationFrame(step);
};
let oldAdd = Group.prototype.add;
Group.prototype.add = function(tween) {
  var tweens = this.getAll();
  if (tweens.length === 0) {
    this.startAnimate();
  }
  oldAdd.call(this, tween);
};

function useTransition(config) {
  let { form, options = {}, to: properties } = config;
  let [props, setProps] = useState({});
  var animateRef = useRef({
    isStart: false,
    props: null,
    form: null,
    to: null,
    tween: null
  });

  const startAnimate = () => {
    let animate = animateRef.current;
    let tween = (animate.tween = new Tween({ ...animate.props }));
    tween._duration = options.duration || 500;
    tween._easingFunction = options.easing || TWEEN.Easing.Cubic.InOut;
    tween
      .to({ ...animate.to })
      .onUpdate(object => {
        animate.props = { ...object };
        setProps({
          ...object
        });
      })
      .onComplete(() => {
        animate.isStart = false;
      })
      .start();
  };
  useEffect(() => {
    let animate = animateRef.current;
    let isChange = false;
    if (!isEqual(animate.form, form)) {
      animate.form = form;
      animate.props = form;
      isChange = true;
    }
    if (!isEqual(animate.to, properties)) {
      animate.to = properties;
      isChange = true;
    }
    if (isChange) {
      if (animate.isStart) {
        animate.tween.stop();
      }
      startAnimate();
    }
  });

  return props;
}

export default () => {
  const [collapse, setState] = useState(false);
  const props = useTransition({
    options: {
      duration: 500
    },
    form: {
      opacity: 0,
      width: 0
    },
    to: {
      opacity: collapse ? 0 : 1,
      width: collapse ? 0 : 100
    }
  });
  const onSwitch = () => {
    setState(!collapse);
  };

  return (
    <div>
      <Div style={props} />
      <button onClick={onSwitch}>switch</button>
    </div>
  );
};

 

發佈了46 篇原創文章 · 獲贊 14 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章