Home > Software engineering >  Making a clickable SVG that doesn't trigger a mouseLeave
Making a clickable SVG that doesn't trigger a mouseLeave

Time:10-07

What I'm trying to do:

  • when you hover over the row, color changes and a SVG appears
  • you can click the SVG (currently displays 'clicked' in console) to trigger a function (needs to support triggering external functions too, not just ones that need to be defined inside script tags inside svg, so props functions for example)
  • when your mouse leaves, the row reverts to original form

Problems:

  • hovering over the SVG button triggers a mouseLeave (leaves the row) if pointer-events is not set to none. If it is set to none, the SVG button becomes unclickable.
  • onClick inside SVG doesn't seem to support external functions (props functions for example)

Would appreciate help with this.

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'))}
    onm ouseLeave={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>

CodePudding user response:

You can create file .svg and store your svg on that file. example

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>

And you can render your Icon.svg into your component example:

YourComponent.jsx

import { ReactComponent as Icon } from "./Icon.svg";

const YourComponent = () => {
  return (
    <div>
      <Icon onClick={e => console.log('clicked')} />
    </div>
  );
};

export default YourComponent;

and congratulation now you can click your Icon.svg.

in best practice if you wanna import some .svg images you should import as ReactComponent

CodePudding user response:

Maybe you can try this using useState for conditional rendering

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;
  • Related