检测鼠标悬停在哪个元素上并传递给函数

Detect which element is moused over and pass to function

我正在使用 greensock 为 svg 剪辑路径设置动画,它非常适合使用一个剪辑路径和硬编码变量。现在我需要添加更多的剪辑路径,并且我需要每一个都独立地制作动画。所以我需要构建某种函数来检测哪个圆被鼠标悬停/移出,然后调用时间轴,向它传递正确的参数(剪辑路径和覆盖圆)。我确定我可以用 'this' 做到这一点,但我仍然处于 'this' 让我的大脑融化的地步。这是我正在使用的代码笔。

http://codepen.io/kathryncrawford/pen/JYvdzx

HTML

  <svg class="svg-graphic" width="500" height="500" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs>
  <clipPath id="clippath">
  <circle id="clip1" cx="200" cy="200" r="2.5"/>
  <circle id="clip2" cx="400" cy="200" r="3.2"/>  
  </clipPath>
</defs>
<image class="svg-image1" xlink:href="http://lorempixel.com/300/300/" width="300" height="300" x="80" y="80"/>
<circle id="circle1"  fill="#CC66FF" cx="200" cy="200" r="30"/>

<image class="svg-image2" xlink:href="http://lorempixel.com/300/300/" width="300" height="300" x="380" y="80"/>
<circle id="circle2" fill="#CC66FF" cx="400" cy="200" r="30"/>

JS

var clip = document.getElementById("clip1");
var circles = document.getElementById("circle1");

circles.addEventListener("mouseenter", expand);
circles.addEventListener("mouseleave", contract);

var tl = new TimelineMax({paused: true});
tl.to(clip, 0.5, {
    attr: {
      r: 120
    },
    transformOrigin: "50% 50%",
    ease: Power4.easeInOut
  })
  .to(circles, 0.5, {alpha:0, ease:Power4.easeInOut}, '-0.1');

function expand() {
  tl.play();
}

function contract() {
  tl.reverse();
}

好吧,this 是我分叉你的笔所创造的。

变化如下:

  • HTML 中,我删除了每个 circle [=115] 上设置的唯一 ID =] 元素存在于 clipPath HTML 元素中,即 clipPath 的子元素。相反,我给所有这些 circle 标签一个 clip class.
  • 作为所述 clipPath 兄弟姐妹的其他 circle 元素,即与 clipPath 元素处于同一级别的元素,已被赋予 circle class.
  • 至于image元素,我也做过类似的事情。从它们中删除了唯一的 ID,而是给它们一个通用的 svg-image class.
  • 这 HTML 完成了。
  • 在 HTML 中,因为唯一的 ID 已被删除,例如 #circle1#circle2#svg-image1#svg-image2,我也从 CSS 中删除了它们,而是应用了与新创建的 classes 完全相同的规则,即 .circle.svg-image 分别。
  • JavaScript中,clipcircle元素以及clip个元素的总数在前分别存储在变量 clipscirclesnumClips 中。
  • 最初创建的 timelines 也是一个空数组。
  • 然后会启动一个循环,它会一直上升到 numClips 的长度,它会做两件事:
    • createTimeline 顾名思义,应该创建一个 TimelineMax 实例,它看起来类似于您之前拥有的实例,即它添加了两个补间,一个用于动画 opacity当前 circle 元素(记住,我们在一个循环中,我们通过使用 circles[i] 获得当前 circle 元素的引用),另一个用于动画 r当前 clip 元素。
    • assignListeners 用于监听每个 circle 元素上的 mouseentermouseleave 事件。
  • 最后,expandcollapse 方法用于播放或倒转当前时间轴实例。 (同样,我们有 timeline 的参考,应该在悬停或离开时使用 timelines[i] 参考播放。

HTML:

<svg class="svg-graphic" width="500" height="500" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" version="1.1">
  <defs>
    <clipPath id="clippath">
      <circle class="clip" cx="200" cy="200" r="20" />
      <circle class="clip" cx="400" cy="200" r="20" />
      <circle class="clip" cx="600" cy="200" r="20" />
    </clipPath>
  </defs>
  <image class="svg-image" xlink:href="http://lorempixel.com/300/300/" width="300" height="300" x="80" y="80" />
  <circle class="circle" fill="#CC66FF" cx="200" cy="200" r="20" />
  <image class="svg-image" xlink:href="http://lorempixel.com/300/300/" width="300" height="300" x="380" y="80" />
  <circle class="circle" fill="#CC66FF" cx="400" cy="200" r="20" />
  <image class="svg-image" xlink:href="http://lorempixel.com/300/300/" width="300" height="300" x="680" y="80" />
  <circle class="circle" fill="#CC66FF" cx="600" cy="200" r="20" />
</svg>

CSS:

*{
    box-sizing: border-box;
}

body{
    margin: 0;
    padding: 0  
}

.circle{        
  position: absolute;
  margin: 0;
  z-index: 1;
  clip-path: url("#clippath");
}

.svg-image {
  z-index: 3;
  clip-path: url(#clippath);
}

svg{
    overflow: visible;
}

.svg-graphic {
  position: absolute;
}

.imgContainer {
  position: relative;
  width: 800px;
  height: 800px;
}

JavaScript:

var clips = document.getElementsByClassName('clip');
var circles = document.getElementsByClassName('circle');
var numClips = clips.length;
var timelines = [];

for (var i = 0; i < numClips; i += 1) {
  createTimeline(i);
  assignListeners(i);
}

function createTimeline(i) {
  var timeline = new TimelineMax({ paused: true });
  timeline.to(circles[i], 0.6, { opacity: 0, ease: Expo.easeInOut }, 0);
  timeline.to(clips[i], 0.6, {
    attr: { r: 120 },
    transformOrigin: '50% 50%',
    ease: Expo.easeInOut
  }, 0.1);
  timelines[i] = timeline;
}

function assignListeners(i) {
  (function(i) {
    circles[i].addEventListener('mouseenter', function(e) { expand(e, i); }, false);
    circles[i].addEventListener('mouseleave', function(e) { contract(e, i); }, false);
  }(i));
}

function expand(e, i) { timelines[i].play(); }
function contract(e, i) { timelines[i].reverse(); }

希望对您有所帮助。