【问题标题】:make an html svg object also a clickable link使 html svg 对象也成为可点击的链接
【发布时间】:2012-07-07 10:05:16
【问题描述】:

我的 HTML 页面中有一个 SVG 对象,并将其包装在一个锚点中,因此当单击 svg 图像时,它会将用户带到锚点链接。

<a href="http://www.google.com/">
    <object data="mysvg.svg" type="image/svg+xml">
        <span>Your browser doesn't support SVG images</span>
    </object>
</a>

当我使用此代码块时,单击 svg 对象不会将我带到谷歌。在 IE8

我不想修改我的 svg 图像以包含标签。

我的问题是,如何使 svg 图片可点击?

【问题讨论】:

    标签: html object svg anchor


    【解决方案1】:

    其实解决这个问题最好的办法是……在标签上,使用:

    pointer-events: none;
    

    注意:安装了 Ad Blocker 插件的用户在悬停时会在右上角获得一个类似标签的 [Block](与 Flash 横幅一样)。通过设置这个 css,它也会消失。

    http://jsfiddle.net/energee/UL9k9/

    【讨论】:

    • 注意:在 IE 11 之前,IE 不支持常规元素上的指针事件,但在 SVG 上已经支持它们。见caniuse.com/pointer-events
    • 此解决方案(以及来自 noelmcg 的解决方案)的一个缺点是,如果您的 SVG 文件包含带有 :hover 选择器的 CSS 规则,这些规则将停止工作。 Ben Frain 提出的解决方案没有这个问题。
    • 这应该是批准的答案。将 img 与 svg 一起使用会导致无法更改内部 SVG 样式。
    • 这必须是经过批准的答案!真的很好,谢谢
    • 很好的答案。我在全球 css 中使我的通用。对象[type*="svg"]{pointer-events: none}
    【解决方案2】:

    我遇到了同样的问题,并通过以下方式解决了这个问题:

    使用设置为块或内联块的元素包装对象

    <a>
        <span>
            <object></object>
        </span>
    </a>
    

    添加到&lt;a&gt;标签:

    display: inline-block;
    position: relative; 
    z-index: 1;
    

    &lt;span&gt;标签:

    display: inline-block;
    

    &lt;object&gt;标签:

    position: relative; 
    z-index: -1
    

    在此处查看示例:http://dabblet.com/gist/d6ebc6c14bd68a4b06a6

    通过评论 20 找到 https://bugzilla.mozilla.org/show_bug.cgi?id=294932

    【讨论】:

    • 抱歉,忘记显示:inline-block/block 元素环绕对象
    • 这里的最佳解决方案!
    • 这是解决此问题的最佳解决方案,适用于所有浏览器
    • 如果图像具有透明背景,则这些位看起来不可点击
    • 这对我有用,我还必须在我的情况下将 height: 100% 添加到 a 和 span 元素
    【解决方案3】:

    我想以此为荣,但我在这里找到了解决方案:

    https://teamtreehouse.com/forum/how-do-you-make-a-svg-clickable

    将以下内容添加到锚点的 css 中:

    a.svg {
      position: relative;
      display: inline-block; 
    }
    a.svg:after {
      content: ""; 
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left:0;
    }
    
    
    <a href="#" class="svg">
      <object data="random.svg" type="image/svg+xml">
        <img src="random.jpg" />
      </object>
    </a>
    

    链接适用于 svg 和后备。

    【讨论】:

    • 这是最简单和最受支持的解决方案
    • 这仍然有一个问题:SVG 指针事件(动画)不再起作用(鼠标悬停、鼠标移出、单击)!就像简单地在对象本身上使用指针事件:none ...
    【解决方案4】:

    你也可以在你的 SVG 底部贴上这样的东西(就在结束 &lt;/svg&gt; 标签之前):

    <a xmlns="http://www.w3.org/2000/svg" id="anchor" xlink:href="/" xmlns:xlink="http://www.w3.org/1999/xlink" target="_top">
        <rect x="0" y="0" width="100%" height="100%" fill-opacity="0"/>
    </a>
    

    然后只需修改链接以适应。我已经使用 100% 的宽度和高度来覆盖它所在的 SVG。这项技术的功劳归功于 Clearleft.com 上的聪明人 - 这是我第一次看到它使用的地方。

    【讨论】:

    • 我的 SVG 文件中嵌入了带有 :hover 选择器的 css 样式。这是唯一不会停用样式的解决方案。
    • 唯一对我有用的东西 - 谢谢!
    【解决方案5】:

    Richard 解决方案的简化。至少在 Firefox、Safari 和 Opera 中有效:

    <a href="..." style="display: block;">
        <object data="..." style="pointer-events: none;" />
    </a>
    

    有关其他解决方案,请参阅 http://www.noupe.com/tutorial/svg-clickable-71346.html

    【讨论】:

    • 谢谢,我需要在父级&lt;a&gt; 上将显示设置为blockinline-block
    • 好的链接:noupe.com/inspiration/tutorials-inspiration/… 对每个解决方案都有 proscons
    • 在某些情况下我还需要使用inline-block,但block 似乎在其他情况下效果很好;我想这取决于封闭的块......
    【解决方案6】:

    最简单的方法是不使用。而是使用 标签,并且锚应该可以正常工作。

    【讨论】:

    • img 标签通常会放在 span 标签所在的位置,以便优雅地降级。
    • 显示 svg 矢量不是图像的想法吗?
    • @ErikDahlström 但 &lt;img&gt; 引用 svg 数据并不总是如您所愿,即使在最新版本的 Chrome 中也是如此:( stackoverflow.com/questions/15194870/…
    • 正如@energee 指出的那样,您可以使用&lt;object&gt; 标签并添加point-event: none; 使其可点击。它保留对您的 svg 源代码的访问权限并允许您动态操作它。
    • @Antoine 实际上正确的属性是 'pointer-events: none;'就像下面提到的,这不起作用,不过谢谢
    【解决方案7】:

    要在所有浏览器中完成此操作,您需要结合使用@energee、@Richard 和@Feuermurmel 方法。

    <a href="" style="display: block; z-index: 1;">
        <object data="" style="z-index: -1; pointer-events: none;" />
    </a>
    

    添加:

    • pointer-events: none; 使它可以在 Firefox 中运行。
    • display: block; 让它在 Chrome 和 Safari 中运行。
    • z-index: 1; z-index: -1; 也可以在 IE 中运行。

    【讨论】:

    • @janaspage 我不确定...我还没有在 IE 10 上尝试过。让我知道它是否有效 :)
    • @jaepage 没关系,因为object 现在将位于比其父级更低的堆叠上下文(下方)中。
    • 这可以在 iPhone/手机上使用吗?不适合我。不可点击/不可点击
    【解决方案8】:

    我也通过编辑 svg 文件解决了这个问题。

    我将整个 svg 图形的 xml 包装在一个具有点击事件的组标签中,如下所示:

    <svg .....>
    <g id="thefix" onclick="window.top.location.href='http://www.google.com/';">
     <!-- ... your graphics ... -->
    </g>
    </svg>
    

    解决方案适用于所有支持对象 svg 脚本的浏览器。 (对于不支持 svg 的浏览器,您的 object 元素中默认有一个 img 标签,您将覆盖所有浏览器)

    【讨论】:

    • 您是否发现将 onclick 添加到外部 &lt;svg&gt; 元素并且根本不包装它不起作用?
    • 您也可以使用根 svg 元素的事件。除了 onclick 事件,我还使用 onmouseout、ontouchstart、ontouchend 等……对于根 svg 元素,我经常使用 onload 事件。下面的 Ben Frain 解决方案涉及绘制一个额外的封面对象(一个矩形)来捕获点击事件......所以我提供了这个解决方案,展示了在绘图元素本身上获取事件,而不必为了获得点击事件而制作透明封面。当您不想绘制另一个元素或者您想要特定于现有形状而不是矩形的事件时特别有用。
    【解决方案9】:

    我尝试了这种干净简单的方法,并且似乎适用于所有浏览器。 在 svg 文件中:

    <svg>
    <a id="anchor" xlink:href="http://www.google.com" target="_top">
      
    <!--your graphic-->
      
    </a>
    </svg>
      

    【讨论】:

    • 必须将以下 'xlink' 命名空间添加到 svg 元素才能使其工作:xmlns:xlink="w3.org/1999/xlink"
    • 其他解决方案都不适合我,但这个解决方案可以,哇,谢谢!
    • 虽然我通常对直接更改 SVG 文件没有疑虑,但在我的场景中,我将 same SVG 用于多个 不同 链接 — 意思是从理论上讲,我必须为每个创建一个不同的 SVG。或者,当然,我可以在 标记中添加图形位内联,但我讨厌重复的代码(即使我得到的实际 SVG 很小......)
    【解决方案10】:

    我只是在使用

            <a href="#">
                <img src="../../assets/images/logo.svg" alt="">
            </a>
    

    除了我试图应用 :hover 状态外,它工作正常。把我带到这里的是我使用的时候

            <a href="#">
                <object data="../../assets/images/logo.svg" type="image/svg+xml" class="logo">
                </object>
            </a>
    

    我丢失了链接,并在 DevTools 中注意到该链接仍然出现在 SVG 周围,但 :hover 状态有效。利用 energee 的优雅答案,我的链接有效,但我当然失去了:悬停。所以看起来 object 标记对于将 :hover 更改应用于 SVG 来说并不是一个很好的解决方案。

    我很好奇,你为什么不使用 img 标签来显示一个没有任何特殊添加的 SVG,比如 :hover?使用 img 标签也适用于 a 标签。

    【讨论】:

      【解决方案11】:

      只是不要使用&lt;object&gt;。这是一个使用&lt;a&gt;&lt;svg&gt; 标签对我有用的解决方案:

      <a href="<your-link>" class="mr-5 p-1 border-2 border-transparent text-gray-400 rounded-full hover:text-white focus:outline-none focus:text-white focus:bg-red-700 transition duration-150 ease-in-out" aria-label="Notifications">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="30" 
          height="30"><path class="heroicon-ui" fill="#fff" d="M17 16a3 3 0 1 1-2.83 
          2H9.83a3 3 0 1 1-5.62-.1A3 3 0 0 1 5 12V4H3a1 1 0 1 1 0-2h3a1 1 0 0 1 1 
          1v1h14a1 1 0 0 1 .9 1.45l-4 8a1 1 0 0 1-.9.55H5a1 1 0 0 0 0 2h12zM7 12h9.38l3- 
         6H7v6zm0 8a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm10 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
          </svg>
      </a>
      

      【讨论】:

      • 顺便说一句,我正在使用顺风 css。
      【解决方案12】:

      这已经很晚了,但我想知道为什么 energee's solution 有效:具体来说,&lt;object&gt; 元素如何影响其父元素。

      tl;dr 您不能单击其中包含 &lt;object&gt; 元素的锚点,因为单击事件正在被 &lt;object&gt; 元素内部的任何内容捕获,然后不会将其冒泡。

      jsfiddle


      扩展原始问题中描述的症状:不仅锚元素内的&lt;object&gt;元素会导致锚变得不可点击,似乎&lt;object&gt;元素作为任何元素的子元素 将导致clickmousedownmouseup 事件(也可能是触摸事件)不会在父元素上触发,(当您在&lt;object&gt; 的边界矩形内单击时.)

      <span>
          <object type="image/svg+xml" data="https://icons.getbootstrap.com/icons/three-dots.svg">
          </object>
      </span>
      
      document
          .querySelector('span')
          .addEventListener('click', console.log) // will not fire
      

      现在,&lt;object&gt; 元素的行为有点“像”&lt;iframe&gt;s,因为它们将建立新的浏览上下文,包括当内容是 &lt;svg&gt; 文档时。在 JavaScript ,这通过 HTMLObjectElement.contentDocumentHTMLObjectElement.contentWindow 属性的存在来体现。

      这意味着如果你在&lt;object&gt; 内的&lt;svg&gt; 元素中添加一个事件监听器:

      document
          .querySelector('object')
          .contentDocument  // returns null if cross-origin: the same-origin policy
          .querySelector('svg')
          .addEventListener('click', console.log)
      

      然后单击图像,您将看到正在触发的事件。

      那么pointer-events: none; 解决方案的工作原理就很清楚了:

      • 如果没有这种样式,任何被认为是“交互式”的MouseEvent(例如clickmousedown,但不是mouseenter)都会发送到&lt;object&gt; 内的嵌套浏览上下文,永远不会冒出来。

      • 使用这种样式,MouseEvents 首先不会发送到&lt;object&gt;,然后&lt;object&gt; 的父元素将照常接收事件。

      这也应该解释z-index 解决方案:只要您可以防止click 事件被发送到嵌套文档,点击应该按预期工作。

      (在我的测试中,只要父元素不是inline 并且&lt;object&gt; 被定位并且具有负值z-indexz-index 解决方案就可以工作)

      (或者,您可以找到一种方法将事件重新冒泡):

      let objectElem = document.querySelector('object')
      let svgElemt = objectElem.contentDocument.querySelector('svg')
      
      svgElem.addEventListener('click', () => {
          window.postMessage('Take this click event please.')
          // window being the outermost window
      })
      
      window.addEventListener('message', console.log)
      

      【讨论】:

        【解决方案13】:

        使用 javascript 并添加 onClick-attribute 到您的 object-element:

        <object data="mysvg.svg" type="image/svg+xml" onClick="window.location.href='http://google.at';">
            <span>Your browser doesn't support SVG images</span>
        </object>
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-12
        • 2011-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-06
        相关资源
        最近更新 更多