SVG中animateTransform缩放及transform-origin在Safari的兼容问题
SVG 实现从下到上缩放:修复 Safari 兼容性问题
我之前也踩过这个坑!用 animateTransform 配合 transform-origin 做从下到上的缩放,Chrome 和 Firefox 都能正常渲染,但 Safari 偏不按预期来,非要从左上角开始缩放。查了相关文档确实发现,Safari 对 SVG 元素的 transform-origin 支持一直比较模糊,不像 HTML 元素那样稳定可靠。
问题根源
SVG 的坐标系统和常规 HTML 元素逻辑不同,transform-origin 在 SVG 里的解析规则和 HTML 存在差异,目前 Safari 还没完全对齐标准,导致设置 transform-origin: bottom center 后无法生效,缩放仍默认以左上角(SVG 坐标原点)为基准点。
解决方案:用复合变换替代 transform-origin
既然直接依赖 transform-origin 不靠谱,我们可以通过平移 + 缩放 + 反向平移的复合变换手动模拟从下到上的缩放效果,完全绕开 transform-origin,实现全浏览器兼容。
核心思路是:
- 先把元素的底部平移到 SVG 坐标原点(让我们想要的缩放原点对齐到默认变换原点)
- 执行 Y 轴方向的缩放动画
- 最后把元素平移回原位置
这样相当于手动将缩放原点定位到了元素底部,完美规避 Safari 的兼容性问题。
示例代码
假设我们有一个高度为 100px 的矩形,要实现从下到上的展开效果:
<svg width="120" height="120" viewBox="0 0 120 120"> <!-- 目标矩形:初始状态被压缩到底部 --> <rect x="10" y="10" width="100" height="100" fill="#4CAF50"> <!-- 复合变换动画:平移到底部 → 缩放 → 平移回原位 --> <animateTransform attributeName="transform" from="translate(0,100) scale(1,0) translate(0,-100)" to="translate(0,100) scale(1,1) translate(0,-100)" dur="1.5s" fill="freeze" /> </rect> </svg>
也可以拆分多个 animateTransform 用 additive="sum" 组合,效果完全一致:
<svg width="120" height="120" viewBox="0 0 120 120"> <rect x="10" y="10" width="100" height="100" fill="#4CAF50"> <!-- 第一步:将元素底部平移到原点 --> <animateTransform attributeName="transform" type="translate" from="0 100" to="0 100" dur="1.5s" fill="freeze" /> <!-- 第二步:执行Y轴缩放,叠加在平移之上 --> <animateTransform attributeName="transform" type="scale" from="1 0" to="1 1" additive="sum" dur="1.5s" fill="freeze" /> <!-- 第三步:平移回原位置,叠加在前两个变换之上 --> <animateTransform attributeName="transform" type="translate" from="0 -100" to="0 -100" additive="sum" dur="1.5s" fill="freeze" /> </rect> </svg>
注意点
- 平移距离要对应元素的实际高度,如果是动态高度,可以用 JS 通过
getBBox()获取元素高度值 - 若为圆形、路径等其他形状,只需把平移距离改成形状底部到顶部的垂直距离即可
这样修改后,Safari 就能正确渲染从下到上的缩放效果,和 Chrome、Firefox 表现完全一致!
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

