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

2022-01-22 00:00:00 hover svg css cross-browser pointer-events

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

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

我在做

<代码>g {指针事件:边界框;}

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

我可以使用 没有说什么,它提到svgs也有支持这个属性.

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

<?xml version="1.0" encoding="UTF-8"?>

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

谢谢,

解决方案

所以 pointer-events: bounding-box 似乎大多数浏览器都不支持.

我在问题的评论部分实施了@ccprog 建议的解决方法.

我在 svg 中添加了一个 <rect fill="none"> 元素,它的尺寸与 SVG 本身相同.我为该元素添加了一个 :hover 选择器和同级选择器 ~ 以选择其同级组,其中包含 flip 类.

参见 CSS:

#mobile-hover {能见度:可见;指针事件:可见;}#mobile-hover:hover ~ .group .flip {-moz 变换来源:55% 50%;-webkit-transform-origin:55% 50%;变换原点:55% 50%;-webkit-animation:flip_left 1.6s 向前;动画:flip_left 1.6s 前进;}

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

在全新的 SVG 代码下方:

<?xml version="1.0" encoding="UTF-8"?>

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

非常感谢,

I'm working on some animated SVGs with CSS animations that triggers on hover. I'm being able to have the SVG animate on hover the way I want to for Chrome but I'm facing a Firefox and Safari issue.

Apparently, the pointer-events property applied to groups <g></g> doesn't give same behavior on this browser than on the other modern ones, at least when trying to set the value to bounding-box.

I'm doing

g {
  pointer-events: bounding-box;
}

but the hover only gets triggered when the actual <path> element is hovered, not the whole group <g> as I would need to.

Can I use doesn't say anything about this, it mentions svgs also have support for this property.

Below there's a sample code for you to see how one of my SVGs looks like. On chrome hovering the main containing group area will trigger the hover animation, on Firefox the actual path (the icon lines in this case) needs to be hovered in order to that to happen.

<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" 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-width="1" fill="none" fill-rule="evenodd">
        <g id="MS_HP_Usecase_Based_Page-Desktop-2A" transform="translate(-766.000000, -418.000000)" stroke="#00A0DF" stroke-width="1.25">
            <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" width="15.32" height="25.33" 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>

I would like to find a workaround for this, since I want to make this animations work cross browser. I would like to eventually make it work for IE11 and Edge too.

Thanks,

解决方案

So pointer-events: bounding-box seems to not be supported by most browsers.

I implemented the workaround @ccprog suggested on the comments section of my question.

I added a <rect fill="none"> element to svg, that is same dimensions than the SVG itself. I added a :hover selector for that element and sibling selector ~ to select its sibling group with the flip class inside.

See 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;
}

I found out I had to add pointer-events: visible to the rect element so it would detect the :hover. I added visibility: visible as a requirement to pointer-events: visible to work.

Below the full new SVG code:

<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" 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-width="1" fill="none" fill-rule="evenodd" >
    <rect fill="none" width="40" height="40" id="mobile-hover">
    </rect>
        <g id="MS_HP_Usecase_Based_Page-Desktop-2A" transform="translate(-766.000000, -418.000000)" stroke="#00A0DF" stroke-width="1.25" 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" width="15.32" height="25.33" 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>

Works on Chrome, Safari and Firefox and I'm attempting to test IE11 and Edge next.

Many thanks,

相关文章