资讯专栏INFORMATION COLUMN

浅谈vi-motion小程序运动组件的内部原理

yhaolpz / 2232人阅读

摘要:组件介绍组件的内部运动是动画,使用的是开源动画库的出现是为了解决小程序开发时的复杂运动会话框。但是我们在结构中用语句来控制组件的显示与隐藏的。因为该组件的使命是提供多种运动方式,所以不会定义用于装载内容盒子的样式。

vi-motion 组件介绍
vi-motion组件的内部运动是css3动画,使用的是animate开源动画库 

vi-motion的出现是为了解决小程序开发时的复杂运动会话框。让开发不必把精力放在复杂的动画运动上,使其更加关注业务逻辑

组件文档:vi-motion

github仓库:VisionUI, 欢迎 start 或 issues

明确组件需求及使用场景

复杂的运动会话弹窗

多适用于授权弹窗、儿童类小程序项目、抽奖类小程序项目等

只定制运动动画,不提供任何UI界面

DOM结构设计
在上一步我们清楚的知道了组件的使用场景以及一些需要对外提供的接口 

那么DOM结构(wxml)应该怎么设计呢?

既然这是一个运动类的会话弹窗,那么DOM结构与普通的会话弹窗是差不多的。一个根元素下面包含两个子元素。其中一个子元素为弹窗的mask遮罩层,一个元素是用来装载与用户的对话内容。

但是,该组件只是提供弹窗的运动方式,而不会提供弹窗的基本交互UI。所以,需要定义一个 slot 插槽用来接收开发者提供的对话UI界面

组件的内部DOM结构(wxml)

isShow 是用来控制组件的显示与隐藏 

maskIsHide 用来控制遮罩层的显示与隐藏

maskColor 用来定义遮罩层的颜色

enterAnimateName 用来控制组件出现时候的动画

outAnimateName 用来控制组件隐藏时候的动画

animationDuration 用来控制动画运动的时间


  
  
  
           
  

基本的DOM结构出来之后,下面是给这些DOM结构编写style

我们会在样式文件(wxss)中引入animate开源动画库
@charset "UTF-8";
@import "./animate.min.wxss";
.vi-dialog {
  top: 0;
  left: 0;
  position: fixed;
  height: 100%;
  width: 100%;
  box-sizing: border-box;
  z-index: 10000;
}

.vi-motion__animated {
  transition-property: transform;
  transition-delay: 0.5s;
}

.vi-dialog-mask {
  background-color: rgba(0, 0, 0, 0.3);
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  z-index: 9999;
}
组件的行为开发
在组件的DOM结构上,我们基本定义了一些对外的接口用来控制组件的行为表现 

这些接口分别为:ishide maskIsHide maskColor enterAnimateName outAnimateName animationDuration

在清楚了一些基本接口的设计之后,我们就可以在 Component构造器中定义接口了

Component({
  properties: {
    ishide: {
      type: Boolean,
      value: false,
      observer(newValue) {
      },
    enterAnimateName: {
      type: String,
      value: "bounce"
    },
    maskIsHide: {
      type: Boolean,
      value: false
    },
    outAnimateName: {
      type: String,
      value: ""
    },
    maskColor: {
      type: String,
      value: "rgba(0,0,0, .3)"
    },
    animationDuration: {
      type: Number,
      value: 1
    }
  },
})

接口定义完成已经基本可以控制弹窗的现实、隐藏。但是我们在wxml结构中用 wx:if="{{isShow}}" 语句来控制组件的显示与隐藏的。为什么在接口定义的部分没有看到呢?其实是有原因的,说清楚原因我们再继续之后的开发

没有定义isShow接口的原因有:

wx:if语句是直接控制元素的显示隐藏,在组件进入页面的时候会有动画,但是如果组件隐藏的时候也需要动画呢?

组件在隐藏的时候如果有动画,那么就必须要等动画运动结束才可以让组件隐藏

基于上面的这两个原因,我们把isShow字段放在data对象上

Component({
  properties: {
    ishide: {
      type: Boolean,
      value: false,
      observer(newValue) {
            if (newValue) {
             this.setData({
              isShow: newValue
            });
          } else {
            setTimeout(() => {
              this.setData({
                isShow: newValue
              });
            }, this.data.animationDuration * 1000)
          }
      }
    },
    ...
  },
  data: {
    isShow: false
  }
})

那既然解决了组件隐藏时动画的展示。但是,如果在组件隐藏的时候就是不想要动画呢?基于这样的需求,于是我们再定义一个接口,用来控制组件隐藏的时候是否出现动画

Component({
  properties: {
    ishide: {
      type: Boolean,
      value: false,
      observer(newValue) {
        if (this.data.outHasAnimate) {
          if (newValue) {
            this.setData({
              isShow: newValue
            });
          } else {
            setTimeout(() => {
              this.setData({
                isShow: newValue
              });
            }, this.data.animationDuration * 1000)
          }
        } else {
          this.setData({
            isShow: newValue
          });
        }
      }
    },
    outHasAnimate: {
      type: Boolean,
      value: true
    },
    ...
  },
  data: {
    isShow: false
  }
})

现阶段,我们定义了组件的行为接口。那如果是这样的业务场景:用户点击 mask 遮罩层,需要隐藏组件。那么我们就需要监听mask 遮罩层的点击事件

Component({
  methods: {
    triggerToHide(e) {
      this.triggerEvent("hide", this.data.ishide)
    }
  },
})

上面是mask遮罩层的点击方法,然后用 this.triggerEvent()自定义一个事件。之后在页面中调用 hide自定义事件就可以达到监听组件的mask元素的点击事件。

但是,如果产品提出了这样的需求:点击遮罩层不能隐藏组件。我们大可以不必在页面中调用组件的自定义事件,我们也可以再定义一个接口,用于表示是否触发组件的自定义事件

Component({
  properties: {
    clickMaskHide: {
      type: Boolean,
      value: false
    },
    ...
  },
  methods: {
    triggerToHide(e) {
      if (this.data.clickMaskHide) return false;
      this.triggerEvent("hide", this.data.ishide)
    }
  }
})

写到这,副本基本算是通关了,可以收功了。但我们好像还遗漏了一个页面布局相关的“小怪“。因为该组件的使命是提供多种运动方式,所以不会定义用于装载内容盒子的样式。所以我们需要暴露一个样式扩展的接口。

由于小程序框架本身的限制,在页面中是无法更改组件的内部元素的样式,所以小程序提供了一个接口:externalClasses
Component({
  properties: {
      ...
  },
  externalClasses: ["container-class"],
  methods: {
      ...
  },
  data: {
      ...
  }
})

在页面的元素中用 class 属性来接收组件外部的自定义样式


    
写在最后的提示:由于组件的运动方式是使用的animate开源动画库,所以 container-class接口定义的样式不能使用css3的 transform
组件效果预览与微信公众号

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99466.html

相关文章

  • 浅谈程序运行机制

    摘要:小程序的基础库不会被打包在某个小程序的代码包里边,它会被提前内置在微信客户端。小程序没有重启的概念当小程序进入后台,客户端会维持一段时间的运行状态,超过一定时间后目前是分钟会被微信主动销毁当短时间内连续收到两次 写作背景 接触小程序有一段时间了,总得来说小程序开发门槛比较低,但其中基本的运行机制和原理还是要懂的。比如我在面试的时候问到一个关于小程序的问题,问小程序有window对象吗?...

    Caicloud 评论0 收藏0
  • 【前端早读会】每天记录前端学习过程

    摘要:在这里使用学而思网校的录像设备,记录前端工程师每天学习的内容商城小程序分享人王聪视频插件开发分享人魏媛视频原理分享人李佳晓视频讲座优化实战分享人江芊视频文件操作分享人张凯视频一次性学会正则表达式分享人贺杰视频浅谈 在这里使用学而思网校的录像设备,记录前端工程师每天学习的内容: 2019-8-22 商城小程序codereview 分享人:王聪 视频:https://lecture.xue...

    tylin 评论0 收藏0
  • 浅谈 WebVR

    摘要:它与智能手机相连接,将显示变成显示。厂商滑配式设备包括谷歌和三星。作为一款独立的计算设备,整合式设备将配备一整套零部件,价格甚至高于普通。厂商微软对于想初步体验或入门的用户,推荐谷歌的或国内的性价比高的滑配式设备。 本文转自凹凸实验室:https://aotu.io/notes/2016/08... showImg(https://segmentfault.com/img/bVC2cm...

    yexiaobai 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<