SVG嵌套动画故障:父元素隐藏时子动画元素仍可见的解决方法
问题分析
核心问题是:SVG中子元素的<animate>显式设置visibility属性时,优先级会高于父元素继承的visibility: hidden。即便page_two被设为隐藏,黑色方块的动画仍会主动将自身visibility设为visible,导致它无视父元素的隐藏状态。
补充说明:SVG里的z-index对<g>元素无效,SVG是按文档绘制顺序决定层级的,后绘制的元素会覆盖前面的,你设置的z-index实际没起作用。
解决方案
提供两种可行修复思路:
思路一:替换visibility动画为opacity动画
把黑色方块的闪烁动画从修改visibility改成修改opacity,这样父元素的visibility: hidden会直接让子元素完全不可见,不会被子元素的动画覆盖。
修改后代码:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 612 792" style="enable-background:new 0 0 612 792;" xml:space="preserve"> <rect x="0.5" y="0.167" fill="#ccc" stroke="#000" width="100" height="100"/> <!-- square --> <g> <!-- page 1 --> <g id="page_one"> <rect x="25" y="5" width="50" height="50" fill="red"></rect> </g> <!-- page 2 --> <g id="page_two"> <rect x="25" y="5" width="50" height="50" fill="white"></rect> <g transform="scale(2.9) translate(6,0)"> <g transform="scale(0.205)translate(1,1)"> <!-- 把visibility动画替换为opacity动画 --> <g> <animate attributeName="opacity" dur="2s" repeatCount="indefinite" keyTimes="0;0.5;1" values="1;0;1"></animate> <rect x="25" y="15" width="50" height="50" fill="black"></rect> </g> </g> </g> </g> <!-- animate page 1 & 2 --> <animate xlink:href="#page_one" attributeName="visibility" values="visible;hidden" dur="4s" begin="0s" repeatCount="indefinite"></animate> <animate xlink:href="#page_two" attributeName="visibility" values="hidden;visible" dur="4s" begin="0s" repeatCount="indefinite"></animate> </g> </svg>
思路二:让子元素动画依赖父元素的可见状态
通过动画的begin和end属性,让黑色方块的闪烁动画只在page_two可见时运行,当page_two隐藏时,强制将黑色方块设为隐藏。
修改后代码:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 612 792" style="enable-background:new 0 0 612 792;" xml:space="preserve"> <rect x="0.5" y="0.167" fill="#ccc" stroke="#000" width="100" height="100"/> <!-- square --> <g> <!-- page 1 --> <g id="page_one"> <rect x="25" y="5" width="50" height="50" fill="red"></rect> </g> <!-- page 2 --> <g id="page_two"> <rect x="25" y="5" width="50" height="50" fill="white"></rect> <g transform="scale(2.9) translate(6,0)"> <g transform="scale(0.205)translate(1,1)"> <!-- 绑定动画到page_two的可见状态 --> <g> <!-- page_two可见时开始闪烁,隐藏时停止动画 --> <animate id="blink" attributeName="visibility" dur="2s" repeatCount="indefinite" keyTimes="0;0.5;1" values="visible;hidden;visible" begin="page_two_anim.begin+2s" end="page_two_anim.begin+4s"></animate> <!-- 确保page_two隐藏时元素保持hidden --> <set attributeName="visibility" to="hidden" begin="page_two_anim.begin"></set> <rect x="25" y="15" width="50" height="50" fill="black"></rect> </g> </g> </g> </g> <!-- animate page 1 & 2 --> <animate xlink:href="#page_one" attributeName="visibility" values="visible;hidden" dur="4s" begin="0s" repeatCount="indefinite"></animate> <animate xlink:href="#page_two" attributeName="visibility" values="hidden;visible" dur="4s" begin="0s" repeatCount="indefinite" id="page_two_anim"></animate> </g> </svg>
额外提示
- SVG的
visibility属性继承规则和CSS类似,但子元素被动画显式设置该属性时,会覆盖继承值,这是问题的核心原因。 - SVG中
<g>元素的z-index不生效,元素层级由文档中的绘制顺序决定,后出现的元素会覆盖前面的。
内容的提问来源于stack exchange,提问作者user1430489
相关产品推荐
相关产品推荐

