:当 svg 在外部文件中时,悬停不在 svg 上工作
:hover not working on svg when svg is in external file
所以我正在学习 SVG 动画。
基本上我想做的就是在鼠标悬停时更改圆圈的颜色。
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 437.1 294.4" style="enable-background:new 0 0 437.1 294.4;" xml:space="preserve">
<style type="text/css">
.st0:hover {
fill: red;
}
</style>
<g id="Circle">
<path class="st0" d="M291.3,147.4c0,77-62.4,139.4-139.4,139.4S12.5,224.4,12.5,147.4C12.6,70.4,75,8,151.9,8
C228.9,8,291.3,70.4,291.3,147.4"/>
</g>
</svg>
当 svg 代码在 html 文件中时,这完全符合预期。
但是,当我将它放入 svg 文件并使用 img 标签调用它时,悬停效果不再有效。
<img class="logo" src="url/logo.svg">
有没有办法在不将 svg 代码嵌入 html 的情况下做到这一点?
谢谢!
无法使用 <img>
标签完成。参见:Styling And Animating SVGs With CSS。在本文页面底部附近有一个 table,其中列出了每种 SVG 嵌入技术(即 img、对象等)的优缺点。我在这里转载了 table:
| | CSS Interactions | CSS Animations | SVG Animations |
|:--------------------:|:----------------:|:--------------:|:--------------:|
| <img> | No | Yes* | Yes |
| CSS background image | No | Yes* | Yes |
| <object> | Yes* | Yes* | Yes |
| <iframe> | Yes* | Yes* | Yes |
| <embed> | Yes* | Yes* | Yes |
| <svg> (inline) | Yes | Yes | Yes |
*仅在 <svg>
内
我把这个答案写成 的一种应用版本。以下代码段显示了您可以如何利用的不同形式 <svg>
以及它们在每种情况下的功能。
主要要点是,根据上下文,<svg>
可能会或可能不会从顶级文档接收样式规则,并且可能会或可能不会从顶级文档接收交互事件(:hover
).
我建议您查看下面的代码片段以查看正在运行的应用程序:
const someSVG = `
<svg width="128" height="128" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<style>
.interactive.from-svg {
fill: red;
transition: fill 200ms ease;
}
.interactive.from-svg:hover {
fill: blue;
}
.animated.from-svg{
animation: 3s infinite alternate changecolor;
}
@keyframes changecolor{
from {
fill: green;
}
to {
fill: purple;
}
}
</style>
<circle class="interactive from-doc" cx="25" cy="25" r="25"></circle>
<circle class="animated from-doc" cx="75" cy="25" r="25"></circle>
<circle class="interactive from-svg" cx="25" cy="75" r="25"></circle>
<circle class="animated from-svg" cx="75" cy="75" r="25"></circle>
</svg>
`;
const dataUri = `data:image/svg+xml;base64,${btoa(someSVG)}`;
const imgContainer = document.getElementById("img-container"),
img = document.createElement("img");
imgContainer.appendChild(img);
img.src = dataUri;
const backgroundImageContainer = document.getElementById("background-image-container"),
backgroundImage = document.createElement("div");
backgroundImageContainer.appendChild(backgroundImage);
backgroundImage.style.width = "128px";
backgroundImage.style.height = "128px";
backgroundImage.style.backgroundImage = `url(${dataUri})`;
const iframeContainer = document.getElementById("iframe-container"),
iframe = document.createElement("iframe");
iframeContainer.appendChild(iframe);
iframe.src = dataUri;
main {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
section {
flex-basis: 50%;
flex-grow: 1;
flex-shrink: 0;
}
.interactive.from-doc {
fill: red;
transition: fill 200ms ease;
}
.interactive.from-doc:hover {
fill: blue;
}
.animated.from-doc {
animation: 3s infinite alternate changecolor;
}
@keyframes changecolor {
from {
fill: green;
}
to {
fill: purple;
}
}
li.pro {
color: green;
}
li.con {
color: red;
}
<h1><code><svg></code> Usage Comparison</h1>
<main>
<section id="external">
<h2><code><img></code></h2>
<div id="img-container"></div>
<pre><code><img src="some.svg"></code></pre>
<ul>
<li class="con">Does not receive <strong>any</strong> style from top level document</li>
<li class="con">Does not utilize CSS Interactions such as <code>:hover</code></li>
<li class="pro">Will use CSS Animations if they are defined within the svg element's style</li>
</ul>
</section>
<section>
<h2><code>background-image</code></h2>
<div id="background-image-container"></div>
<pre><code>
<style>
.rule{
background-image: url(some.svg);
}
</style>
<div class="rule"></div>
</code></pre>
<ul>
<li class="con">Does not receive <strong>any</strong> style from top level document</li>
<li class="con">Does not utilize CSS Interactions</li>
<li class="pro">Will use CSS Animations if they are defined within the svg element's style</li>
</ul>
</section>
<section>
<h2><code><iframe></code></h2>
<div id="iframe-container"></div>
<pre><code><iframe src="some.svg"></code></pre>
<ul>
<li class="con">Does not receive <strong>any</strong> style from top level document</li>
<li class="pro">Will use CSS Interactions if they are defined within the svg element's style</li>
<li class="pro">Will use CSS Animations if they are defined within the svg element's style</li>
</ul>
</section>
<section>
<h2>Inline <code><svg></code></h2>
<svg width="128" height="128" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<style>
.interactive.from-svg {
fill: red;
transition: fill 200ms ease;
}
.interactive.from-svg:hover {
fill: blue;
}
.animated.from-svg{
animation: 3s infinite alternate changecolor;
}
@keyframes changecolor{
from {
fill: green;
}
to {
fill: purple;
}
}
</style>
<circle class="interactive from-doc" cx="25" cy="25" r="25"></circle>
<circle class="animated from-doc" cx="75" cy="25" r="25"></circle>
<circle class="interactive from-svg" cx="25" cy="75" r="25"></circle>
<circle class="animated from-svg" cx="75" cy="75" r="25"></circle>
</svg>
<pre><code><svg>...</svg></code></pre>
<ul>
<li class="pro">Receives <strong>all</strong> style rules from top level document</li>
<li class="pro">Will use CSS Interactions if they are defined within the svg element's style</li>
<li class="pro">Will use CSS Animations if they are defined within the svg element's style</li>
</ul>
</section>
</main>
<img>
<img src="some.svg">
- 未从顶级文档
接收任何样式
- 不利用 CSS 交互,例如
:hover
- 将使用 CSS 动画,如果它们是在 svg 元素的样式中定义的
background-image
<style>
.rule {
background-image: url(some.svg);
}
</style>
<div class="rule"></div>
- 未从顶级文档
接收任何样式
- 不利用 CSS 互动
- 将使用 CSS 动画,如果它们是在 svg 元素的样式中定义的
<iframe>
<iframe src="some.svg"></iframe>
- 没有从顶级文档中接收到任何样式
- 将使用 CSS 交互,如果它们是在 svg 元素的样式中定义的
- 将使用 CSS 动画,如果它们是在 svg 元素的样式中定义的
内联<svg>
<svg>...</svg>
- 从顶级文档接收所有样式规则
- 将使用 CSS 交互,如果它们是在 svg 元素的样式中定义的
- 将使用 CSS 动画,如果它们是在 svg 元素的样式中定义的
所以我正在学习 SVG 动画。
基本上我想做的就是在鼠标悬停时更改圆圈的颜色。
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 437.1 294.4" style="enable-background:new 0 0 437.1 294.4;" xml:space="preserve">
<style type="text/css">
.st0:hover {
fill: red;
}
</style>
<g id="Circle">
<path class="st0" d="M291.3,147.4c0,77-62.4,139.4-139.4,139.4S12.5,224.4,12.5,147.4C12.6,70.4,75,8,151.9,8
C228.9,8,291.3,70.4,291.3,147.4"/>
</g>
</svg>
当 svg 代码在 html 文件中时,这完全符合预期。
但是,当我将它放入 svg 文件并使用 img 标签调用它时,悬停效果不再有效。
<img class="logo" src="url/logo.svg">
有没有办法在不将 svg 代码嵌入 html 的情况下做到这一点?
谢谢!
无法使用 <img>
标签完成。参见:Styling And Animating SVGs With CSS。在本文页面底部附近有一个 table,其中列出了每种 SVG 嵌入技术(即 img、对象等)的优缺点。我在这里转载了 table:
| | CSS Interactions | CSS Animations | SVG Animations |
|:--------------------:|:----------------:|:--------------:|:--------------:|
| <img> | No | Yes* | Yes |
| CSS background image | No | Yes* | Yes |
| <object> | Yes* | Yes* | Yes |
| <iframe> | Yes* | Yes* | Yes |
| <embed> | Yes* | Yes* | Yes |
| <svg> (inline) | Yes | Yes | Yes |
*仅在 <svg>
我把这个答案写成 <svg>
以及它们在每种情况下的功能。
主要要点是,根据上下文,<svg>
可能会或可能不会从顶级文档接收样式规则,并且可能会或可能不会从顶级文档接收交互事件(:hover
).
我建议您查看下面的代码片段以查看正在运行的应用程序:
const someSVG = `
<svg width="128" height="128" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<style>
.interactive.from-svg {
fill: red;
transition: fill 200ms ease;
}
.interactive.from-svg:hover {
fill: blue;
}
.animated.from-svg{
animation: 3s infinite alternate changecolor;
}
@keyframes changecolor{
from {
fill: green;
}
to {
fill: purple;
}
}
</style>
<circle class="interactive from-doc" cx="25" cy="25" r="25"></circle>
<circle class="animated from-doc" cx="75" cy="25" r="25"></circle>
<circle class="interactive from-svg" cx="25" cy="75" r="25"></circle>
<circle class="animated from-svg" cx="75" cy="75" r="25"></circle>
</svg>
`;
const dataUri = `data:image/svg+xml;base64,${btoa(someSVG)}`;
const imgContainer = document.getElementById("img-container"),
img = document.createElement("img");
imgContainer.appendChild(img);
img.src = dataUri;
const backgroundImageContainer = document.getElementById("background-image-container"),
backgroundImage = document.createElement("div");
backgroundImageContainer.appendChild(backgroundImage);
backgroundImage.style.width = "128px";
backgroundImage.style.height = "128px";
backgroundImage.style.backgroundImage = `url(${dataUri})`;
const iframeContainer = document.getElementById("iframe-container"),
iframe = document.createElement("iframe");
iframeContainer.appendChild(iframe);
iframe.src = dataUri;
main {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
section {
flex-basis: 50%;
flex-grow: 1;
flex-shrink: 0;
}
.interactive.from-doc {
fill: red;
transition: fill 200ms ease;
}
.interactive.from-doc:hover {
fill: blue;
}
.animated.from-doc {
animation: 3s infinite alternate changecolor;
}
@keyframes changecolor {
from {
fill: green;
}
to {
fill: purple;
}
}
li.pro {
color: green;
}
li.con {
color: red;
}
<h1><code><svg></code> Usage Comparison</h1>
<main>
<section id="external">
<h2><code><img></code></h2>
<div id="img-container"></div>
<pre><code><img src="some.svg"></code></pre>
<ul>
<li class="con">Does not receive <strong>any</strong> style from top level document</li>
<li class="con">Does not utilize CSS Interactions such as <code>:hover</code></li>
<li class="pro">Will use CSS Animations if they are defined within the svg element's style</li>
</ul>
</section>
<section>
<h2><code>background-image</code></h2>
<div id="background-image-container"></div>
<pre><code>
<style>
.rule{
background-image: url(some.svg);
}
</style>
<div class="rule"></div>
</code></pre>
<ul>
<li class="con">Does not receive <strong>any</strong> style from top level document</li>
<li class="con">Does not utilize CSS Interactions</li>
<li class="pro">Will use CSS Animations if they are defined within the svg element's style</li>
</ul>
</section>
<section>
<h2><code><iframe></code></h2>
<div id="iframe-container"></div>
<pre><code><iframe src="some.svg"></code></pre>
<ul>
<li class="con">Does not receive <strong>any</strong> style from top level document</li>
<li class="pro">Will use CSS Interactions if they are defined within the svg element's style</li>
<li class="pro">Will use CSS Animations if they are defined within the svg element's style</li>
</ul>
</section>
<section>
<h2>Inline <code><svg></code></h2>
<svg width="128" height="128" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<style>
.interactive.from-svg {
fill: red;
transition: fill 200ms ease;
}
.interactive.from-svg:hover {
fill: blue;
}
.animated.from-svg{
animation: 3s infinite alternate changecolor;
}
@keyframes changecolor{
from {
fill: green;
}
to {
fill: purple;
}
}
</style>
<circle class="interactive from-doc" cx="25" cy="25" r="25"></circle>
<circle class="animated from-doc" cx="75" cy="25" r="25"></circle>
<circle class="interactive from-svg" cx="25" cy="75" r="25"></circle>
<circle class="animated from-svg" cx="75" cy="75" r="25"></circle>
</svg>
<pre><code><svg>...</svg></code></pre>
<ul>
<li class="pro">Receives <strong>all</strong> style rules from top level document</li>
<li class="pro">Will use CSS Interactions if they are defined within the svg element's style</li>
<li class="pro">Will use CSS Animations if they are defined within the svg element's style</li>
</ul>
</section>
</main>
<img>
<img src="some.svg">
- 未从顶级文档 接收任何样式
- 不利用 CSS 交互,例如
:hover
- 将使用 CSS 动画,如果它们是在 svg 元素的样式中定义的
background-image
<style>
.rule {
background-image: url(some.svg);
}
</style>
<div class="rule"></div>
- 未从顶级文档 接收任何样式
- 不利用 CSS 互动
- 将使用 CSS 动画,如果它们是在 svg 元素的样式中定义的
<iframe>
<iframe src="some.svg"></iframe>
- 没有从顶级文档中接收到任何样式
- 将使用 CSS 交互,如果它们是在 svg 元素的样式中定义的
- 将使用 CSS 动画,如果它们是在 svg 元素的样式中定义的
内联<svg>
<svg>...</svg>
- 从顶级文档接收所有样式规则
- 将使用 CSS 交互,如果它们是在 svg 元素的样式中定义的
- 将使用 CSS 动画,如果它们是在 svg 元素的样式中定义的