iOS设备中CSS动画失效的汉堡菜单修复方案咨询
问题
我用自定义HTML、CSS和JS实现了一个带动画效果的汉堡菜单,动画在Android设备上正常,但iOS设备完全不生效。已经尝试给CSS各部分加了-webkit前缀,问题依然存在,求修复方法。
代码片段
JS代码
var state = 0; var icona = document.getElementById("icon"); var path = document.getElementById("mypath"); icona.addEventListener("click", function(event) { event.preventDefault(); if (state == 0) { path.classList.remove('shape2'); path.classList.add('shape1'); state = 1; console.log("shape1"); } else { path.classList.remove('shape1'); path.classList.add('shape2'); state = 0; console.log("shape2"); } }); icona.addEventListener("touchstart", function(event) { event.preventDefault(); if (state == 0) { path.classList.remove('shape2'); path.classList.add('shape1'); state = 1; console.log("shape1"); } else { path.classList.remove('shape1'); path.classList.add('shape2'); state = 0; console.log("shape2"); } });
CSS代码
body { background-color: black; font-family: sans-serif; } .shape1 { -webkit-animation: webkit-apertura 800ms ease-in-out forwards; animation: apertura 800ms ease-in-out forwards; } .shape2 { -webkit-animation: webkit-chiusura 800ms ease-in-out forwards; animation: chiusura 800ms ease-in-out forwards; } @-webkit-keyframes webkit-apertura { 0% { d: path("M 1 1 L 16 1 M 16 1 L 31 1 M 1 11 L 16 11 M 16 11 L 31 11 M 1 21 L 16 21 M 16 21 L 31 21"); } 50% { d: path("M 1 11 L 16 1 M 16 1 L 31 11 M 1 11 L 16 11 M 16 11 L 31 11 M 1 11 L 16 21 M 16 21 L 31 11"); } 100% { d: path("M 16 11 L 6 1 M 26 1 L 16 11 M 16 11 L 16 11 M 16 11 L 16 11 M 16 11 L 6 21 M 26 21 L 16 11"); } } @keyframes apertura { 0% { d: path("M 1 1 L 16 1 M 16 1 L 31 1 M 1 11 L 16 11 M 16 11 L 31 11 M 1 21 L 16 21 M 16 21 L 31 21"); } 50% { d: path("M 1 11 L 16 1 M 16 1 L 31 11 M 1 11 L 16 11 M 16 11 L 31 11 M 1 11 L 16 21 M 16 21 L 31 11"); } 100% { d: path("M 16 11 L 6 1 M 26 1 L 16 11 M 16 11 L 16 11 M 16 11 L 16 11 M 16 11 L 6 21 M 26 21 L 16 11"); } } @keyframes chiusura { 0% { d: path("M 16 11 L 6 1 M 26 1 L 16 11 M 16 11 L 16 11 M 16 11 L 16 11 M 16 11 L 6 21 M 26 21 L 16 11"); } 50% { d: path("M 1 11 L 16 1 M 16 1 L 31 11 M 1 11 L 16 11 M 16 11 L 31 11 M 1 11 L 16 21 M 16 21 L 31 11"); } 100% { d: path("M 1 1 L 16 1 M 16 1 L 31 1 M 1 11 L 16 11 M 16 11 L 31 11 M 1 21 L 16 21 M 16 21 L 31 21"); } } @-webkit-keyframes webkit-chiusura { 0% { d: path("M 16 11 L 6 1 M 26 1 L 16 11 M 16 11 L 16 11 M 16 11 L 16 11 M 16 11 L 6 21 M 26 21 L 16 11"); } 50% { d: path("M 1 11 L 16 1 M 16 1 L 31 11 M 1 11 L 16 11 M 16 11 L 31 11 M 1 11 L 16 21 M 16 21 L 31 11"); } 100% { d: path("M 1 1 L 16 1 M 16 1 L 31 1 M 1 11 L 16 11 M 16 11 L 31 11 M 1 21 L 16 21 M 16 21 L 31 21"); } }
HTML代码
<div style="color:white">touch or click to animate</div> <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 20" id="icon"> <path id="mypath" d="M 1 1 L 16 1 M 16 1 L 31 1 M 1 11 L 16 11 M 16 11 L 31 11 M 1 21 L 16 21 M 16 21 L 31 21" fill="none" stroke="white" stroke-width="1" /> </svg>
解决方案
核心问题是iOS Safari不支持通过CSS动画修改SVG <path>的d属性,加-webkit前缀无法解决这个兼容性问题,改用SVG原生的SMIL动画即可修复。
修复步骤
1. 替换CSS动画为SVG SMIL动画
在SVG内部添加<animate>元素,定义路径切换的动画逻辑,这是iOS支持更好的原生方案:
<div style="color:white">touch or click to animate</div> <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 20" id="icon"> <path id="mypath" d="M 1 1 L 16 1 M 16 1 L 31 1 M 1 11 L 16 11 M 16 11 L 31 11 M 1 21 L 16 21 M 16 21 L 31 21" fill="none" stroke="white" stroke-width="1" /> <!-- 打开菜单动画 --> <animate id="openAnim" attributeName="d" values="M 1 1 L 16 1 M 16 1 L 31 1 M 1 11 L 16 11 M 16 11 L 31 11 M 1 21 L 16 21 M 16 21 L 31 21; M 1 11 L 16 1 M 16 1 L 31 11 M 1 11 L 16 11 M 16 11 L 31 11 M 1 11 L 16 21 M 16 21 L 31 11; M 16 11 L 6 1 M 26 1 L 16 11 M 16 11 L 16 11 M 16 11 L 16 11 M 16 11 L 6 21 M 26 21 L 16 11" dur="800ms" fill="freeze" begin="indefinite" /> <!-- 关闭菜单动画 --> <animate id="closeAnim" attributeName="d" values="M 16 11 L 6 1 M 26 1 L 16 11 M 16 11 L 16 11 M 16 11 L 16 11 M 16 11 L 6 21 M 26 21 L 16 11; M 1 11 L 16 1 M 16 1 L 31 11 M 1 11 L 16 11 M 16 11 L 31 11 M 1 11 L 16 21 M 16 21 L 31 11; M 1 1 L 16 1 M 16 1 L 31 1 M 1 11 L 16 11 M 16 11 L 31 11 M 1 21 L 16 21 M 16 21 L 31 21" dur="800ms" fill="freeze" begin="indefinite" /> </svg>
2. 简化JS逻辑
不再通过添加CSS类触发动画,直接控制SVG动画的播放状态:
var state = 0; var icona = document.getElementById("icon"); var openAnim = document.getElementById("openAnim"); var closeAnim = document.getElementById("closeAnim"); function toggleMenu() { if (state === 0) { // 重置关闭动画并播放打开动画 closeAnim.pause(); closeAnim.beginElement(); openAnim.beginElement(); state = 1; console.log("menu opened"); } else { // 重置打开动画并播放关闭动画 openAnim.pause(); openAnim.beginElement(); closeAnim.beginElement(); state = 0; console.log("menu closed"); } } icona.addEventListener("click", function(event) { event.preventDefault(); toggleMenu(); }); icona.addEventListener("touchstart", function(event) { event.preventDefault(); toggleMenu(); });
3. 清理无用CSS代码
删除原CSS中所有和.shape1、.shape2及对应的@keyframes相关的代码,只保留基础样式:
body { background-color: black; font-family: sans-serif; }
原理说明
SMIL是SVG原生的动画规范,iOS Safari对其支持度远高于CSS修改SVG属性的特性,因此替换后动画能在iOS和Android上正常生效。
内容的提问来源于stack exchange,提问作者Antonio
相关产品推荐
相关产品推荐

