簡體   English   中英

在沒有Mouse的情況下在mouseEnter和mouseLeave上停止/開始淡出反應

[英]React stop/start fade-out on mouseEnter and mouseLeave without Jquery

我正在嘗試將錯誤消息顯示為Toast(反應組件),該消息將在某些秒后消失。 但是,當用戶在淡入淡出時將鼠標懸停在吐司上時,淡出應該停止並且吐司應恢復到其初始狀態;當用戶將鼠標懸停在吐司上時,淡出應該再次開始。 可以這樣使用JQuery來實現-

//開始計時的功能-t sec

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的情況下幫助我實現相同目標嗎?

對於褪色動畫,我將使用React-Spring 使用Spring可以延遲開始動畫,以便在延遲后淡出。 然后,您可以添加onMouseEnteronMouseLeave事件處理程序以檢測烤面包機的懸停。

通過這種鼠標檢測,您可以將Spring的to值切換為opacity 1。這樣,如果將鼠標懸停在烤面包上,它將不會淡出。

為了刪除烤面包機,您可以使用Spring的onRest並檢查opacity是否為零。 動畫結束后將立即調用onRest

狀態管理是內部完成Toastr組件,它將使所有顯示的toasts 該組件還將處理不帶有不透明性的烤面包。

對於click event addToast我在addToast使用了更高階的組件,因此可以將prop的withToastr添加到包含組件。

對於事件處理,我使用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本地狀態,因此我們可以更改動畫的結束不透明度-這樣可以避免動畫。 我也嘗試過React-Spring reset prop,但是效果不如預期。

Toastr組件

該組件正在管理活動的吐司。 這里沒什么特別的。 它呈現了與addToast添加的addToast數組。 addToast正在創建帶有時間戳和數組索引的相對唯一的鍵。 這是必需的,因此React在組件上獲得了關鍵支撐。 我們也可以在這里使用uuid庫,但我認為timestamp-id可以。 如果不透明度為0,則將調用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} />; } }; }; 

在應用中的使用

我們通過使用withToastr(App)添加addToast 這會將prop addToastr添加到App組件。 然后,我們將渲染將管理和渲染吐司的Toastr組件。 最后,我們添加一個按鈕,以便觸發吐司。

 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); 

結論

該代碼正在運行,但是我將向Spring添加native道具,並且還將檢查過渡是否更適合該用例。 請參閱來自React-spring文檔的MessageHub示例中的示例 應該也可以防止淡出,但是我還沒有檢查。

您可能要考慮使用Animatable庫。 它使用了很容易合並的聲明性語法。

import * from 'react-native-animatable';

return(
        <Animatable.View animation="fadeOut" duration={2000} delay={1000}>
            <View>
               {/* YOUR CONTENT */}
            </View>
        </Animatable.View>
    );

https://github.com/oblador/react-native-animatable

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM