效果还可以,使用很简单
在线演示地址: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>
);
};