Trigger Tween for individually hovered over SVG hexagons

75 Views Asked by At

I want the Tween animation to be triggered for the hexagon you are hovering over only. At the moment only the top hexagon triggers the blurred reddish outline animation around the hexagon.

Each individual hexagon should have the filter applied to itself only.

Thanks in advance for advice.

https://codepen.io/daneli84/pen/OJVZmeJ

HTML

    <svg viewBox="0 0 100 100">
  <defs>
         <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-1">
            <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
            <feGaussianBlur stdDeviation="0" class="flag-blur" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
            <feColorMatrix values="0 0 0 0 1   0 0 0 0 0   0 0 0 0 0  0 0 0 0.4 0" in="shadowBlurOuter1" type="matrix" result="shadowMatrixOuter1"></feColorMatrix>
            <feMerge>
                <feMergeNode in="shadowMatrixOuter1"></feMergeNode>
                <feMergeNode in="SourceGraphic"></feMergeNode>
            </feMerge>
        </filter>

    <g id="pod">
      <polygon stroke="#000000" stroke-width="1" points="5,-9 -5,-9 -10,0 -5,9 5,9 10,0" />
    </g>

        <!-- a transparent grey drop-shadow that blends with the background colour -->

  </defs>

  <g class="pod-wrap" ">
    <use xlink:href="#pod" transform="translate(50, 41)" class="flag" />
    <use xlink:href="#pod" transform="translate(35, 50)" class="flag"  />
    <use xlink:href="#pod" transform="translate(65, 50)" class="flag" />
    <use xlink:href="#pod" transform="translate(50, 59)" class="flag"  />
  </g>
</svg>

<a href="http://www.mathopenref.com/coordpolycalc.html" target="_blank">point calculator</a>

CSS

/* grid styling */
use {
  transition: 0.1s;
  cursor: pointer;
  fill: transparent;
}

use {filter: url(#filter-1);}




/* other styling */
svg {
  width: 700px;
  flex: 1;
}
body {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  margin: 0;
  height: 100vh;
  font-weight: 700;
  font-family: sans-serif;
}
a {
  color: #ccc;
  padding: 10px;
  text-decoration: none;
  transition: color 0.4s;
}

JS

// 
var flagBlur = document.querySelector('.flag-blur');
var flag = document.querySelector('.flag');



function startPage() {

  // 
  flag.onmouseover = function() {
    TweenMax.to(flagBlur, 0.9, {
      attr:{stdDeviation: 0.9},
      ease: Power1.easeInOut
    });
  };

  flag.onmouseleave = function() {
    TweenMax.to(flagBlur, 0.35, {
      attr:{stdDeviation: 0},
      ease: Power1.easeInOut
    });
  };
}

startPage();
2

There are 2 best solutions below

0
On BEST ANSWER

There are 2 corrections:

  1. Use document.querySelectorAll(".flag") to add a listener on all four hexagons.

  2. Use a separate class for the blur filter and add/remove it to the hexagon you are interacting with. Also remove transition from use

Check the code below:

// переменные
var flagBlur = document.querySelector('.flag-blur');
var flags = document.querySelectorAll('.flag');

// наведение курсора на флаги
function startPage() {
  flags.forEach(flag => {
    flag.onmouseover = function() {
      flag.classList.add('filter-class')
      TweenMax.fromTo(flagBlur, 0.9, {
        attr: {
          stdDeviation: 0
        }
      }, {
        attr: {
          stdDeviation: 0.9
        },
        ease: Power1.easeInOut
      });
    }

    flag.onmouseleave = function() {
      flag.classList.remove('filter-class')
    }
  })
}

startPage();
/* grid styling */
use {
  cursor: pointer;
  fill: transparent;
}

.filter-class {
  filter: url(#filter-1);
}

/* other styling */
svg {
  width: 700px;
  flex: 1;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  margin: 0;
  height: 100vh;
  font-weight: 700;
  font-family: sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js"></script>
<svg viewBox="0 0 100 100">
  <defs>
         <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-1">
            <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
            <feGaussianBlur stdDeviation="0" class="flag-blur" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
            <feColorMatrix values="0 0 0 0 1   0 0 0 0 0   0 0 0 0 0  0 0 0 0.4 0" in="shadowBlurOuter1" type="matrix" result="shadowMatrixOuter1"></feColorMatrix>
            <feMerge>
                <feMergeNode in="shadowMatrixOuter1"></feMergeNode>
                <feMergeNode in="SourceGraphic"></feMergeNode>
            </feMerge>
        </filter>
    
    <g id="pod">
      <polygon stroke="#000000" stroke-width="1" points="5,-9 -5,-9 -10,0 -5,9 5,9 10,0" />
    </g>
        
        <!-- a transparent grey drop-shadow that blends with the background colour -->
        
  </defs>
  
  <g class="pod-wrap">
    <use xlink:href="#pod" transform="translate(50, 41)" class="flag h1" />
    <use xlink:href="#pod" transform="translate(35, 50)" class="flag h2"  />
    <use xlink:href="#pod" transform="translate(65, 50)" class="flag h3" />
    <use xlink:href="#pod" transform="translate(50, 59)" class="flag h4"  />
  </g>
</svg>

2
On

Use document.querySelectorAll('.flag') which returns an array of elements with that class instead of just the first one.

Then you can proceed to iterate over the array using .forEach() or some other method

the querySelector() function will only return the very first matching element, not all of them.

function startPage() {

  // 
  document.querySelectorAll(".flag").forEach(function(flag){ 
    flag.onmouseover = function() {
     TweenMax.to(flagBlur, 0.9, {
       attr:{stdDeviation: 0.9},
       ease: Power1.easeInOut
     });
   };

   flag.onmouseleave = function() {
     TweenMax.to(flagBlur, 0.35, {
       attr:{stdDeviation: 0},
       ease: Power1.easeInOut
     });
    };

  });
}