【问题标题】:How to make an SVG image with hover effect inside <a> clickable如何使 <a> 内具有悬停效果的 SVG 图像可点击
【发布时间】:2014-07-26 10:45:45
【问题描述】:

假设我们有一个锚点,其中包含一个带有悬停效果的 SVG 图标和一些文本。

假设图标在指向不同 URL 的各种链接中多次使用。

  • SVG 应该在一个单独的文件中,而不是内联
  • 不应将链接嵌入到 SVG 文件中
  • 悬停效果应该可以工作
  • JS 和 noscript 回退到 PNG 是公平的游戏

嵌入 SVG 的方法

对象:

<a href="http://tomasreichmann.cz/" >
    <object data="http://svgtest.tomasreichmann.cz/images/grafika.svg" type="image/svg+xml">
    </object>
    Link
</a>

图片

<a href="http://tomasreichmann.cz/" >
    <img src="http://svgtest.tomasreichmann.cz/images/grafika.svg" alt="" />
    Link
</a>

演示 http://jsfiddle.net/YZkj9/

这真的不可能吗? 这是不是因为 SVG 自 IE9 起就受支持,但没人使用它?

感谢您的时间和精力,你们太棒了!

【问题讨论】:

  • &lt;object&gt; 的版本在 Chrome、Firefox 和 IE 中适用于我。当然,只有在&lt;object&gt; 悬停时才能看到效果,因为这是定义效果的地方。
  • 链接不起作用,是吗?它不应该因为&lt;object&gt; 是一个被替换的元素。

标签: html css svg


【解决方案1】:

SVG 实际上可以使用 javascript 进行操作。问题是 SVG 对象在尝试使用 jQuery 选择时非常错误,因此您至少必须使用常规 javascript 进行选择。

假设(就像我的例子)你将你的对象包装在一个 div 和一个 href 标记中;它看起来像这样:

<div id="mp3-link">
  <a href="http://your-url.com">
    <object type="image/svg+xml" class="mp3-svg" id="object-svg" data="your-svg-url.com"></object>
  </a>
</div>

对象标签要吐出的代码看起来像这样(在我的例子中,是一个 MP3 下载链接)。

<div id="mp3-link">
<a href="http://google.com">
<object type="image/svg+xml" class="mp3-svg" id="object-svg">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 612 792" style="enable-background:new 0 0 612 792;" xml:space="preserve">
    <defs>
    <style type="text/css"><![CDATA[
        .fill-blue {
            fill:inherit;
            stroke-width:0;
        }
        .mp3 {
            font-family:'Lato-Bold'; 
            stroke-width:0;
        }
        .stroke-blue {
            fill-opacity:0;
            stroke:inherit;
            stroke-width:inherit;
            stroke-miterlimit:inherit;
        }
        #hover-me:hover {
            stroke:#3c4147;
            fill:#3c4147;
        }
        #hover-me {
            stroke:#227AA5;
            stroke-width:22;
            stroke-miterlimit:10;
            fill:#227AA5;
        }
    ]]></style>
</defs>
<g id="hover-me">
<text transform="matrix(0.7813 0 0 1 216.4761 524.5479)" class="mp3 fill-blue hover-me" style="font-size:193.4593;">MP3</text>
<path class="stroke-blue hover-me" d="M377.1,560.5v79 c0,6.2-5,11.2-11.2,11.2H30.6c-6.2,0-11.2-5-11.2-11.2V153.1c0-6.2,5-11.2,11.2-11.2h235.2c6.2,0,111.3,121.2,111.3,121.2v80.7  M593.7,535.4V373.5c0-11-9-20-20-20H189.2c-11,0-20,9-20,20v161.8c0,11,9,20,20,20h384.6C584.7,555.4,593.7,546.4,593.7,535.4z"/>
<path class="page-flap fill-blue hover-me" d="M272,164.5l46.3,50.4l46.7,52.6v2.4h-93V164.5 M267,131h-18v145.1c0,9.4,7.7,17,17.2,17H388v-34.2   l-52.6-59.3l-53.9-58.7L267,131L267,131z"/>
</g>
</svg>

</object>
</a>
</div>

我们需要做的是选择 svg 的内部元素(在本例中为“#hover-me”)并为其附加一个 javascript 函数:

//this is important, as the svg tends to load a little later than the rest of the elements
window.onload=function() {

    // Get the Object by ID
    var theObject = document.getElementById("object-svg");
    // Get the SVG document inside the Object tag
    var svgDoc = theObject.contentDocument;
    // Get one of the SVG items by ID;
    var svgItem = svgDoc.getElementById("hover-me");

    //our javascript selector
    svgItem.addEventListener('click', function() { 
    //here, I'm using jQuery to select the parent and get the href. This is so you can see that jQuery is possible, just not for the selection portion of the code
    var svgHref = $(theObject).parent().attr("href");
    //now, we navigate to the external href. I chose to open in new window.
    var win = window.open(svgHref, '_blank');
    win.focus();
  });
}; //window.onload

所以现在,我们创建了一个函数,该函数将使用 javascript 查找包装对象的链接,然后使用 jQuery 将用户导航到该链接。

我尝试附加一个 jsfiddle,但 jsfiddle 不允许您导入对象,因此您必须在实际网页上尝试此代码

More info in selecting SVG elements with javascript

编辑

在进一步研究之后,我想出了一个更优化的方法来做到这一点:

通过使用 javascript 来实际改变悬停的样式,我们可以让 svg 图像像普通链接一样运行(右键单击选项,下角的状态窗口等)

所以在这种情况下,使用相同的 svg 标记并向我们的链接添加一个类

<div id="mp3-link">
  //we'll call our link "a-svg"
  <a href="http://your-url.com" class="a-svg">
<object type="image/svg+xml" class="mp3-svg" id="object-svg" data="your-svg-url.com"></object>
  </a>
</div>

当链接悬停时,我们可以使用此代码更改 svg 的样式:

window.onload=function() {
//get our link
var theA = document.getElementsByClassName("a-svg");
//loop through all of these (jQuery does this by default, but we're forced to use regular javascript
for(var i=0;i<theA.length;i++){
    //when the user hovers over the link...
    theA[i].addEventListener('mouseover', function() { 
    var thisObject = this.getElementsByClassName('mp3-svg')[0];
    var svgDoc = thisObject.contentDocument;
    // Get one of the SVG items by ID;
    var svgItem = svgDoc.getElementById("hover-me");
    //change the attributes of the svg
    svgItem.setAttribute("fill", "#3c4147");
    svgItem.setAttribute("stroke", "#3c4147");
});
//now revert the changes when the mouse leaves
theA[i].addEventListener('mouseleave', function() { 
    var thisObject = this.getElementsByClassName('mp3-svg')[0];
    var svgDoc = thisObject.contentDocument;
    // Get one of the SVG items by ID;
    var svgItem = svgDoc.getElementById("hover-me");
    svgItem.setAttribute("fill", "#227aa5");
    svgItem.setAttribute("stroke", "#227aa5");
});
}   
};

最后,我们需要一点 css 来使链接位于 svg 之上

.a-svg:after {
  top:0;
  bottom:0;
  left:0;
  right:0;
  position:absolute;
  content"";
}
#mp3-link {
  position:relative;
  height:140px;
  width:140px;
}

现在我们的 svg 图像有了一个具有悬停功能的功能齐全的链接。

【讨论】:

  • 哇,这里有很多有用的东西。我喜欢带有 a-svg:after 的链接覆盖,它解决了点击能力并允许在新选项卡中打开以及处理链接。我不喜欢在 JS 中有链接样式。理想情况下,它们会在页面的 style.css 文件中,但这是不可能的。将它们放在 SVG 文件中是可以的,我们可以使用 JS 更改 SVG 中的一个类来触发悬停效果。总的来说,这是一个很好的解决方案。谢谢:)
【解决方案2】:

您发现图像不支持交互,对象不支持用作链接。如果它们是对象,您可以深入研究图像并使用 DOM 修改链接属性或...

使用两张图片,一张在另一张上面。顶部的图像是您现在拥有的图像,而底部的图像将是悬停图像的静态版本,即编辑您现在拥有的图像并更改填充,使其看起来像悬停的版本并将其另存为文件。

现在让顶部的图像在悬停时将其不透明度转换为 0。您需要将图像定位为绝对位置,以便它们彼此重叠。像这样的……

<a href="http://tomasreichmann.cz/" >
    <img src="http://svgtest.tomasreichmann.cz/images/grafika-hover.svg" alt="" />
    <img class="top" src="http://svgtest.tomasreichmann.cz/images/grafika.svg" alt="" />
    Link
</a>

img {
  position:absolute;
  left:0;
  -webkit-transition: opacity 0.3s; 
  -moz-transition: opacity 0.3s; 
  -ms-transition: opacity 0.3s; 
  -o-transition: opacity 0.3s; 
  transition: opacity 0.3s;
}

img.top:hover {
  opacity:0;
}

【讨论】:

  • 是的,我也想出了这个解决方案,但它相当不雅。你将如何访问图像 DOM?或者是否可以在 SVG 中包含一些 JS 并通过 URL 传递某种参数?
  • 无法访问图像的 DOM。在图像上下文中考虑 SVG 时,它就像是光栅图像一样工作。如果你不能对光栅图像做一些事情,那么你不能用 SVG 作为图像来做。
  • 这太愚蠢了。我花了 2 天时间阅读有关 SVG 和测试的信息。用户期望元素是可点击的某种视觉指示。因此,唯一可行的选择是将其包含为图像并提供除颜色之外的悬停状态。例如。 css 变换比例,不透明度。没有嵌入的 SVG 样式:-/ 底线:链接中的 SVG 上没有花哨的悬停状态,句号。
  • 虽然您的回答在技术上符合我的需要,但我没有回答这个问题,希望有人最终发布更普遍可用的解决方案。无论如何,谢谢你,我相信有人会觉得它有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-23
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
  • 2015-12-26
  • 2015-02-23
  • 2020-12-31
相关资源
最近更新 更多