如何获得 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
选择器。
您可以通过分别访问previousElementSibling
和nextElementSibling
来获取当前元素的上一个和下一个兄弟。
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 正方形。通过简单地在 button
和 svg
上使用 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/
首先,我对您的
- 我给最上面的
一个id="ThePage",这样我就可以在js代码中避免它。
- 我在包含矩形的
上设置了 class="button",而不是在 "sub-level" 矩形上设置了它。
- 我向按钮形状组内的元素添加了 pointer-events="none"。当您将鼠标悬停在
元素上时,即使光标仍在组内,它也会触发 mouseout。此指针事件设置会停止该行为,但现在您无法 select/copy 文本。那可能就好了。
- 在 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 可以读取的元数据。形状数据字段、用户定义的单元格、图层、文本格式和其他信息等内容存储在这些标签中。
我正在尝试解决一个非常简单的问题:两个元素;一个按钮和一个矩形。当您将鼠标悬停在按钮上时,矩形会更改填充颜色。我试过 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
选择器。
您可以通过分别访问previousElementSibling
和nextElementSibling
来获取当前元素的上一个和下一个兄弟。
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 正方形。通过简单地在 button
和 svg
上使用 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/
首先,我对您的
- 我给最上面的
一个id="ThePage",这样我就可以在js代码中避免它。 - 我在包含矩形的
上设置了 class="button",而不是在 "sub-level" 矩形上设置了它。 - 我向按钮形状组内的元素添加了 pointer-events="none"。当您将鼠标悬停在
元素上时,即使光标仍在组内,它也会触发 mouseout。此指针事件设置会停止该行为,但现在您无法 select/copy 文本。那可能就好了。 - 在 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 可以读取的元数据。形状数据字段、用户定义的单元格、图层、文本格式和其他信息等内容存储在这些标签中。