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

标签 javascript svg mouseover gsap

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

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 是我通过 fork 你的笔能够创建的。

以下是发生的变化:

  • HTML 中,我删除了 clipPath 内每个 circle HTML 元素上设置的唯一 ID> HTML 元素,即 clipPath 的子元素。相反,我为所有这些 circle 标签赋予了一个 clip 类。
  • 其他 circle 元素是所述 clipPath 的同级元素,即与 clipPath 元素位于同一级别,已被赋予 类。
  • 至于 image 元素,我也做了类似的事情。从中删除了唯一的ID,并为它们提供了一个通用的svg-image类。
  • 这是 HTML 完成的。
  • 在 HTML 中,由于唯一的 ID 已被删除,例如 #circle1#circle2#svg-image1#svg-image2,我也将它们从 CSS 中删除,并在新创建的类(即 )上应用了完全相同的规则。分别是 Circle.svg-image
  • JavaScript 中,首先是 clipcircle 元素以及 clip 元素的总数分别存储在变量 clipscirclesnumClips 中。
  • 最初还创建了一个空的时间线数组。
  • 然后将启动一个循环,该循环一直持续到 numClips 的长度,并执行以下两件事:
    • createTimeline 顾名思义,应该创建一个 TimelineMax 实例,它看起来与您之前的实例类似,即它添加了两个补间,一个用于为 制作动画当前 circle 元素上的 >opacity (请记住,我们处于循环内部,并且通过使用 circles 获得了当前 circle 元素的引用[i]),另一个用于为当前 clip 元素的 r 制作动画。
    • assignListeners 用于监听每个 circle 元素上的 mouseentermouseleave 事件。
  • 最后,expandcollapse 方法用于播放或反转当前时间轴实例。 (同样,我们使用 timelines[i] 引用来获取悬停或移出时应播放的 timeline 的引用)。

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(); }

希望这有帮助。

关于javascript - 检测鼠标悬停在哪个元素上并传递给函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33423170/

相关文章:

android - NGraphics 在 Xamarin Droid 上渲染 SVG 路径结果不佳

javascript - 从值到值到原始值无限地动画 SVG?

带有图像的 WPF 按钮触发鼠标悬停以更改图像

jquery - 在 jquery 中指向元素

javascript - react map 不渲染

javascript - $(this).val() 返回不正确的值 IE8

jquery - 使用 slideToggle() 时,preventDefault() 不会阻止移动设备上的 SVG 加载

javascript - 正则表达式删除所有以特殊字符开头的字符串

javascript - 如何创建 jquery 模态弹出窗口?

javascript - 鼠标悬停时更改字体,第二次悬停时恢复字体