如何在Safari中使用JavaScript的.animate方法?解决undefined错误
问题:Safari中使用
.animate()方法出现"undefined is not a function"错误 我尝试实现多个叶子的随机动画效果,以下是我的代码片段:
var leafs = document.querySelectorAll(".leaf"); leafs.forEach(function(leaf) { var angle = parseInt(leaf.getAttribute("data-angle")), posY = parseInt(leaf.getAttribute("data-top")), posX = parseInt(leaf.getAttribute("data-left")), directionX = Math.random() < 0.5 ? -1 : 1, directionY = Math.random() < 0.5 ? -1 : 1, newposX = directionX * Math.round(Math.random()*10) + posX, newposY = directionY * Math.round(Math.random()*10) + posY; // 后续调用leaf.animate(...)的代码 });
但在Safari中运行时,出现了“undefined is not a function”错误,请问该如何解决?
解决方案
嘿,这个问题我之前踩过坑!核心原因是Safari(尤其是旧版本)对原生Web Animations API的Element.animate()支持不完善,这就导致你调用leaf.animate()时,浏览器找不到这个方法,抛出了错误。下面给你几个可行的解决办法:
1. 先做特性检测,避免直接报错
先判断当前浏览器是否支持Element.animate,再执行对应的逻辑,这样至少不会在不支持的浏览器里直接崩掉:
var leafs = document.querySelectorAll(".leaf"); leafs.forEach(function(leaf) { // 前面的变量计算逻辑不变 var angle = parseInt(leaf.getAttribute("data-angle")), posY = parseInt(leaf.getAttribute("data-top")), posX = parseInt(leaf.getAttribute("data-left")), directionX = Math.random() < 0.5 ? -1 : 1, directionY = Math.random() < 0.5 ? -1 : 1, newposX = directionX * Math.round(Math.random()*10) + posX, newposY = directionY * Math.round(Math.random()*10) + posY; // 特性检测 if (Element.prototype.animate) { // 支持原生animate的浏览器,执行你的原有逻辑 leaf.animate([ { transform: `translate(${posX}px, ${posY}px) rotate(${angle}deg)` }, { transform: `translate(${newposX}px, ${newposY}px) rotate(${angle + Math.random()*20}deg)` } ], { duration: 1000, easing: 'ease-in-out', fill: 'forwards' }); } else { // 不支持的浏览器,执行降级逻辑 fallbackAnimate(leaf, posX, posY, newposX, newposY, angle); } });
2. 降级方案:用CSS动画替代原生JS animate
如果不想引入额外的polyfill,用CSS动画是最稳妥的方式,兼容性拉满:
首先定义CSS关键帧和变量:
@keyframes leafFloat { to { transform: translate(var(--target-x), var(--target-y)) rotate(var(--target-rotate)); } } .leaf { position: absolute; transition: none; /* 避免和动画冲突 */ } .leaf.floating { animation: leafFloat 1s ease-in-out forwards; }
然后在JS里设置变量并添加动画类:
function fallbackAnimate(leaf, posX, posY, newposX, newposY, angle) { // 设置初始位置 leaf.style.transform = `translate(${posX}px, ${posY}px) rotate(${angle}deg)`; // 设置目标位置的CSS变量 leaf.style.setProperty('--target-x', `${newposX}px`); leaf.style.setProperty('--target-y', `${newposY}px`); leaf.style.setProperty('--target-rotate', `${angle + Math.random()*20}deg`); // 添加动画类触发动画 leaf.classList.add('floating'); // 动画结束后可以移除类,方便下次触发 leaf.addEventListener('animationend', () => { leaf.classList.remove('floating'); }, { once: true }); }
3. 使用Web Animations API Polyfill
如果你坚持想用原生animate()方法,可以引入官方的polyfill来补全Safari的支持。你只需要在你的动画代码之前引入这个polyfill:
<script src="https://cdn.jsdelivr.net/npm/web-animations-js@2.3.2/web-animations.min.js"></script>
引入之后,Safari就能识别Element.animate()方法了,你的原有代码基本不需要修改就能正常运行。
内容的提问来源于stack exchange,提问作者Ado Ren
相关产品推荐
相关产品推荐

