我试图将错误消息显示为烤面包(React Component),该消息将在某些秒后消失。但是,当用户在淡入淡出时将鼠标悬停在吐司上时,淡出应该停止并且吐司应恢复到其初始状态;当用户将鼠标悬停在吐司上时,淡出应该再次开始。可以通过使用JQuery这样实现-
//用于在时间-t秒后开始淡出的功能
static fadeOutToast(id, t) {
let toast = document.getElementById(id);
if (toast) {
setTimeout(() => {
FadeAndRemove('#' + id);
}, t * 1000);
}
}
/ ** * t1-淡出动画的时间 * /
static FadeAndRemove(id,t1) {
jQuery(id).fadeOut(t1 * 1000, function () {
jQuery(this).hide();
});
handleReAppear(id);
}
static handleReAppear(id) {
jQuery(id).on("mouseover", function (e) {
jQuery(this).stop(true).fadeIn(0);
});
jQuery(id).on("mouseleave", function (e) {
FadeAndRemove(this);
});
}
它工作得很好。但是由于项目的限制,我不应该混淆Jquery并做出反应。
我试图通过操纵mouseEnter和mouseLeave事件的CSS不透明度来实现这一点。我面临的问题是,烤面包永远不会使用不透明性脱离页面。有什么方法可以检测烤面包的不透明度何时变为0,以便我可以在不透明度变为0时将其从页面中删除?
有人可以在不使用Jquery的情况下帮助我实现相同目标吗?
答案 0 :(得分:0)
对于褪色动画,我将使用React-Spring。使用Spring
可以延迟开始动画,以便在延迟之后淡出。
然后,您可以添加onMouseEnter
和onMouseLeave
事件处理程序,以检测烤面包机的悬停状态。
通过这种鼠标检测,您可以将Spring的to
值切换为opacity
1。这样,如果鼠标悬停在烤面包上,它就不会淡出。
要除去烤面包机,可以使用Spring的onRest
,然后检查opacity
是否为零。动画结束后,将立即调用onRest
。
状态管理在Toastr
组件内完成,它将呈现所有显示的toasts
。该组件还将处理去除不透明的吐司面包。
对于点击事件addToast
,我使用的是高阶组件withToastr
,因此我可以将prop的属性添加到包含的组件中。
对于事件处理,我使用的是Eventemitter3。如果您使用的是Redux,也可以使用它来触发敬酒。
在接下来的部分中,我将详细介绍在以下Codesandbox中创建的每个组件。 (注意:此处的代码段未运行-要测试代码,请查看沙盒)
ToastrItem
组件负责渲染吐司和动画。
import React, { PureComponent } from "react";
import { Spring } from "react-spring";
import styled from "styled-components";
import PropTypes from "prop-types";
class ToastrItem extends PureComponent {
static propTypes = {
id: PropTypes.string,
timeout: PropTypes.number,
destroy: PropTypes.func
};
static defaultProps = {
timeout: 5000
};
state = {
hovered: false
};
handleRest = ({ opacity }) => {
if (opacity === 0) {
this.props.destroy(this.props.id);
}
};
handleMouseEnter = () => {
this.setState({
hovered: true
});
};
handleMouseLeave = () => {
this.setState({
hovered: false
});
};
render() {
const { message, index, timeout } = this.props;
const { hovered } = this.state;
return (
<Spring
config={{ duration: 600, delay: timeout }}
from={{ opacity: 1.0 }}
to={{ opacity: hovered ? 1.0 : 0 }}
onRest={this.handleRest}
>
{interpolated => (
<Wrapper>
<ToastBox
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
pos={index}
opacity={interpolated.opacity}
>
{message}
{/*- debug info: {JSON.stringify(interpolated)}*/}
</ToastBox>
</Wrapper>
)}
</Spring>
);
}
}
const Wrapper = styled.div`
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
pointer-events: none;
z-index: 100;
`;
const ToastBox = styled.div.attrs(props => ({
style: {
transform: `translateY(${props.pos * 80}px)`,
opacity: props.opacity
}
}))`
width: 60%;
height: 50px;
line-height: 50px;
margin: 0 auto;
color: white;
padding: 10px;
background: rgba(0, 0, 0, 0.8);
text-align: center;
box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.5);
border-radius: 10px;
pointer-events: auto;
`;
export default ToastrItem;
春天正在做前面提到的动画。鼠标事件enter
/ leave
设置了本地状态hovered
,因此我们可以更改动画的末端不透明度-这样可以避免动画。
我还尝试了reset
的{{1}}道具,但是效果不理想。
React-Spring
组件此组件正在管理活动的吐司。这里没什么特别的。它呈现了Toastr
添加的toasts数组。
addToast
正在创建带有时间戳和数组索引的相对唯一的键。这是必需的,因此React在组件上获得了关键支撑。我们也可以在这里使用uuid库,但我认为timestamp-id可以。
如果不透明度为0,则会调用addToast
,然后按键对其进行过滤并更新状态。地图就在那儿,因此我们正在更新吐司的位置。
destroy
我们正在使用class Toastr extends PureComponent {
state = {
toasts: []
};
addToast = (message, config) => {
const index = this.state.toasts.length;
const id = `toastr-${Date.now()}-${index}`;
const ToastComponent = (
<ToastrItem
key={id}
id={id}
index={index}
message={message}
timeout={config.timeout || 3000}
destroy={this.destroy}
/>
);
this.setState(state => ({
toasts: [...state.toasts, ToastComponent]
}));
};
destroy = id => {
this.setState(state => ({
toasts: [
...state.toasts
.filter(toast => toast.key !== id)
.map((toast, index) => ({
// map for updating index
...toast,
props: {
...toast.props,
index: index
}
}))
]
}));
};
componentDidMount() {
emitter.on("add/toastr", this.addToast);
}
render() {
const { toasts } = this.state;
return toasts;
}
}
export const withToastr = WrappedComponent => {
return class extends PureComponent {
render() {
return <WrappedComponent addToast={actions.add} />;
}
};
};
添加addToast
。这会将prop addToastr添加到App组件。
然后,我们将渲染withToastr(App)
组件,该组件将管理和渲染我们的敬酒。
最后,我们添加一个按钮,以便触发吐司。
Toastr
代码正在工作,但是我会在Spring上添加class App extends Component {
toastr;
render() {
const { addToast } = this.props;
return (
<div className="App">
<Toastr />
<button onClick={() => addToast("Hello", { timeout: 4000 })}>
Show toast
</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
const AppWithToasts = withToastr(App);
ReactDOM.render(<AppWithToasts />, rootElement);
prop,并且还要检查过渡是否更适合用例。请参阅来自React-spring文档的MessageHub example中的示例。应该也可以防止淡出,但我没有检查。
答案 1 :(得分:0)
您可能想考虑使用Animatable库。它使用了很容易合并的声明性语法。
import * from 'react-native-animatable';
return(
<Animatable.View animation="fadeOut" duration={2000} delay={1000}>
<View>
{/* YOUR CONTENT */}
</View>
</Animatable.View>
);