【问题标题】:Hovering over label to affect <circle> element in JS将鼠标悬停在标签上以影响 JS 中的 <circle> 元素
【发布时间】:2021-05-06 19:50:53
【问题描述】:

我正在一个内部站点中制作一些小图表,并且想在&lt;label&gt; 悬停在上面时更改&lt;circle&gt; 元素的不透明度。

我最初想在 CSS 中完成这一切,但没有选择器可以让我定位 circle,并且没有匹配的类。

我希望能够在纯 JS 中做到这一点(as I've seen similar using jQuery)

悬停的目标如下所示(黄色表示):

因此,如果将任一项目悬停在(圆圈或标签)上方,则相应项目将变为 100% 不透明度。

从左到右的圆圈项目有一个固定的顺序是1n从上到下匹配标签。

body{
min-height: 300px
}
.container {
  display: flex;
  flex-direction: row;
  margin-bottom: 2em !important;
}

.container>* {
  align-self: center;
}

.dataset {
  max-width: 100%;
  width: 100%;
}

.dataset svg {
  overflow: visible;
  max-width: 25em;
  max-height: 25em;
}

fieldset {
  order: 2;
  margin-left: auto;
  border-width: 5px 0 0 0;
  border-color: #CCC;
  border-style: solid;
  font-size: 0.9em;
  max-width: 30%;
  width: 100%;
}

fieldset legend {
  font-size: 1em;
  font-family: sans-serif;
  font-weight: bold;
  padding: 0 1em;
  margin: 0 0 0.5em -1em;
}

fieldset label {
  display: block;
  text-indent: -2.5em;
  margin: 0.5em 0 0 2.5em;
  line-height: 1.5em;
}

fieldset label span {
  height: 1em;
  width: 1em;
  margin-right: 1em;
  border-radius: 0.2em;
  display: inline-block;
}
<figure>
  <div class="container">
    <div class="dataset">
      <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
        <g class="data-container">
          <g class="data-item">
            <circle r="1.25" cx="5" cy="88.8" fill="hsl( 18, 98%, 0% )"></circle>
            <circle r="1.25" cx="20.83" cy="0"fill="hsl( 18, 98%, 10% )"></circle>
            <circle r="1.25" cx="36.6" cy="77.77" fill="hsl( 18, 98%, 20% )"></circle>
            <circle r="1.25" cx="52.5" cy="11.1" fill="hsl( 18, 98%, 30% )"></circle>
            <circle r="1.25" cx="68.3" cy="66.6" fill="hsl( 18, 98%, 40% )"></circle>
            <circle r="1.25" cx="84.16" cy="22.2" fill="hsl( 18, 98%, 50% )"></circle>
          </g>
        </g>
      </svg>
    </div>
    <fieldset>
      <legend>Legend</legend>
      <label><span style="background:hsl( 18, 98%, 0% );"></span>Dot 1</label>
      <label><span style="background:hsl( 18, 98%, 10% );"></span>Dot 2</label>
      <label><span style="background:hsl( 18, 98%, 20% );"></span>Dot 3</label>
      <label><span style="background:hsl( 18, 98%, 30% );"></span>Dot 4</label>
      <label><span style="background:hsl( 18, 98%, 40% );"></span>Dot 5</label>
      <label><span style="background:hsl( 18, 98%, 50% );"></span>Dot 6</label>
    </fieldset>
  </div>
</figure>

【问题讨论】:

  • 您尝试了哪些 JavaScript?为什么不自己将 jQuery 移植到 JS 中呢?你被困在哪里了?

标签: javascript html css


【解决方案1】:

这样的事情应该可以工作:

const circles = [...document.getElementsByTagName('circle')];
const labels = [...document.getElementsByTagName('label')];
circles.forEach((circle, index) => {
    circle.addEventListener('mouseover', e => {
        labels[index].style.backgroundColor = 'red'
    })
    circle.addEventListener('mouseout', e => {
        labels[index].style.backgroundColor = ''
    })
})

发生了什么:

const circles = [...document.getElementsByTagName('circle')];

获取所有circle 元素并将它们存储在一个数组中(getElementsByTagName 返回一个HTMLCollection]。对labels 执行相同操作。

然后我们要做的就是循环并设置我们的事件监听器。

注意事项:

  1. document.getElementsByTagName('circle') 等工作,因为这是一个简单的例子;你显然需要更精确地定位你的选择器,可能使用类似querySelectorAll() (https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll)的东西
  2. 这假设每个&lt;circle&gt; 以相同的顺序对应每个&lt;label&gt;

编辑以影响所有标签

只需遍历labels 数组并检查索引:

circle.addEventListener('mouseover', e => {
    labels.forEach((label, index2) => {
        if (index === index2) {
            label.classList.add('active');
        } else {
            label.classList.remove('active')
        }
    })
})
circle.addEventListener('mouseout', e => {
    labels.forEach(label => label.classList.remove('active'))
})

在这里,active 类将不透明度设置为 100%(默认为 50%)。 mouseout 更简单,因为我们只需要删除类。

从技术上讲,在这里你根本不需要 mouseout 回调,假设你总是想让一个(最后一个悬停在上面)处于活动状态

【讨论】:

  • 谢谢@divillysausages!我正在尝试重新处理您的 sn-p,以便未突出显示的所有内容(因此在示例中圈出 #5 和标签 #5)其余部分的不透明度为 50%。如果没有悬停,则全部 100%
  • 轻松搞定;在您的 mouseover 方法中,只需遍历 labels 数组。如果数组的索引是圆的索引,那么它是活动的,否则不是。我会使用类而不是直接修改它
  • 反之(悬停在label 上会突出显示circle),几乎是一样的
【解决方案2】:

我在圆圈旁边添加了一个rect 元素,并制作了正确的 jQuery 以很好地定位它。

还添加了这个 CSS

/* ADDED */
label{
 position:relative;
}
label:hover::after{
  content:"";
  background:grey;
  width: 100%;
  height: 100%;
  position: absolute;
  left: -3em;
  top: -2px;
  z-index: -1;
}
rect{
  fill:grey;
}

演示

var r;
var cx;
var cy;

$("label").hover(function(){
  var i = $(this).index() - 1;
  r = $("svg circle:eq("+i+")").attr("r");
  cx = $("svg circle:eq("+i+")").attr("cx") - 2;
  cy = $("svg circle:eq("+i+")").attr("cy") - 2;
  
  $("svg rect").attr("r", r);
  $("svg rect").attr("x", cx);
  $("svg rect").attr("y", cy);
  $("svg rect").attr("width", "4");
  $("svg rect").attr("height", "4");
}, function(){
  $("svg rect").attr("width", "0");
  $("svg rect").attr("height", "0");
});
body{
min-height: 300px
}
.container {
  display: flex;
  flex-direction: row;
  margin-bottom: 2em !important;
}

.container>* {
  align-self: center;
}

.dataset {
  max-width: 100%;
  width: 100%;
}

.dataset svg {
  overflow: visible;
  max-width: 25em;
  max-height: 25em;
}

fieldset {
  order: 2;
  margin-left: auto;
  border-width: 5px 0 0 0;
  border-color: #CCC;
  border-style: solid;
  font-size: 0.9em;
  max-width: 30%;
  width: 100%;
}

fieldset legend {
  font-size: 1em;
  font-family: sans-serif;
  font-weight: bold;
  padding: 0 1em;
  margin: 0 0 0.5em -1em;
}

fieldset label {
  display: block;
  text-indent: -2.5em;
  margin: 0.5em 0 0 2.5em;
  line-height: 1.5em;
}

fieldset label span {
  height: 1em;
  width: 1em;
  margin-right: 1em;
  border-radius: 0.2em;
  display: inline-block;
}
/* ADDED */
label{
 position:relative;
}
label:hover::after{
  content:"";
  background:grey;
  width: 100%;
  height: 100%;
  position: absolute;
  left: -3em;
  top: -2px;
  z-index: -1;
}
rect{
  fill:grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<figure>
  <div class="container">
    <div class="dataset">
      <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
        <g class="data-container">
          <g class="data-item">
            <rect></rect>
            <circle r="1.25" cx="5" cy="88.8" fill="hsl( 18, 98%, 0% )"></circle>
            <circle r="1.25" cx="20.83" cy="0"fill="hsl( 18, 98%, 10% )"></circle>
            <circle r="1.25" cx="36.6" cy="77.77" fill="hsl( 18, 98%, 20% )"></circle>
            <circle r="1.25" cx="52.5" cy="11.1" fill="hsl( 18, 98%, 30% )"></circle>
            <circle r="1.25" cx="68.3" cy="66.6" fill="hsl( 18, 98%, 40% )"></circle>
            <circle r="1.25" cx="84.16" cy="22.2" fill="hsl( 18, 98%, 50% )"></circle>
          </g>
        </g>
      </svg>
    </div>
    <fieldset>
      <legend>Legend</legend>
      <label><span style="background:hsl( 18, 98%, 0% );"></span>Dot 1</label>
      <label><span style="background:hsl( 18, 98%, 10% );"></span>Dot 2</label>
      <label><span style="background:hsl( 18, 98%, 20% );"></span>Dot 3</label>
      <label><span style="background:hsl( 18, 98%, 30% );"></span>Dot 4</label>
      <label><span style="background:hsl( 18, 98%, 40% );"></span>Dot 5</label>
      <label><span style="background:hsl( 18, 98%, 50% );"></span>Dot 6</label>
    </fieldset>
  </div>
</figure>

【讨论】:

    【解决方案3】:

    仅使用纯 CSS 的解决方案

    这可能不是您正在寻找的确切答案。

    我试图在不破坏 DOM 结构允许的情况下获得结果。也许它会为你工作。祝你好运。

    body {
      min-height: 300px
    }
    
    fieldset {
      position: relative;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: flex-end;
      padding-top: 9rem;
      padding-bottom: 9em;
      border: 0;
    }
    
    .dataset {
      display: flex;
      align-items: center;
      max-width: 70%;
      width: 70%;
      position: absolute;
      top: 0;
      left: 0;
      bottom: 0;
      max-height: 100%;
    }
    
    .dataset svg {
      overflow: visible;
      width: 100%;
      max-height: 100%;
      height: 100%;
    }
    
    .dataset svg circle{
      transition: .3s;
    }
    
    fieldset legend {
      font-size: 1em;
      font-family: sans-serif;
      font-weight: bold;
      padding: 0 1em;
      margin: 0 0 0.5em -1em;
    }
    
    fieldset label {
      display: block;
      margin: 0.5em 0 0 2.5em;
      line-height: 1.5em;
      max-width: 30%;
      width: 100%;
    }
    
    fieldset label:hover {
      opacity: .5;
    }
    fieldset label:nth-child(1):hover ~ .dataset circle:nth-child(1),
    fieldset label:nth-child(2):hover ~ .dataset circle:nth-child(2),
    fieldset label:nth-child(3):hover ~ .dataset circle:nth-child(3),
    fieldset label:nth-child(4):hover ~ .dataset circle:nth-child(4), 
    fieldset label:nth-child(5):hover ~ .dataset circle:nth-child(5), 
    fieldset label:nth-child(6):hover ~ .dataset circle:nth-child(6) {
      opacity: .5;
      fill: green;
      background-color: black;
    }
    
    fieldset label span {
      height: 1em;
      width: 1em;
      margin-right: 1em;
      border-radius: 0.2em;
      display: inline-block;
    }
    <figure>
      <fieldset>
        <label><span style="background:hsl( 18, 98%, 0% );"></span>Dot 1</label>
        <label><span style="background:hsl( 18, 98%, 10% );"></span>Dot 2</label>
        <label><span style="background:hsl( 18, 98%, 20% );"></span>Dot 3</label>
        <label><span style="background:hsl( 18, 98%, 30% );"></span>Dot 4</label>
        <label><span style="background:hsl( 18, 98%, 40% );"></span>Dot 5</label>
        <label><span style="background:hsl( 18, 98%, 50% );"></span>Dot 6</label>
        <div class="dataset">
          <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
              <g class="data-container">
                <g class="data-item">
                  <circle r="1.25" cx="5" cy="88.8" fill="hsl( 18, 98%, 0% )"></circle>
                  <circle r="1.25" cx="20.83" cy="0"fill="hsl( 18, 98%, 10% )"></circle>
                  <circle r="1.25" cx="36.6" cy="77.77" fill="hsl( 18, 98%, 20% )"></circle>
                  <circle r="1.25" cx="52.5" cy="11.1" fill="hsl( 18, 98%, 30% )"></circle>
                  <circle r="1.25" cx="68.3" cy="66.6" fill="hsl( 18, 98%, 40% )"></circle>
                  <circle r="1.25" cx="84.16" cy="22.2" fill="hsl( 18, 98%, 50% )"></circle>
                </g>
              </g>
            </svg>
        </div>
      </fieldset>
    </figure>

    【讨论】:

    • 我非常感谢这次尝试!我试图重用它但很难做到,因为我无法移动关闭fieldset
    猜你喜欢
    • 1970-01-01
    • 2020-01-03
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-14
    相关资源
    最近更新 更多