uni-app 使用 setup 做动画效果时,安卓正常,iOS只能做一次。

发布于 1周前 作者 eggper 来自 Uni-App

uni-app 使用 setup 做动画效果时,安卓正常,iOS只能做一次。

开发环境 版本号 项目创建方式
Mac 13.5 HBuilderX

产品分类:uniapp/App

PC开发环境操作系统:Mac

HBuilderX类型:正式

HBuilderX版本号:4.24

手机系统:iOS

手机系统版本号:iOS 17

手机厂商:模拟器

手机机型:SE

页面类型:vue

vue版本:vue3

打包方式:云端

示例代码:

```html
<template>  
  <view style="flex: 1;" >  
    <view  
      class="base-style transition-transform"  
      :class="{ 'translate': isTransformTranslate }"  
      @click="changeTransformTranslate"  
    ></view>  
  </view>  
</template>  

<script setup>  
const isTransformTranslate = ref(false);  

const changeTransformTranslate = () => {  
  isTransformTranslate.value = !isTransformTranslate.value;  
};  
</script>  

<style>  
.base-style {  
  width: 200px;  
  height: 200px;  
  background-color: brown;  
}  

.transition-transform {  
  transition-property: transform;  
  transition-duration: 1s;  
}  

.translate {  
  transform: translate(0, 100%);  
}  
</style>
```
```

操作步骤:
- iOS在模拟器运行,点击view做动画效果

预期结果:
- iOS在模拟器运行,view可以来回点击

实际结果:
- iOS在模拟器运行,view只能点击一次

bug描述:
参考 https://doc.dcloud.net.cn/uni-app-x/css/transition.html 中的教程,把其中的`点击修改TransformTranslate`代码由选项式改为组合式,并把动画改为css效果。安卓运行正常,iOS在模拟器上只能点击一次,做一次动画,再点击无效。代码如下:

1 回复

在使用uni-app开发跨平台应用时,如果发现在iOS上动画效果只能执行一次,而在安卓上表现正常,这通常与事件绑定、状态更新或动画库的兼容性问题有关。以下是一个使用Vue 3的Composition API(即setup语法)实现的简单动画效果示例,并附带了一些可能的解决方案,以确保动画在iOS上也能正常多次执行。

示例代码

首先,确保你的uni-app项目已经配置好支持Vue 3和Composition API。

<template>
  <view class="container">
    <button @click="startAnimation">Start Animation</button>
    <view class="box" :style="boxStyle"></view>
  </view>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';

const boxStyle = ref({
  transform: 'translateX(0)',
  transition: 'transform 0.5s ease'
});

let animationFrameId = null;

const startAnimation = () => {
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId); // 防止重复动画
  }

  let position = 0;
  const animate = () => {
    position = (position + 10) % 300; // 模拟移动范围0-300px
    boxStyle.value.transform = `translateX(${position}px)`;
    animationFrameId = requestAnimationFrame(animate);
  };

  // 使用requestAnimationFrame来确保动画平滑
  animationFrameId = requestAnimationFrame(animate);
};

onUnmounted(() => {
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId);
  }
});
</script>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.box {
  width: 50px;
  height: 50px;
  background-color: red;
}

button {
  margin-bottom: 20px;
}
</style>

解决思路

  1. 使用requestAnimationFrame:确保动画在iOS上也能平滑运行,避免使用简单的setIntervalsetTimeout,因为requestAnimationFrame与浏览器的渲染周期更同步。

  2. 清理动画帧:在组件卸载或重新开始动画前,确保使用cancelAnimationFrame来清理之前的动画帧,避免潜在的内存泄漏或动画冲突。

  3. 状态管理:确保动画状态(如位置、速度等)被正确管理,避免由于状态更新不当导致的动画中断。

  4. 测试与调试:使用真机测试,特别是iOS设备,因为模拟器可能无法完全模拟真机的行为。使用开发者工具查看控制台输出,检查是否有错误或警告。

通过上述方法,你应该能够解决iOS上动画只能执行一次的问题。如果问题依旧存在,可能需要检查uni-app或Vue 3的相关issue,看是否有已知的兼容性问题。

回到顶部