两种方案开发小程序动画

2018-11-09 admin

在普通的网页开发中,动画效果可以通过css3来实现大部分需求,在小程序开发中同样可以使用css3,同时也可以通过api方式来实现。

指路:小程序animatiom动画API

API解读

小程序中,通过调用api来创建动画,需要先创建一个实例对象。这个对象通过wx.createAnimation返回,animation的一系列属性都基于这个实例对象。

创建这个对象

    let animation = wx.createAnimation({
        duration: 2000,
        delay: 0,
        timingFunction: "linear",
    });

这个animation就是通过wx.createAnimation之后返回的实例。在创建过程中,可以给这个实例添加一些属性,如以上代码所示,等同于css3animation:$name 2s linear的写法。

添加动效

实例创建完成之后,基于该实例,添加需要的动态效果,动态类型可以查阅文档得知,以最常见的移动,旋转为例:

    animation.translate($width, 0).rotate($deg);

结束动画

.step()表示一组动画的结束

    animation.step();

导出动画

动画效果添加完成了,如何给想要的dom添加动效呢。这里需要用到.export()导出动画队列,赋值给某个dom对象。

    this.setData({ moveOne: animation.export() })
    <view  animation="{{moveOne}}"></view>

例子

以下将通过2组动画,来对比一下css3api实现方式的不同。

一、模块移动动画

动画效果:

下图有两组动画,分别为api方式(上)与css3方式(下)完成的效果,点击move按钮,动画启动。

image

代码实现

以下分别为css3api的核心代码:

css3:
    <!-- wxml -->
    <view class='border'>
        <view class='css-block {{isMove && "one"}}'></view>
        <view class='css-block {{isMove && "two"}}'></view>
        <view class='css-block {{isMove && "three"}}'></view>
        <view class='css-block {{isMove && "four"}}'></view>
    </view>
    // scss
    @mixin movePublic($oldLeft,$oldTop,$left,$top) {
        from {
          transform:translate($oldLeft,$oldTop);
        }
        to {
          transform:translate($left,$top);
        }
    }

    @mixin blockStyle($color,$name) {
        background: $color;
        animation:$name 2s linear infinite alternate;
    }
    .one {
        @include blockStyle(lightsalmon,onemove);
    }

    @keyframes onemove {
        @include movePublic(50rpx,-25rpx,-150rpx,0rpx);
    }

    .two {
        @include blockStyle(lightblue,twomove);
    }

    @keyframes twomove {
        @include movePublic(0rpx,25rpx,-50rpx,0rpx);
    }

    .three {
        @include blockStyle(lightgray,threemove);
    }

    @keyframes threemove {
        @include movePublic(0rpx,25rpx,50rpx,0rpx);
    }

    .four {
        @include blockStyle(grey,fourmove);
    }

    @keyframes fourmove {
        @include movePublic(-50rpx,-25rpx,150rpx,0rpx);
    }
    // js
    moveFunction(){
        this.setData({
            isMove: true
        })
    }

css3中通过动态改变class类名来达到动画的效果,如上代码通过onetwothreefour来分别控制移动的距离,通过sass可以避免代码过于冗余的问题。(纠结如何在小程序中使用sass的童鞋请看这里哦:wechat-mina-template

api:
    moveClick(){
        this.move(-75,-12.5,25,'moveOne');
        this.move(-25,12.5, 0,'moveTwo');
        this.move(25, 12.5,0,'moveThree');
        this.move(75, -12.5,-25,'moveFour');
        this.moveFunction(); // 该事件触发css3模块进行移动
    },

    // 模块移动方法
    move: function (w,h,m,ele) {
        let self = this;
        let moveFunc = function () {
        let animation = wx.createAnimation({
            duration: 2000,
            delay: 0,
            timingFunction: "linear",
        });

        animation.translate(w, 0).step()
        self.setData({ [ele]: animation.export() })
        let timeout = setTimeout(function () {
            animation.translate(m, h).step();
            self.setData({
                // [ele] 代表需要绑定动画的数组对象
                [ele]: animation.export()
            })
          }.bind(this), 2000)
        }
        moveFunc();
        let interval = setInterval(moveFunc,4000)
    }

效果图可见,模块之间都是简单的移动,可以将他们的运动变化写成一个公共的事件,通过向事件传值,来移动到不同的位置。其中的参数w,h,m,ele分别表示发散水平方向移动的距离、聚拢时垂直方向、水平方向的距离以及需要修改animationData的对象。

通过这种方法产生的动画,无法按照原有轨迹收回,所以在事件之后设置了定时器,定义在执行动画2s之后,执行另一个动画。同时动画只能执行一次,如果需要循环的动效,要在外层包裹一个重复执行的定时器到。

查看源码,发现api方式是通过js插入并改变内联样式来达到动画效果,下面这张动图可以清晰地看出样式变化。

代码变化

打印出赋值的animationDataanimates中存放了动画事件的类型及参数;options中存放的是此次动画的配置选项,transition中存放的是wx.createAnimation调用时的配置,transformOrigin是默认配置,意为以对象的中心为起点开始执行动画,也可在wx.createAnimation时进行配置。

animationData

二、音乐播放动画

上面的模块移动动画不涉及逻辑交互,因此新尝试了一个音乐播放动画,该动画需要实现暂停、继续的效果。

动画效果:

播放音乐

两组不同的动画效果对比,分别为api(上)实现与css3实现(下):

旋转对比

代码实现

以下分别是css3实现与api实现的核心代码:

css3:
    <!-- wxml -->
    <view class='music musicTwo musicRotate {{playTwo ? " ": "musicPaused"}} ' bindtap='playTwo'>
        <text class="iconfont has-music" wx:if="{{playTwo}}"></text>
        <text class="iconfont no-music" wx:if="{{!playTwo}}"></text>
    </view>
    // scss
    .musicRotate{
        animation: rotate 3s linear infinite;
    }

    @keyframes rotate{
        from{
            transform: rotate(0deg)
        }
        to{
            transform: rotate(359deg)
        }
    }

    .musicPaused{
        animation-play-state: paused;
    }
    // js
    playTwo(){
        this.setData({
            playTwo: !this.data.playTwo
        },()=>{
            let back = this.data.backgroundAudioManager;
            if(this.data.playTwo){
                back.play();
            } else {
                back.pause();
            }
        })
    }

通过playTwo这个属性来判断是否暂停,并控制css类的添加与删除。当为false时,添加.musicPaused类,动画暂停。

api:
    <!-- wxml -->
    <view class='music' bindtap='play'  animation="{{play && musicRotate}}">
        <text class="iconfont has-music" wx:if="{{play}}"></text>
        <text class="iconfont no-music" wx:if="{{!play}}"></text>
    </view>
    // js
    play(){
        this.setData({
            play: !this.data.play
        },()=>{
            let back = this.data.backgroundAudioManager;
            if (!this.data.play) {
                back.pause();
               // 跨事件清除定时器
               clearInterval(this.data.rotateInterval);
            } else {
                back.play();
                // 继续旋转,this.data.i记录了旋转的程度
                this.musicRotate(this.data.i);
            }
        })
    },
    musicRotate(i){
        let self = this;
        let rotateFuc = function(){
            i++;
            self.setData({
                i:i++
            });
            let animation = wx.createAnimation({
                duration: 1000,
                delay: 0,
                timingFunction: "linear",
            });
            animation.rotate(30*(i++)).step()
            self.setData({ musicRotate: animation.export() });
        }
        rotateFuc();
        let rotateInterval = setInterval(
            rotateFuc,1000
        );
        // 全局定时事件
        this.setData({
            rotateInterval: rotateInterval
        })
    }

通过api实现的方式是通过移除animationData来控制动画,同时暂停动画也需要清除定时器,由于清除定时器需要跨事件进行操作,所以定了一个全局方法rotateInterval

api方式定义了旋转的角度,但旋转到该角度之后便会停止,如果需要实现重复旋转效果,需要通过定时器来完成。因此定义了变量i,定时器每执行一次便加1,相当于每1s旋转30°,对animation.rotate()中的度数动态赋值。暂停之后继续动画,需要从原有角度继续旋转,因此变量i需要为全局变量。

代码变化

下图可以看出,api方式旋转是通过不断累加角度来完成,而非css3中循环执行。

代码对比

对比

通过上述两个小例子对比,无论是便捷度还是代码量,通过css3来实现动画效果相对来说是更好的选择。api方式存在较多局限性:

  1. 动画只能执行一次,循环效果需要通过定时器完成。
  2. 无法按照原有轨迹返回,需要返回必须定义定时器。
  3. 频繁借助定时器在性能上有硬伤。

综合以上,推荐通过css3来完成动画效果。

广而告之

本文发布于薄荷前端周刊,欢迎Watch & Star ★,转载请注明出处。

欢迎讨论,点个赞再走吧 。◕‿◕。 ~

原文链接:https://segmentfault.com/a/1190000016964098

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-45006.html

文章标题:两种方案开发小程序动画

相关文章
Html5 是否适合移动应用开发
HTML5最近这几年声誉鹊起,而基于HTML5技术的产品也风生水起。感觉现在你的产品要是不和HTML5沾点边,都不好意思和客户打招呼!移动应用开发中,HTML5更是不可或缺的角色,市面上不少移动应用中间件产品都号称支持HTML5,例如APP...
2015-11-12
关于Ajax应用开发需要注意的事项
接触Ajax,那时候的Ajax支持还不是很好,都要涉及底层,没有现成的框架给你调用。现在把常见的问题列举如下。 [b]1、编码问题[/b] 注意AJAX要取的文件是UTF-8编码的。GB2312编码传回BROWSE后中文会乱码。如果用VBS...
2015-11-11
HTML5移动应用开发的12大特性
1.离线缓存为HTML5开发移动应用提供了基础 HTML5 Web Storage API可以看做是加强版的cookie,不受数据大小限制,有更好的弹性以及架构,可以将数据写入到本机的ROM中,还可以在关闭浏览器后再次打开时恢复数据,以减少...
2015-11-11
百度新功能【特效搜索】演示 惊呆了小伙伴
百度搜索最近又出新玩意新功能了,可能你还没有发现,名为【百度特效搜索】已经默默上线了,有什么效果呢? 在百度搜索中根据用户搜索的关键词来出发某些动作,例如笔者搜索“打雷”关键字,在搜索结果中你会听到有打雷声, 黑洞,闪烁、翻转、跳跃,打雷,...
2015-11-12
哪些互联网产品适合用HTML5开发?
J.P. Morgan(摩根大通集团)不久前发布了有关2013年互联网公司股票的研究报告,其中在预测2013年趋势时,提及移动互联网有关web和app之间的辩论将在3到5年内继续,而摩根认为这对于搜索产品和谷歌是利好消息,因为用户需要处理复...
2015-11-12
Node.js v0.11.16 开发版发布
Node.js v0.11.16 开发版发布了,改进记录包括: openssl: Upgrade to 1.0.1l npm: Upgrade to 2.3.0 url: revert support of path for url.fo...
2015-11-12
JavaScript开发工具
常用的有sublime,webstorm,notepad++等 ...
2015-11-12
梳理前端开发使用eslint-prettier检查和格式化代码
问题痛点 在团队的项目开发过程中,代码维护所占的时间比重往往大于新功能的开发。因此编写符合团队编码规范的代码是至关重要的,这样做不仅可以很大程度地避免基本语法错误,也保证了代码的可读性。 对于代码版本管理系统(svn 和 git或者其他)...
2018-05-07
Webpack(含 4)配置详解——从 0 配置一套开发模板
前言 源代码 熟悉 webpack 与 webpack4 配置。 webpack4 相对于 3 的最主要的区别是所谓的零配置,但是为了满足我们的项目需求还是要自己进行配置,不过我们可以使用一些 webpack 的预设值。同时 webpack...
2018-05-02
JavaScript库开发者们的规则
保持无侵入性 我的HTML标记不想知道你的JavaScript代码。 严禁修改和扩展Object.prototype! 这条很重要,因此需要一条完全针对它的规则。对象是JavaScript功能的基本构建模块,不要搞乱它们。 不要...
2015-11-11
回到顶部