You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 19:07:02