CSS:悬停在 SVG 组区域而不是渲染像素上,指针事件:边界框不能跨浏览器工作。如何解决

Posted

技术标签:

【中文标题】CSS:悬停在 SVG 组区域而不是渲染像素上,指针事件:边界框不能跨浏览器工作。如何解决【英文标题】:CSS :hover on SVG group area instead of rendered pixels, pointer-events: bounding-box not working cross browser. How to workaround 【发布时间】:2019-02-07 21:19:18 【问题描述】:

我正在制作一些带有 CSS 动画的动画 SVG,这些动画会在悬停时触发。 我能够以我希望 Chrome 的方式悬停 SVG 动画,但我面临 Firefox 和 Safari 问题。

显然,应用于组 <g></g>pointer-events 属性在此浏览器上的行为与在其他现代浏览器上的行为不同,至少在尝试将值设置为 bounding-box 时。

我在做

g 
  pointer-events: bounding-box;

但只有在实际的 <path> 元素悬停时才会触发悬停,而不是像我需要的那样整个组 <g>

Can I use 没有说明这一点,它提到 svgs 也支持这个属性。

下面有一个示例代码,供您查看我的一个 SVG 的外观。 在 chrome 上悬停主要包含组区域将触发悬停动画,在 Firefox 上实际路径(在本例中为图标行)需要悬停才能发生。

<?xml version="1.0" encoding="UTF-8"?>
<svg   viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
    <style>
        g 
            pointer-events: bounding-box;     
            //not working on FF
        
        #mobile:hover .flip 
            transform-origin:55% 50%;
            -moz-transform-origin:55% 50%;
            animation: flip_left 1.6s forwards;
        
        @keyframes flip_left 
          0% transform: perspective(2000px) rotateY(90deg) skewY(-1deg)
          30% transform:perspective(2000px) rotateY(-25deg) skewY(-0.8deg)
          50% transform:perspective(2000px) rotateY(20deg) skewY(0.8deg)
          70% transform:perspective(2000px) rotateY(-10deg) skewY(-0.8deg)
          100% transform:perspective(2000px) rotateY(0deg)
        
    </style>
    <!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
    <title>Mobile solutions</title>
    <desc>Created with Sketch.</desc>
    <defs></defs>
    <g id="mobile" stroke="none" stroke- fill="none" fill-rule="evenodd">
        <g id="MS_HP_Usecase_Based_Page-Desktop-2A" transform="translate(-766.000000, -418.000000)" stroke="#00A0DF" stroke->
            <g id="Asset-5" transform="translate(766.000000, 418.000000)">
                <g class="flip">
                <rect id="Rectangle-path" stroke-linecap="round" stroke-linejoin="round" x="12.35" y="7.41"   rx="2.03"></rect>
                <circle id="Oval" stroke-linecap="round" stroke-linejoin="round" cx="20.01" cy="28.72" r="1.58"></circle>
                <path d="M18.43,10.72 L21.48,10.72" id="Shape" stroke-linecap="round" stroke-linejoin="round"></path>
            </g>
                <circle id="Oval" cx="19.67" cy="19.67" r="19.04"></circle>
            </g>
        </g>
    </g>
</svg>

我想找到一个解决方法,因为我想让这个动画跨浏览器工作。我希望最终让它也适用于 IE11 和 Edge。

谢谢,

【问题讨论】:

pointer-events: bounding-box; 你确定吗?不是有效值。请看MDN web docs pointer-events @enxaneta 根据SVG2,它是一个有效值,但大多数浏览器尚未实现。通常的解决方法是定义一个覆盖所需区域的不可见&lt;rect fill="none"&gt;。然后为父组设置pointer-events:all 我在 Chrome 上开发此解决方案时发现了bounding-box 解决方案,但我没有意识到它根本不被所有浏览器支持。我现在觉得很傻。不管怎样,你们两个帮了我很多。我将实施解决方法并返回工作示例作为问题的答案。谢谢! 【参考方案1】:

所以pointer-events: bounding-box 似乎不受大多数​​浏览器的支持。

我在问题的 cmets 部分实施了@ccprog 建议的解决方法。

我在 svg 中添加了一个 &lt;rect fill="none"&gt; 元素,它与 SVG 本身的尺寸相同。我为该元素添加了一个:hover 选择器和兄弟选择器~ 以选择其内部包含flip 类的兄弟组。

参见 CSS:

#mobile-hover 
   visibility: visible;
   pointer-events: visible;

#mobile-hover:hover ~ .group .flip 
  -moz-transform-origin:55% 50%;
  -webkit-transform-origin: 55% 50%;
  transform-origin:55% 50%;
  -webkit-animation: flip_left 1.6s forwards;
  animation: flip_left 1.6s forwards;

我发现我必须将pointer-events: visible 添加到rect 元素,这样它才能检测到:hover。我添加了visibility: visible 作为pointer-events: visible 工作的要求。

在全新的 SVG 代码下方:

<?xml version="1.0" encoding="UTF-8"?>
<svg   viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="mobile-icon">
    <style>
        #mobile-hover 
        visibility: visible;
        pointer-events: visible;
        
        #mobile-hover:hover ~ .group .flip 
            -moz-transform-origin:55% 50%;
            -webkit-transform-origin: 55% 50%;
            transform-origin:55% 50%;
            -webkit-animation: flip_left 1.6s forwards;
            animation: flip_left 1.6s forwards;
        
        @keyframes flip_left 
          0% transform: perspective(2000px) rotateY(90deg) skewY(-1deg)
          30% transform:perspective(2000px) rotateY(-25deg) skewY(-0.8deg)
          50% transform:perspective(2000px) rotateY(20deg) skewY(0.8deg)
          70% transform:perspective(2000px) rotateY(-10deg) skewY(-0.8deg)
          100% transform:perspective(2000px) rotateY(0deg)
        
    </style>
    <!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
    <title>Mobile solutions</title>
    <desc>Created with Sketch.</desc>
    <defs></defs>
    <g id="mobile" stroke="none" stroke- fill="none" fill-rule="evenodd" >
    <rect fill="none"   id="mobile-hover">
    </rect>
        <g id="MS_HP_Usecase_Based_Page-Desktop-2A" transform="translate(-766.000000, -418.000000)" stroke="#00A0DF" stroke- class="group">
            <g id="Asset-5" transform="translate(766.000000, 418.000000)">
                <g class="flip">
                <rect id="Rectangle-path" stroke-linecap="round" stroke-linejoin="round" x="12.35" y="7.41"   rx="2.03"></rect>
                <circle id="Oval" stroke-linecap="round" stroke-linejoin="round" cx="20.01" cy="28.72" r="1.58"></circle>
                <path d="M18.43,10.72 L21.48,10.72" id="Shape" stroke-linecap="round" stroke-linejoin="round"></path>
            </g>
                <circle id="Oval" cx="19.67" cy="19.67" r="19.04"></circle>
            </g>
        </g>

    </g>
</svg>

适用于 Chrome、Safari 和 Firefox,接下来我正在尝试测试 IE11 和 Edge。

非常感谢,

【讨论】:

以上是关于CSS:悬停在 SVG 组区域而不是渲染像素上,指针事件:边界框不能跨浏览器工作。如何解决的主要内容,如果未能解决你的问题,请参考以下文章

鼠标悬停时的SVG工具提示?

SVG css旋转坚持而不是围绕中心旋转

FF25 和 IE10 中的内联 SVG 上的 1 像素(或更少?亚像素?)边框,而不是 Chrome

你如何使css中悬停的区域更大

SVG 与 HTML5 的 canvas 各有啥优点,哪个更有前途

SVG 与 HTML5 的 canvas 各有啥优点,哪个更有前途