javascriptcssreactjssvgcss-transitions

Can anyone help me achieve smooth transition for SVG on onClick event in react.js?


I want to have a burger icon and on onClick event it changes into 'X' icon. But I cannot able to achieve smooth transition, Can someone help me?

React

import React, {useState} from 'react';
import '../Styles/BurgerIcon.css';

const BurgerIcon = () => {
  const [isMenuOpen, setIsMenuOpen] = useState(false);
  const toggleMenu = () => {
    setIsMenuOpen(!isMenuOpen);
  };
  return (
    <svg 
        xmlns="http://www.w3.org/2000/svg" 
        fill="none" 
        viewBox="0 0 24 24" 
        stroke-width="1.5" 
        stroke="currentColor"
        onClick={toggleMenu}
        class='burger_icon'
    >
        <path 
            className='burger_icon_path'
            stroke-linecap="round" 
            stroke-linejoin="round" 
            d={!isMenuOpen? "M3.75 6.75h16.5M3.75 12h16.5M12 17.25h8.25":"M6 18 18 6M6 6l12 12"} 
        />
    </svg>
  )
};

export default BurgerIcon;

CSS

.burger_icon{
    transition: all 500ms ease;
}

.burger_icon_path{
    transition: d 500ms ease;
}

Thank you.


Solution

  • Like @enxaneta commented, you need to align the number of commands in the path.

    Use the pointer-events attribute to control if an element should emit a click event or not.

    document.querySelector('svg').addEventListener('click', e => {
      let path = e.target.querySelector('.burger_icon_path');
      path.classList.toggle('open');
    });
    .burger_icon {
      transition: all 500ms ease;
      width: 100px;
    }
    
    .burger_icon_path {
      transition: all 500ms ease;
      d: path("M 3.75 6.75 L 20.25 6.75 M 3.75 12 L 20.25 12 M 12 17.25 L 20.25 17.25");
    }
    
    .burger_icon_path.open {
      d: path("M 5 6 L 19 20 M 5 20 L 12 13 M 12 13 L 19 6");
    }
    <svg xmlns="http://www.w3.org/2000/svg" fill="none"
      viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
      class="burger_icon" pointer-events="all">
      <path class="burger_icon_path" stroke-linecap="round" 
        stroke-linejoin="round" pointer-events="none" />
    </svg>