使用 onclick 使 svg 图像对象可点击,避免绝对定位

Posted

技术标签:

【中文标题】使用 onclick 使 svg 图像对象可点击,避免绝对定位【英文标题】:Making an svg image object clickable with onclick, avoiding absolute positioning 【发布时间】:2011-01-18 18:15:03 【问题描述】:

我尝试将我网站上的图片从img 更改为svg,将img 标签更改为embedobject 标签。但是,实现以前包含在img 标签中的onclick 函数被证明是最困难的。

我发现onclick 放在objectembed 标签内时没有效果。

所以,我专门为 svg 制作了一个 div,并将 onclick 放在这个 div 标记中。但是,除非访问者点击图像的边缘/填充,否则无效。

我已经阅读了关于覆盖div 的信息,但我试图避免使用absolute 定位,或者根本不指定position

还有其他方法可以将 onclick 应用于 svg 吗?

有人遇到过这个问题吗?欢迎提出问题和建议。

【问题讨论】:

【参考方案1】:

您可以在 svg 本身中有一个 onclick 事件,我在工作中一直这样做。在你的 svg 的空间上做一个矩形,(所以最后定义它,记住 svg 使用画家模型)

rect.btn 
  stroke:#fff;
  fill:#fff;
  fill-opacity:0;
  stroke-opacity:0;

然后作为 rect 的属性添加 onclick(也可以使用 js 或 jquery 完成)。

<div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <g>
    <circle ... //your img svg
    <rect class="btn" x="0" y="0"   onclick="alert('click!')" />
  </g>
</svg>
</div>

这几乎适用于所有浏览器:http://caniuse.com/svg

【讨论】:

是的,这对我有用,只是想添加一些 cmets/澄清。请查看提交的答案。 不错的解决方案。对于 CSS,似乎只需要fill-opacity: 0。为什么要设置strokefillstroke-opacity 它们的存在只是为了明确,以防止任何其他样式侵入。 这个答案的代码不相关,因为最初的问题是关于使用带有嵌入或对象标签的 svg。在任何情况下它都会起作用,但不应推荐,因为将 UI 代码放在图像文件中是没有意义的。 @DAG 操作并没有指定他想要使用对象或嵌入,只是提到它们是他尝试过的事情。【参考方案2】:

如果您可以将 svg 包装在另一个元素中(例如 a)并将 onclick 放在包装器上,svg pointer-events: none; CSS 就可以解决问题。

【讨论】:

【参考方案3】:

我将“svg”标签包裹在“a”标签中,并将 onClick 事件放在“a”标签中

【讨论】:

【参考方案4】:

通过点击事件在&lt;object&gt; 中点击SVG 的&lt;g&gt; 元素。工作 100%。看看&lt;svg&gt; 中的嵌套javascript。如果要重定向父页面,请不要忘记插入window.parent.location.href=

https://www.tutorialspoint.com/svg/svg_interactivity.htm

【讨论】:

【参考方案5】:

这开始是对 RGB 解决方案的评论,但我无法适应它,因此将其转换为答案。其灵感完全来自 RGB。

RGB 的解决方案对我有用。但是,我想指出几点可能会帮助其他人(如我)到达这篇文章,他们不太熟悉哪个 SVG,并且很可能从图形包生成了他们的 SVG 文件(就像我一样)。

所以要应用我使用的 RGB 解决方案:

CSS

 <style>
    rect.btn 
        stroke:#fff;
        fill:#fff;
        fill-opacity:0;
        stroke-opacity:0;
    
</style>

jquery 脚本

<script type="text/javascript" src="../_public/_jquery/jquery-1.7.1.js"></script>   
<script type="text/javascript">
   $("document").ready(function()
       $(".btn").bind("click", function(event)alert("clicked svg"));
   );
</script>

用于编码将您预先存在的 SVG 文件包含在 SVG 代码内的组标记中的 html

<div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <g>
     <image x="0" y="0"  
     xlink:href="../_public/_icons/booked.svg" />
    <rect class="btn" x="0" y="0"  />

  </g>
</svg>
</div>

但是,就我而言,我有几个 SVG 图标,我希望它们是可点击的,并且将这些图标中的每一个都合并到 SVG 标记中开始变得很麻烦。

因此,作为一种可以使用类的替代方法,我使用了 jquery.svg。这可能是这个插件的一个可耻的应用程序,它可以用 SVG 做各种各样的事情。但它使用以下代码工作:

<script type="text/javascript" src="../_public/_jquery/jquery-1.7.1.js"></script>       
<script type="text/javascript" src="jquery.svg.min.js"></script>
<script type="text/javascript">
    $("document").ready(function()
        $(".svgload").bind("click", function(event)alert("clicked svg"));

         for (var i=0; i < 99; i++) 
           $(".svgload:eq(" + i + ")").svg(
              onLoad: function()
              var svg = $(".svgload:eq(" + i + ")").svg('get');
              svg.load("../_public/_icons/booked.svg", addTo: true,  changeSize: false);        
              ,
              settings: 
          ); 
         
    );
</script>

HTML 在哪里

<div class="svgload" style="width: 10px; height: 10px;"></div>

我的想法的好处是,我可以在需要图标的地方使用适当的类,并避免在 HTML 正文中使用大量有助于可读性的代码。而且我只需要将预先存在的 SVG 文件合并一次。

编辑:这是由 Keith Wood 提供的更简洁的脚本版本:使用 .svg 的加载 URL 设置。

<script type="text/javascript" src="../_public/_jquery/jquery-1.7.1.js"></script>       
<script type="text/javascript" src="jquery.svg.min.js"></script>
<script type="text/javascript">
    $("document").ready(function()

      $('.svgload').on('click', function() 
          alert('clicked svg new');
      ).svg(loadURL: '../_public/_icons/booked.svg');

    );
</script>

【讨论】:

【参考方案6】:

如果你只使用 inline svg 没有问题。

<svg id="svg1" xmlns="http://www.w3.org/2000/svg" style="width: 3.5in; height: 1in">
  <circle id="circle1" r="30" cx="34" cy="34" onclick="circle1.style.fill='yellow';"
            style="fill: red; stroke: blue; stroke-width: 2"/>
  </svg>
  

【讨论】:

【参考方案7】:

使用&lt;object&gt; 嵌入同源SVG 时,您可以使用objectElement.contentDocument.rootElement 访问内部内容。从那里,您可以轻松附加事件处理程序(例如,通过onclickaddEventListener() 等)

例如:

var object = /* get DOM node for <object> */;
var svg = object.contentDocument.rootElement;
svg.addEventListener('click', function() 
  console.log('hooray!');
);

请注意,对于跨域 &lt;object&gt; 元素,这是不可能,除非您还控制 &lt;object&gt; 源服务器并且可以在那里设置 CORS 标头。对于没有 CORS 标头的跨域情况,对 contentDocument 的访问被阻止。

【讨论】:

【参考方案8】:

也许您正在寻找的是 SVG 元素的 pointer-events 属性,您可以在 SVG w3C working group docs 上阅读。

您可以使用 CSS 来设置 SVG 元素在被单击时发生的情况等。

【讨论】:

【参考方案9】:

只需将&lt;embed/&gt; 标记替换为&lt;img/&gt; 并删除类型属性即可。

例如,在我的代码中,而不是:

<embed src=\"./images/info_09c.svg\" type=\"image/svg+xml\" width=\"45\" onClick='afiseaza_indicatie($i, \"$indicatii[$i]\")'> 

没有回答点击,我写道:

<img src=\"./images/info_09c.svg\" height=\"25\" width=\"25\" onClick='afiseaza_indicatie($i, \"$indicatii[$i]\")'> 

它可以在 Internet Explorer 和 Google Chrome 中使用,我希望其他浏览器也可以。

【讨论】:

我猜你正在转义 xml 或其他东西的引用,但这至少在 IE 中有效,当它在 中显示 svg 时不起作用(类似于嵌入示例)。只要您使用的是现代浏览器,我不明白为什么在使用 尝试用 img src 替换 引用以使 onclick 工作。在 safari、chrome 和 firefox 以及 android 上的 chrome 下测试工作。感谢这个解决方案 - 它更简单,并且避免使用内联 javascript 使我的 svg 混乱。【参考方案10】:

您可以使用以下代码:

<style>
    .svgwrapper 
        position: relative;
    
    .svgwrapper 
        position: absolute;
        z-index: -1;
    
</style>

<div class="svgwrapper" onClick="function();">
    <object src="blah" />
</div>

b3ng0 写了类似的代码,但它不起作用。父级的 z-index 必须是自动的。

【讨论】:

【参考方案11】:

我在最新版本的 Firefox、Chrome、Safari 和 Opera 上都能正常工作。

它依赖于具有绝对位置并设置宽度和高度的对象之前的透明div,因此它覆盖了下面的对象标签。

在这里,我有点懒,使用了内联样式:

<div id="toolbar" style="width: 600px; height: 100px; position: absolute; z-index: 1;"></div>
<object data="interface.svg"   type="image/svg+xml">
</object>

我使用以下 JavaScript 将事件连接到它:

<script type="text/javascript">
    var toolbar = document.getElementById("toolbar");
    toolbar.onclick = function (e) 
        alert("Hello");
    ;
</script>

【讨论】:

【参考方案12】:

假设您不需要跨浏览器支持(如果没有 IE 插件,这是不可能的),您是否尝试过使用 svg as a background image?

当然是实验性的东西,但我想我会提到它。

【讨论】:

好主意,但缺乏 Firefox 支持让我放弃了这个主意。【参考方案13】:

您是否考虑过使用 CSS z-index 属性使容器 dev 位于 svg 的“顶部”?因为 div 是(大概)透明的,所以您仍然会看到与以前完全相同的图像。

我相信,这是解决您的问题的最佳实践、非 hack、预期的方法。 z-index 仅对具有position 属性为fixedrelative 或正如您所听说的absolute 的元素有用。但是,您实际上不必移动对象。

例如:

<style>
    .svgwrapper 
        position: relative;
        z-index: 1;
    
</style>
<div class="svgwrapper" onClick="function();">
    <object src="blah" />
</div>

对于它的价值,完全不使用onClick,而是使用javascript绑定click事件也会更加优雅和安全。不过,这完全是另一个问题。

【讨论】:

以上是关于使用 onclick 使 svg 图像对象可点击,避免绝对定位的主要内容,如果未能解决你的问题,请参考以下文章

仅为 TextView 复合可绘制对象实现 onClick

SVG 详解——自定义可点击的中国地图

SVG 详解——自定义可点击的中国地图

如何获取相对于持有 onclick 监听器的 SVG 元素的点击坐标?

SVG 检测“填充:无”上的 Onclick 事件

使叠加层后面的图像可点击[重复]