【问题标题】:Making a clickable SVG that doesn't trigger a mouseLeave制作一个不会触发 mouseLeave 的可点击 SVG
【发布时间】:2021-11-27 04:12:37
【问题描述】:

我正在尝试做的事情:

  • 当您将鼠标悬停在行上时,颜色会发生变化并出现 SVG
  • 您可以单击SVG(当前在控制台中显示'clicked')来触发一个函数(也需要支持触发外部函数,而不仅仅是那些需要在svg内部的script标签中定义的函数,例如props函数)
  • 当您的鼠标离开时,该行将恢复为原始形式

问题:

  • 将鼠标悬停在 SVG 按钮上会触发 mouseLeave(离开行) 如果指针事件未设置为无。如果设置为 none,则 SVG 按钮变得无法点击。
  • onClick inside SVG 似乎不支持外部函数(props 例如函数)

不胜感激。

const { Container, Row, Col} = ReactBootstrap;
function Library(props){
  
  function handleMouseEnter(e){
    e.style.background = 'blue';
    var targetNode = e.querySelector(`#content`);
    ReactDOM.render(                
      <svg  width="0.75rem" height="0.75rem" className="Layer_1" x="0px" y="0px" viewBox="0 0 472.615 472.615" fill="white">   
        <polygon onClick={e => console.log('clicked')} points="50.273,0 50.273,472.615 422.342,236.308"/>
      </svg>
      , targetNode);
  }
  
  function handleMouseLeave(e){
    e.style.background = '';
    var targetNode = e.querySelector(`#content`);
    ReactDOM.render(                
      "hover over me and click the button!"
      , targetNode);
  }
  
  return(
  <Container>
    <Row 
    onMouseEnter={e => handleMouseEnter(e.target.closest('.row'))}
    onMouseLeave={e => handleMouseLeave(e.target.closest('.row'))}
    >
      <Col>
        <div id="content">
          hover over me and click the button!
        </div>        
      </Col>
    </Row>
  </Container>
  )
}

ReactDOM.render(
  <Library/>,
  document.getElementById('root')
);
.row{
background:red;
}
svg{
pointer-events:none;
}
<script src="https://unpkg.com/react/umd/react.production.min.js" crossorigin></script>

<script
  src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"
  crossorigin></script>

<script
  src="https://unpkg.com/react-bootstrap@next/dist/react-bootstrap.min.js"
  crossorigin></script>
<div id="root"></div>

【问题讨论】:

    标签: javascript css reactjs events react-bootstrap


    【解决方案1】:

    我想我通过编辑 onMouseLeave 来检查触发它的元素是否是 SVG 或其子元素之一,如果是,则将其视为误报,从而解决了这个问题。现在该按钮是可点击的,并且如果您将鼠标悬停在它上面也不会消失。

    const { Container, Row, Col} = ReactBootstrap;
    function Library(props){
      
      function handleMouseEnter(row){
        row.style.background = 'blue';
        var targetNode = row.querySelector(`#content`);
        ReactDOM.render(                
          <svg onClick={e => console.log('clicked')} width="0.75rem" height="0.75rem" className="Layer_1" x="0px" y="0px" viewBox="0 0 472.615 472.615" fill="white">   
            <polygon points="50.273,0 50.273,472.615 422.342,236.308"/>
          </svg>
          , targetNode);
      }
      
      function handleMouseLeave(e, row){
        if(e.relatedTarget.tagName === 'svg' || e.relatedTarget.tagName === 'polygon') return
        row.style.background = '';
        var targetNode = row.querySelector(`#content`);
        ReactDOM.render(                
          "hover over me and click the button!"
          , targetNode);
      }
      
      return(
      <Container>
        <Row 
        onMouseEnter={e => handleMouseEnter(e.target.closest('.row'))}
        onMouseLeave={e => handleMouseLeave(e, e.target.closest('.row'))}
        >
          <Col>
            <div id="content">
              hover over me and click the button!
            </div>        
          </Col>
        </Row>
      </Container>
      )
    }
    
    ReactDOM.render(
      <Library/>,
      document.getElementById('root')
    );
    .row{
    background:red;
    }
    <script src="https://unpkg.com/react/umd/react.production.min.js" crossorigin></script>
    
    <script
      src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"
      crossorigin></script>
    
    <script
      src="https://unpkg.com/react-bootstrap@next/dist/react-bootstrap.min.js"
      crossorigin></script>
    <div id="root"></div>

    【讨论】:

      【解决方案2】:

      也许你可以尝试使用useState 进行条件渲染

      import { useState } from "react";
      import { ReactComponent as Icon } from "./Icon.svg";
      
      const YourApp = () => {
        const [onHover, setOnHover] = useState(false);
      
        const handleMouseEnter = () => {
          setOnHover(true);
        };
        const handleMouseLeave = () => {
          setOnHover(false);
        };
      
        return (
          <div
            style={onHover ? { background: "blue" } : { background: "red" }}
            onMouseEnter={handleMouseEnter}
            onMouseLeave={handleMouseLeave}
          >
            {onHover && <Icon onClick={(e) => console.log("clicked")} />}
            hover over me and click the button!
          </div>
        );
      };
      
      export default YourApp;
      

      【讨论】:

        【解决方案3】:

        您可以创建文件 .svg 并将您的 svg 存储在该文件中。 例子

        Icon.svg

            <svg  width="0.75rem" height="0.75rem" className="Layer_1" x="0px" y="0px" viewBox="0 0 472.615 472.615" fill="white">   
                <polygon points="50.273,0 50.273,472.615 422.342,236.308"/>
            </svg>
        

        您可以将Icon.svg 渲染到您的组件示例中:

        YourComponent.jsx

        import { ReactComponent as Icon } from "./Icon.svg";
        
        const YourComponent = () => {
          return (
            <div>
              <Icon onClick={e => console.log('clicked')} />
            </div>
          );
        };
        
        export default YourComponent;
        

        恭喜你现在可以点击你的Icon.svg

        在最佳实践中,如果您想导入一些 .svg 图像,您应该导入为 ReactComponent

        【讨论】:

        • 感谢您的回复。我对此进行了测试,但它并没有完全回答我的问题。理论上,SVG 是可点击的,但问题是如果我不将 SVG 的样式设置为 pointer-events:none; SVG 在我单击它之前从行中消失,因为它触发了 onMouseLeave 事件。如果我设置指针事件:无; SVG 不会触发 onMouseLeave,因此它会像我发布的代码一样保留在屏幕上,但是这种样式会禁用所有鼠标交互,因此现在无法点击。
        • 虽然我认为你的回答会帮助我使用 onClick 的外部函数,比如道具函数等......
        • 检查我的另一个答案...
        猜你喜欢
        • 2019-12-16
        • 2016-10-21
        • 1970-01-01
        • 2018-11-14
        • 2020-12-27
        • 2018-04-18
        • 1970-01-01
        • 2022-01-19
        相关资源
        最近更新 更多