如何获得 javascript 鼠标悬停以突出显示 svg 文件中的其他元素(上下文更改)

How to get javascript mouseover to highlight other elements in an svg file (context change)

我正在尝试解决一个非常简单的问题:两个元素;一个按钮和一个矩形。当您将鼠标悬停在按钮上时,矩形会更改填充颜色。我试过 CSS,但出于某种原因我无法让“className:hover targetClass{}”工作. 主体来自 Visio,我尝试对其进行编辑(*编辑:删除了 visio 元数据):

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" 
width="8.26772in" height="11.6929in" viewBox="0 0 595.276 841.89" xml:space="preserve" color-interpolation-filters="sRGB" class="st3">

    <style type="text/css">
    <![CDATA[

        .st1 {fill:#5b9bd5;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5}
        .st2 {fill:#ffffff;font-family:Calibri;font-size:0.833336em}
        .st3 {fill:#FFFF00;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
        .button {fill:#5b9bd5;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5}
        .button:hover{fill: #FFFF00;}
    ]]>
    </style>

 <g id="ThePage">   
    <title>Page-1</title>

    <g id="shape2" transform="translate(283.465,-531.496)">
        <title>Multi-Attachment rectangle.2</title>
        <desc>Button text</desc>
        <rect x="0" y="799.37" width="56.6929" height="42.5197" class="button"/>
        <text x="5.25" y="823.63" class="st2" >Button text</text>   
    </g>

    <g id="shape1" transform="translate(255.118,-595.276)">
        <title>Multi-Attachment rectangle</title>
        <desc>Big box text</desc>
        <rect x="0" y="756.85" width="113.386" height="85.0394" class="st1"/>
        <text x="32.78" y="802.37" class="st2" >Big box text</text>     
    </g>
 </g>

</svg>

我尝试实现但失败的 javascript 代码是:

var javaButton = document.getElementsByClassName('button');

for (var i = 0; i < javaButton.length; i++) {
    javaButton[i].addEventListener('mouseover', mouseOverEffect);
    javaButton[i].addEventListener('mouseout', mouseOutEffect);
}

function mouseOverEffect() {
    this.classList.add("rect-highlight");
}

function mouseOutEffect() {
    this.classList.remove("rect-highlight");
}

其中 "rect-highlight" 在 svg 的 CSS 部分为:.rect-highlight {fill: #ec008c;}。 我知道这是有效的,因为如果我将鼠标悬停在按钮上,按钮会改变颜色,但是需要将上下文从 "this" 获取到另一个元素。我怎么做?

*编辑:删除了 visio 元数据

**编辑:添加代码正文

***编辑:添加了代码栅栏,这样 markdown 就不会吃掉我的代码。

不确定你的问题是什么,因为你没有提供示例 SVG,但如果你想突出显示相关元素,你可以使用 :hover 选择器。

您可以通过分别访问previousElementSiblingnextElementSibling来获取当前元素的上一个和下一个兄弟。

const showSiblings = (e) => toggleSiblings(e.target, true);
const resetSiblings = (e) => toggleSiblings(e.target, false);

Array.from(document.querySelectorAll('.box')).forEach(box => {
  box.addEventListener('mouseenter', showSiblings);
  box.addEventListener('mouseleave', resetSiblings);
});

function toggleSiblings(curr, visible) {
  let prev = curr.previousElementSibling;
  let next = curr.nextElementSibling;
  if (prev) {
    prev.classList.toggle('sib-prev', visible);
  }
  if (next) {
    next.classList.toggle('sib-next', visible);
  }
}
svg { background: #FF7F7F; }

.box { stroke-width: 4; cursor: pointer; }

.foo { fill: #4C4C7F; stroke: #00007F; }
.foo:hover { fill: #7F7FFF; }

.bar { fill: #7F7F4C; stroke: #7F7F00; }
.bar:hover { fill: #FFFF7F; }

.sib-prev.box {
  stroke: #FF0000;
}

.sib-next.box {
  stroke: #00FF00;
}
<svg width="260" height="196">
  <rect class="box foo" x="6" y="6" width="120" height="40" />
  <rect class="box bar" x="6" y="54" width="120" height="40" />
  <rect class="box foo" x="6" y="102" width="120" height="40" />
  <rect class="box bar" x="6" y="150" width="120" height="40" />
  
  <rect class="box bar" x="134" y="6" width="120" height="40" />
  <rect class="box foo" x="134" y="54" width="120" height="40" />
  <rect class="box bar" x="134" y="102" width="120" height="40" />
  <rect class="box foo" x="134" y="150" width="120" height="40" />
</svg>

当您确实需要 javascript 解决方案时,请使用 javascript 寻找答案。

然而,这个答案显示了一个使用 vanilla CSS 的简单非 JS 解决方案。您会看到一个按钮和一个 SVG 正方形。通过简单地在 buttonsvg 上使用 CSS :hover:focus,正方形的颜色改变 4 次...

/*
    CSS Selector Reference
    https://www.w3schools.com/cssref/css_selectors.asp
*/
svg       { fill: red; width: 100px  }
svg:hover { fill: purple }

button:hover + svg { fill: lime } /* + = immediate sibling selector */
button:focus + svg { fill: blue }
<button>hover, click and unfocus me</button>
<svg viewbox="0 0 100 100"><rect width="100" height="100" x="0" y="0" /></svg>

我想 fiddle 解决这个问题,因为我有兴趣使用从 Visio 导出的 SVG 做一些很酷的事情。正如其他张贴者所建议和展示的那样,可能有更优雅的方法来解决您的问题,但也许我的尝试无论如何都会有所帮助。

我想我已经创建了一个 jsFiddle,它可以满足您的需求。看一看: https://jsfiddle.net/visioguy/nv3ew0fh/

首先,我对您的 代码做了一些修改:

  1. 我给最上面的一个id="ThePage",这样我就可以在js代码中避免它。
  2. 我在包含矩形的 上设置了 class="button",而不是在 "sub-level" 矩形上设置了它。
  3. 我向按钮形状组内的元素添加了 pointer-events="none"。当您将鼠标悬停在 元素上时,即使光标仍在组内,它也会触发 mouseout。此指针事件设置会停止该行为,但现在您无法 select/copy 文本。那可能就好了。
  4. 在 jsFiddle 的单独 CSS 区域中有一些样式。

以下是 CSS 样式添加:

/* 
Make the SVG big enough to see and give
it a subtle color: 
*/
svg {
  background: whitesmoke;
  width: 500px;
  height: 500px;
}

/* 
Highlight direct <rect> children of any <g>
that has this class: 
*/
.rect-highlight > rect {
  fill: red;
}

这里是 javaScript。我使用 querySelectorAll 根据 CSS 规则查找形状。如果您将其他非按钮框添加到您的 ,此代码将找到它们并突出显示它们:

// Select all <g> elements that are classed as 'button':
let buttonShapes = document.querySelectorAll('.button');
console.log("buttonShapes: ", buttonShapes.length);

// Add the event handlers to all of these button shapes:
for(let buttonShape of buttonShapes) {
    buttonShape.addEventListener('mouseenter', mouseEnterEffect);
    buttonShape.addEventListener('mouseout'  , mouseOutEffect);
}

function mouseEnterEffect(){

    // Select all other <g> in the SVG that are not classed as button
    // and are not id'd as ThePage:
    let otherShapes = document.querySelectorAll('g:not(.button):not(#ThePage)');
    console.log("otherShapes:", otherShapes.length); 

    for(let g of otherShapes) {
        g.classList.add("rect-highlight");
    }

}

function mouseOutEffect(){

    // Select all shapes that are groups <g> and are classed
    // with "rect-highlight":
    let highlightShapes = document.querySelectorAll('g.rect-highlight');
    console.log("highlightShapes:", highlightShapes.length); 

    for(let g of highlightShapes) {
        g.classList.remove("rect-highlight");
    }  

}

最后一点:您可以删除 Visio 添加的所有额外元素和属性。基本上任何以 "v:" 开头的东西。如果您决定稍后将 svg 重新导入 Visio,这是 Visio 可以读取的元数据。形状数据字段、用户定义的单元格、图层、文本格式和其他信息等内容存储在这些标签中。