您的当前位置:首页>全部文章>文章详情

【UniApp】uniapp 定义动画的几种方式

CrazyPanda发表于:2023-12-12 18:07:12浏览:324次TAG:

本章的前提就是大家都知道动画的基本属性,例如
animation-nameanimation-durationanimation-timing-functionanimation-delayanimation-iteration-countanimation-direction 属性。

了解更多 animation 相关的内容。

现在制作一个左右抖动的动画效果,效果如下:

uniapp 中,可以通过如下两种方式来完成。

1. 直接使用 CSS 动画

1.1 定义动画

@keyframes shakeX {
  from,
  to {
    transform: translate3d(0, 0, 0);
  }

  10%,
  30%,
  50%,
  70%,
  90% {
    transform: translate3d(-10px, 0, 0);
  }

  20%,
  40%,
  60%,
  80% {
    transform: translate3d(10px, 0, 0);
  }
}

.shakeX {
  animation-name: shakeX;
  animation-duration: 1s;
}

1.2 使用

<view class="box shakeX"></view>
<style>
  .box {
    width: 100rpx;
    height: 100rpx;
    background-color: green;
  }
</style>

效果如下:

da437f455432e4353038dac2aade9e67.gif

2. 通过 uniapp 提供编程式创建动画

uniapp 提供 createAnimation 内置函数,用于创建一个动画实例 animation

动画定义步骤:

  • 创建动画实例

  • 调用实例的方法来描述动画

  • 通过动画实例的 export 方法导出动画数据

  • 导出的动画数据传递给组件的 animation 属性(uniapp 提供组件都支持 animation 属性)

兼容性列表:

AppH5微信小程序支付宝小程序百度小程序字节跳动小程序、飞书小程序QQ小程序快手小程序京东小程序
HBuilderX 2.0.4+xx

注意⚠️:

  • export方法每次调用后会清掉之前的动画操作。

  • nvue 暂不支持

2.1 定义动画

接下来通过编程实现上面抖动功能。

2.1.1 创建动画实例
const animation = uni.createAnimation(); // 定义动画实例
2.1.2 调用实例方法来描述动画

在上面的 shakeX 动画定义中,通过 translate3d 来定义动画。 对应的在 animation 实例中去查找与 translate3d 相关的实例方法。

translate 相关的实例方法,如下:

方法参数说明
translatetx,[ty]一个参数时,表示在X轴偏移tx,单位px;两个参数时,表示在X轴偏移tx,在Y轴偏移ty,单位px。
translateXtx在X轴偏移tx,单位px
translateYty在Y轴偏移ty,单位px
translateZtz在Z轴偏移tz,单位px
translate3d(tx,ty,tz)在X轴偏移tx,在Y轴偏移ty,在Z轴偏移tz,单位px

有了这些方法之后,我们可以描述动画啦~

@keyframes shakeX {
  from,
  to {
    transform: translate3d(0, 0, 0);
  }

  10%,
  30%,
  50%,
  70%,
  90% {
    transform: translate3d(-10px, 0, 0);
  }

  20%,
  40%,
  60%,
  80% {
    transform: translate3d(10px, 0, 0);
  }
}

上面 CSS 中 translate3d,对应到编程方式如下:

animation.translate3d(0, 0, 0); // 原始位置
animation.translate3d(-10, 0, 0); // 向左偏移
animation.translate3d(10, 0, 0); // 像右偏移

有上面方法后,可以把动画描述出来,如下:

animation.animation3d(0, 0, 0) // 0%
    .animation3d(-10, 0, 0) // 10%
    .animation3d(10, 0, 0) // 20%
    .animation3d(-10, 0, 0) // 30%
    // ...
    .animation3d(0, 0, 0); // 100%

现在通过 export() 方法导出定义动画:

<template>
    <view class="box" :animation="animationData"></view>
</template>
export default {
  data() {
    return {
        animationData: {}
    }
  },
  onLoad(){
    const animation = uni.createAnimation();
    animation.animation3d(0, 0, 0) // 0%
        .animation3d(-10, 0, 0) // 10%
        .animation3d(10, 0, 0) // 20%
        .animation3d(-10, 0, 0) // 30%
        // ...
        .animation3d(0, 0, 0); // 100%
    this.animationData = animation.export();
  }
}

代码运行之后,并没有如期出现预期抖动效果。为什么? 因为 uniapp 中在定义的一组动画中是并行执行的,所以并不会产生动画效果。

再回过来,看上面 CSS 中把一个动画周期划分成不同的组(步骤),10% 时执行 translate3d(-10px, 0, 0)20% 时执行translate3d(10px, 0, 0)

在 uni-app 中有没有类似的方式呢? 通过 step 来定义。

   animation
    .translateX(0) // 0%
    .translateX(10) // 20%
    .step();
  animation.translateX(-10).step(); // 30%
  animation.translateX(10).step(); // 40%
  animation.translateX(-10).step(); // 50%
  animation.translateX(10).step(); // 60%
  animation.translateX(-10).step(); // 70%
  animation.translateX(10).step(); // 80%
  animation.translateX(-10).step(); // 90%
  animation.translateX(0).step(); // 100%
  this.animationData = animation.export();

再来执行代码,发现会动了。

da437f455432e4353038dac2aade9e67.gif

从效果来看发现跟预期效果差很多,为什么? 跟 animationanimation-duration 属性有关。

animation-duration: 属性指定一个动画周期的时长。

也就是一组动画运行完所需时间。 在 uni.createAnimation() 创建动画时可以传递参数,在不显示的指定 duration 值时,默认值为 400ms。 而 step() 会继承该值。

参数类型必填默认值说明
durationInteger400动画持续时间,单位ms
timingFunctionString“linear”定义动画的效果
delayInteger0动画延迟时间,单位 ms
transformOriginString“50% 50% 0”设置transform-origin

这就是 “慢” 的原因。

在明白“慢”之后,只要把动画执行时间 (duration) 调整,应该能看到预期效果。假设期望完成抖动时间 1s,把动画拆分成 10 组,则每一组的动画时间为 100 ms.

现在指定 stepduration 值为 100ms,更改后代码如下:

  animation
    .translateX(0) // 0%
    .translateX(10) // 20%
    .step({
      duration: 100,
    });

  animation.translateX(-10).step({
    duration: 100,
  }); // 30%

  animation.translateX(10).step({
    duration: 100,
  }); // 40%

  animation.translateX(-10).step({
    duration: 100,
  });

  // 50%
  animation.translateX(10).step({
    duration: 100,
  }); // 60%

  animation.translateX(-10).step({
    duration: 100,
  }); // 70%

  animation.translateX(10).step({
    duration: 100,
  }); // 80%

  animation.translateX(-10).step({
    duration: 100,
  }); // 90%

  animation.translateX(0).step({
    duration: 100,
  });
  this.animationData = animation.export();

再来执行代码,运行效果如下:

da437f455432e4353038dac2aade9e67.gif

发现效果基本与预期效果一样了。

更多 uni.createAnimation() 相关的内容,可以自行查看文档

3. 什么情况下使用编程式创建动画

当不能通过 css 方式或通过动态类名一些方式去添加动画时,此时就可以考虑使用编程式来创建动画。编程式可以很灵活创建动画、控制动画运行和监听动画的结束。 其次从兼容列表来看,能很好在不同平台运行。

现在看个实际例子: 在登录时,通常需要 ☑️ 选用户协议和隐私政策 之后才允许用户登录。现在产品希望当用户在未勾选时点击登录,希望通过抖动 用户协议和隐私政策来提醒用户。

da437f455432e4353038dac2aade9e67.gif

上面需求需要完成几个功能点:

  • 定义抖动动画类

  • 未勾选时动态添加动画类

  • 动画结束时移除动画类(用户下一次点击时,需要继续抖动)

通常可以这样做:

  <view ref="agreement" class="agreement" :class="{ 'shakeX': actived }">
      <radio
        @click="onChecked"
        style="transform: scale(0.6)"
        :color="color"
        :checked="agreement"
      ></radio>
      我已阅读并同意<text class="service"
        >用户协议</text
      >和<text class="privacy">隐私政策</text>
</view>
<button @click="onLogin">登录</button>
export default {
      data() {
        return {
            actived: false // false
        };
      },
      mounted(){
	this.$refs.agreement.$el.addEventListener("animationend", ()=> {
            this.actived = false; // 动画结束移除类
	});
      },
      methods: {
          onLogin(){
             // 动态添加
             this.actived = true;
          }
      },
 };
@keyframes shakeX {
  from,
  to {
    transform: translate3d(0, 0, 0);
  }

  10%,
  30%,
  50%,
  70%,
  90% {
    transform: translate3d(-10px, 0, 0);
  }

  20%,
  40%,
  60%,
  80% {
    transform: translate3d(10px, 0, 0);
  }
}

.shakeX {
  animation-name: shakeX;
  animation-duration: 1s;
}

发现在 app小程序 上运行时,发现 this.$refs.agreement.$el 为空,这是为什么,这里就是跟 uniapp 底层设计有关,如下图所示:

7df092cad0b78c6c9aa32f67e90f4df9.png

上面引用微信小程序,uniapp 在设计跟小程序是一样的。 也可以在上底层设计链接中了解到 uniapp 设计。

如果不能获取元素并注册animationend事件,没办法很好知道动画结束,不知道何时应该移除。当然有的人想可以通过定时器完成,这样不能精细话控制。

此时通过编程式就可以很好解决兼容的问题,现在稍微调整下:

 <view class="agreement" :animation="animationData">
      <radio
        @click="onChecked"
        style="transform: scale(0.6)"
        :color="color"
        :checked="agreement"
      ></radio>
      我已阅读并同意<text class="service"
        >用户协议</text
      >和<text class="privacy">隐私政策</text>
</view>
<button @click="onLogin">登录</button>
export default {
      data() {
        return {
            animationData: {}
        };
      },
      onLoad(){
	const animation = uni.createAnimation({
          timingFunction: "linear",
        });
        this.animation = animation;
      },
      methods: {
          shakeX() {
              const animation = this.animation;
              animation
                .translateX(0) // 0%
                .translateX(10) // 20%
                .step({
                  duration: 100,
                });

              animation.translateX(-10).step({
                duration: 100,
              }); // 30%

              animation.translateX(10).step({
                duration: 100,
              }); // 40%

              animation.translateX(-10).step({
                duration: 100,
              });

              // 50%
              animation.translateX(10).step({
                duration: 100,
              }); // 60%

              animation.translateX(-10).step({
                duration: 100,
              }); // 70%

              animation.translateX(10).step({
                duration: 100,
              }); // 80%

              animation.translateX(-10).step({
                duration: 100,
              }); // 90%

              animation.translateX(0).step({
                duration: 100,
              });
              this.animationData = animation.export();
          },
          onLogin(){
             this.shakeX();
          }
      },
 };

通过编程方式,为什么不需要像动态类名的方式,动画结束必须移除类名否则下次不会生效? 这里留给大家去思考了。

4. 总结

  • 具体采用哪种方式创建动画,可以根据实际业务场景来定。

  • uniapp 编程方式,通过 step 来进行动画分组,同一个分组内动画函数会并行执行。

  • 多个动画分组之间的执行是串行的,也就是需等待上一个结束才会执行下一个。


猜你喜欢

【UniApp】如何在uniapp中实现智能推荐和个性化推送
如何在uniapp中实现智能推荐和个性化推送随着移动互联网的快速发展,用户在使用手机应用的过程中,希望能够得到个性化、智能化的推荐服务。在uniapp框架中,我们可以利用一些常用的技术手段,实现智能推荐和个性化推送功能。本文将介绍如何在uniapp中实现这两个功能,并提供具体的代码示例。一、智能推荐算法智能推荐是一种根据用户的行为和偏好,自动给用户推荐最相关的内容。常见的智能推荐算法有基于协同过滤的算法、基于内容的算法和基于深度学习的算法。在uniapp中,我们可以使用uniCloud
发表于:2023-12-24 浏览:340 TAG:
【UniApp】如何在uniapp中实现倒计时和闹钟功能
如何在uniapp中实现倒计时和闹钟功能一、倒计时功能的实现:倒计时功能在实际开发中非常常见,可以用于实现各种倒计时功能,如验证码倒计时、秒杀倒计时等。下面通过uniapp框架来介绍如何实现倒计时功能。在uniapp项目中创建一个倒计时组件,可以命名为Countdown.vue。在Countdown.vue中,我们可以定义一个倒计时的变量和一个计时器的标志位,如下所示:&lt;template&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;div&gt;{{&amp;nbs
发表于:2023-12-24 浏览:350 TAG:
【UniApp】uniapp怎么去除子页面的左侧返回
随着移动设备在人们生活中使用越来越广泛,移动应用的需求也愈发增长。近年来,由于跨端技术的发展,多端混合应用开发成为了主流,uniapp就是其中的佼佼者。然而,在开发uniapp应用时,我们可能会遇到一些问题,比如如何去除子页面的左侧返回按钮。在uniapp中,每当我们打开一个新的页面,都会在左上角出现一个返回按钮,点击该按钮即可返回到上一页。但是,如果我们在某些场景中不希望显示这个返回按钮,就需要去除它。下面,我将介绍两种方法来实现这一功能。一、使用导航栏组件uniapp提供了一个导航
发表于:2023-12-25 浏览:306 TAG:
【UniApp】uniapp 中使用addEventListener
uniapp 中使用 addEventListener 方法可以给某个元素绑定事件监听。使用方法:document.getElementById(&quot;some-element&quot;).addEventListener(&quot;click&quot;,&nbsp;function()&nbsp;{ &nbsp;&nbsp;//&nbsp;do&nbsp;something&nbsp;when&nbsp;the&nbsp;element&nbsp;is&nbsp;clicked }
发表于:2023-12-13 浏览:539 TAG:
【UniApp】如何在uniapp中集成第三方登录功能
如何在uniapp中集成第三方登录功能在现如今的社交媒体时代,第三方登录功能已经成为了许多应用程序中不可或缺的一部分。通过集成第三方登录功能,可以方便用户使用其它平台的账号来快速登录并使用应用程序。本文将以uniapp为例,介绍如何在uniapp中集成第三方登录功能,并提供具体的代码示例。创建第三方开放平台应用首先,您需要在相应的第三方开放平台注册并创建一个应用。常见的第三方登录平台有微信、QQ、微博等。在注册应用时,您将获得相关的应用ID和密钥,这些信息将用于后续集成中。安装unia
发表于:2023-12-24 浏览:373 TAG:
【UniApp】Uniapp怎么动态更改tabbar
Uniapp是一款跨端开发框架,可以同时开发出H5、小程序、app等多个平台的应用,是非常实用的开发工具。其中,tabbar是作为底部导航栏来展示多个页面的重要控件之一。在开发过程中,有时需要根据不同的业务需求动态更改tabbar,本文将介绍如何在Uniapp中实现动态更改tabbar的方法。一、tabbar的基本使用及结构在Uniapp中使用tabbar,需要在pages.json文件中设置底部导航栏的样式和页面路径。示例代码如下:&quot;tabBar&quot;:&nbsp;{
发表于:2023-12-25 浏览:475 TAG:
【UniApp】uniapp实现如何使用JSBridge实现与原生交互
uniapp实现如何使用JSBridge实现与原生交互,需要具体代码示例一、背景介绍在移动应用开发中,有时需要与原生环境进行交互,比如调用原生的一些功能或获取原生的一些数据。uniapp作为一种跨平台的移动应用开发框架,提供了一种方便的方式来实现与原生交互,即使用JSBridge进行通信。JSBridge是一种前端与移动原生端进行交互的技术方案,通过在前端和原生端分别实现一个桥梁,使得前端可以调用原生的方法和获取原生的数据,同时原生也可以通过桥梁向前端发送消息。二、JSBridge的实
发表于:2023-12-24 浏览:516 TAG:
【UniApp】uniapp及vue中动画功能实现方案
需求场景:实际开发过程中,我们经常遇到各类比较炫酷的动画开发,比如简单的echarts插件使用,animation动画等...动画实现方案:1.css动画,如gif,a-png,animation,transform等animation:&nbsp;handleAni&nbsp;1s&nbsp;linear&nbsp;infinite; @keyframes&nbsp;handleAni&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;0%&nbsp;{&nbsp;//css样式&amp;
发表于:2023-12-12 浏览:376 TAG:
【UniApp】uniapp中路由传参的加密与解密方式
uniapp中路由传参的加密与解密方式,需要具体代码示例【引言】在uniapp开发中,经常会遇到一种情况,就是需要将一些敏感信息通过路由进行传递,但是传递的参数是明文,有一定的安全风险。为了保护用户数据的安全性,我们可以对路由传参进行加密和解密处理,以增加数据的安全性。本文将介绍uniapp中路由传参的加密与解密方式,并提供实际代码示例。【加密方式】在uniapp中,可以使用常见的加密算法(如AES、RSA等)对传递的参数进行加密,以保护数据的安全性。下面以AES算法为例,介绍加密的方式及代码示
发表于:2024-04-03 浏览:335 TAG:
【UniApp】如何在uniapp中实现图片上传和预览
如何在uniapp中实现图片上传和预览在现代社交网络和电子商务应用中,图片上传和预览功能是非常常见的需求。本文将介绍如何在uniapp中实现图片上传和预览的功能,并给出具体的代码示例。一、图片上传功能的实现在uniapp项目中,首先需要在页面中添加一个图片上传组件,如下所示:&lt;template&gt; &nbsp;&nbsp;&lt;view&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;image&nbsp;v-for=&quot;(item,&nbsp;in
发表于:2023-12-11 浏览:421 TAG: