使用 svg 在外部多边形事件上触发内部多边形事件

trigger events on inner polygons on outer polygon event with svg

我有一个 svg,其中有多个片段由 sectors.The 个扇区组成,点击后切换 class 并更改颜色。我需要内部扇区在外部扇区的点击事件中点亮

Here 是 fiddle link 相同。

我尝试提供 classes,例如 herbalLvl1、herbalLvl2、herbalLvl3,这样我可以在点击 HerbalLvl2 或 HerbalLvl3 时触发 herbalLvl1 上的点击事件。但是这些扇区已经有一个 class,我需要这些扇区只有一个 class 来切换动态创建的 class,如下所示:

    var myclass=$(this).attr("class");
    var classarray=myclass.split(" ");
    var currentClass=classarray[0]; var thisClass=classarray[0];



var res=currentClass.split("clicked");
if(res.length==1)
    {
      $(this).removeClass(thisClass);
      $(this).addClass(currentClass+'clicked');
      console.log($(this).attr("class"));

    }
    else
    if(res.length==2)
    {
        console.log('2');

        $(this).removeClass(thisClass);
        $(this).addClass(res[0]);
        console.log($(this).attr("class"));
    }

如果我向多边形添加另一个 class,那么 $(this).addClass(res[0]); 将 return 不同的值,因为 class 以以下方式被删除:

第 Load:herbal 页 herbalLvl1

点击select:草本Lvl1 草本点击

点击取消select: herbalclicked herbalLvl1clicked

n 依此类推,因为新添加的 classes 被附加到最后。

除了应用多个 classes 之外,有没有办法在 select 外环上实现 selecting 内环。

编辑 (或第二个答案!)
由于去除select多边形的能力显然是必要的...

您会注意到 deselection 比 selection 稍微复杂一些。
为什么?

因为 select 也 select 就是 "parents".
但是 deselect may 不是 deselect 它的 parents 因为 maybe 另一个兄弟是 select编辑...

所以必须检查那个案例!

我在代码中加入了尽可能多的注释。
;)

你的鼠标会喜欢 This Fiddle

$("polygon").click(function() {

  var myclass = $(this).attr("class");
  var classarray = myclass.split(" ");
  var currentClass = classarray[0];

  // If the polygon clicked (the trigger) already has the "clicked" class ( Not a "UNIQUE" , see below for those )
  if ($(this).hasClass(currentClass + 'clicked') && $(this).attr("data-sub") != "UNIQUE") {
    console.log("already selected");

    // Remove the "clicked" class.
    $(this).removeClass(currentClass + 'clicked');

    // Get the class and branch.
    var thisSub = $(this).attr("data-sub");
    var thisLevel = $(this).attr("data-level");

    // Filter elements based on level and sub branch.
    var foundAnother = false;
    var foundEl = [];

    // Filter function for each element of the current class.
    $("." + currentClass).filter(function() {

      // If the element has the same sub AND the same level as the current class.
      if (($(this).attr("data-sub") == thisSub) && ($(this).attr("data-level") == thisLevel)) {

        // If this element has the "clicked" class ( So another element that has same sub and level AND that was aleready clicked ).
        if ($(this).hasClass(currentClass + 'clicked')) {
          console.log("found another");
          foundAnother = true;

          // May be many elements... So push it to an array.
          foundEl.push($(this));
        }
      }

      // Keeping anyway all elements of the same sub in this filter. The found elements will be re-clicked later.
      if ($(this).attr("data-sub") == thisSub) {
        return true;
      }

      // For all element kept in the above, remove the "clicked" class. --- End filter function.
    }).removeClass(currentClass + "clicked");

    // Another check on each current class -> If there is element still having the "clicked" class except the "UNIQUE", set a flag.
    var checkAll = false;
    $("." + currentClass).each(function() {
      if ($(this).hasClass(currentClass + "clicked") && $(this).attr("data-sub") != "UNIQUE") {
        checkAll = true;
      }
    });

    // If flag was'n raised in the above, remove the "clicked" class for ALL elements.
    if (!checkAll) {
      $("." + currentClass).removeClass(currentClass + "clicked");
    }

    // If some elements were found having the same sub and level as the trigger.
    if (foundAnother) {
      console.log(foundEl.length);

      // Click them all !! (Kind of a short cut here!)
      for (i = 0; i < foundEl.length; i++) {
        foundEl[i].click();
      }
    }

    // This else is for "UNIQUE" elements that have "clicked" class. So if a  "UNIQUE clicked" element is clicked -> All the ellements having this current class should be unclicked.
  } else if ($(this).hasClass(currentClass + 'clicked') && $(this).attr("data-sub") == "UNIQUE") {
    console.log("UNIQUE FOUND");
    $("." + currentClass).removeClass(currentClass + "clicked");

    // Last else. If the trigger was not already clicked before.
  } else {

    // Add the appropriate "clicked" class.
    $(this).addClass(currentClass + 'clicked');

    // Markup error check... Since maybe it's the very first click it gets, have to check if it has all the required data atributes.
    if (typeof($(this).attr("data-level")) == "undefined") {
      console.log("data-level is missing");
      return;
    }
    if (typeof($(this).attr("data-sub")) == "undefined") {
      console.log("data-sub is missing");
      return;
    }

    // Get the class and branch from this target.
    var thisSub = $(this).attr("data-sub");
    var thisLevel = $(this).attr("data-level");

    // Filter elements based on level and sub branch.
    $("." + currentClass).filter(function() {
      if ((($(this).attr("data-sub") == thisSub) || ($(this).attr("data-sub") == "UNIQUE")) && ($(this).attr("data-level") < thisLevel)) {
        return true;
      }
    }).addClass(currentClass + "clicked");
  }
});





第一个回答 (不包括select)


如果您使用另一个属性而不是 class 来区分 "level" 和 "branch" 会怎么样?

像这样:<polygon class='herbal' data-level="2" data-sub="A"...
所以每个不同的字母 "branches"...
当 "level" 只有一个 "branch" 时,将 data-sub 设置为 "UNIQUE"`。

看看这个updated Fiddle

代码:

$("polygon").click(function() {

  var myclass = $(this).attr("class");
  var classarray = myclass.split(" ");
  var currentClass = classarray[0];

  // Add the appropriate "clicked" class.
  $(this).addClass(currentClass + 'clicked');

  // Markup error check.
  if (typeof($(this).attr("data-level")) == "undefined") {
    console.log("data-level is missing");
    return;
  }
  if (typeof($(this).attr("data-sub")) == "undefined") {
    console.log("data-sub is missing");
    return;
  }

  // Get the class and branch.
  var thisSub = $(this).attr("data-sub");
  var thisLevel = $(this).attr("data-level");

  // Filter elements based on level and sub branch.
  $("." + currentClass).filter(function() {
    if ((($(this).attr("data-sub") == thisSub) || ($(this).attr("data-sub") == "UNIQUE")) && ($(this).attr("data-level") < thisLevel)) {
      return true;
    }
  }).addClass(currentClass + "clicked");
});