小程序animation使用


想实现一个item左滑展示编辑和删除按钮的功能,涉及到元素移动,因此使用animation属性来实现

了解animation

下面这段代码设置了一个动画的各种属性(持续1000ms ; 匀速到加速再减速; 立即开始执行;元素变换基点,此处是平移,不起作用),然后设置动画效果向左平移100元素,最后,调用 export() 方法导出动画数据,并将其赋值给 animation 属性,从而触发视图的更新

html

<
view class="box" animation="{{animationData}}">动画效果</view>
css

Page({ data: { animationData: {} }, onLoad:
function() { // 创建一个动画实例 let animation = wx.createAnimation({ duration: 1000, // 动画持续时间 timingFunction: 'ease', // 动画效果,可选值有:linear、ease、ease-in、ease-in-out、ease-out、step-start、step-end delay: 0, // 延迟多长时间后开始动画 transformOrigin: '50% 50% 0' // 动画原点,用于指定动画相对于哪个点进行变换,默认值为"50% 50% 0" }); // 设置动画效果 animation.translate(-100).step(); // 更新数据,触发视图更新 this.setData({ animationData: animation.export() }); } });

 

动画各属性详解

duration:动画执行完所有操作的需要的时间,毫秒

timingFunction 属性用于指定动画的时间曲线,决定了动画在播放过程中的变化速度。常见的取值包括:

  1. linear(线性):动画效果匀速进行,没有加速度或减速度,动画变化率保持恒定。

  2. ease(匀速到加速再减速):动画从匀速开始,然后逐渐加速,最后减速停止。这是一个常用的默认值,也是很多动画库的默认效果。

  3. ease-in(加速):动画从开始时较慢,然后逐渐加速到结束。在开始时速度较慢,逐渐加快。

  4. ease-out(减速):动画从开始时较快,然后逐渐减速直至结束。在结束时速度较慢,逐渐减慢。

  5. ease-in-out(加速再减速):动画从开始时较慢,然后逐渐加速,到达中间时速度最快,然后逐渐减速直至结束。

  6. step-start(分步开始):动画在每一帧都会直接跳跃到结束位置,但在两个关键帧之间没有动画效果。

  7. step-end(分步结束):动画在每一帧都会直接跳跃到开始位置,但在两个关键帧之间没有动画效果。

delay:多长时间后开始动画效果,毫秒

 transformOrigin :指定一个元素变换的基点,即指定变换的原点。它影响了 CSS 变换函数如 rotate()、scale()、skew()、translate() 等的行为。

                           这个属性通常与 CSS 的 transform 属性一起使用。具体来说,transformOrigin 属性有以下几个方面需要注意:

transformOrigin 属性接受三个值,默认值为 50% 50% 0,即元素的中心点。分别对应于 x 轴、y 轴和 z 轴的位置。每个值可以使用长度单位(如 px、em)或百分比来表示。

x、y、z 轴的取值范围:对于 x、y 轴,取值范围是 left、center、right 和 top、center、bottom。对于 z 轴,取值范围是负无穷到正无穷。

影响的变换:transformOrigin 属性会影响应用于元素的所有 CSS 变换函数的基点位置。例如,如果你将一个元素的 transformOrigin 设置为左上角(top left),

                  那么对该元素的旋转、缩放等变换都将以左上角作为基点。

                  与 translate 的关系:注意,transformOrigin 属性不会影响 translate() 函数的行为。translate() 函数是移动元素的位置,它的移动方向不受 transformOrigin 的影响。

动画常见的操作:

  1. translateX():在 X 轴上进行垂直平移(移动)。
  2. translateY():在 Y 轴上进行垂直平移(移动)。

    • 示例:translateX(100px)translateY(-50%)
  3. rotate(): 旋转度数,正值表示顺时针旋转,负值表示逆时针旋转。
    • 示例:rotate(90deg)rotate(-45deg)
  4. scale():缩放元素的大小,可以分别指定水平和垂直方向上的缩放比例。

    • 示例:scale(1.5)scale(2, 0.5)
  5. scaleX() 和 scaleY():分别在 X 轴和 Y 轴上进行缩放变换。
  6. skewX() 和 skewY():分别在 X 轴和 Y 轴上进行倾斜变换。

    • 示例:skewX(45deg)skewY(-30deg)
  7. matrix():使用一个 2D 转换矩阵来实现自定义的变换效果,可以实现复杂的变换操作。
    接受一个 6 个值的矩阵作为参数,用来表示一个自定义的 2D 变换矩阵。矩阵中的值依次表示水平缩放、水平倾斜、垂直倾斜、垂直缩放、水平平移和垂直平移。

    • 示例:matrix(1, 0.5, -0.5, 1, 100, 50)

 

实现代码

<view>
  <view wx:for="{{tagDetail.goodsList}}" wx:key="id" class='itemContainer'>
    <view class="myItem" animation="{{item.itemAnimation}}" bindtouchstart='onTouchStart' bindtouchmove='onTouchMove' bindtouchend='onTouchEnd' id="{{index}}">
      {{item.goodsName}}
    </view>
    <view class='menu'>
      <view id='{{item.id}}' class='menu-delete' bindtap='onDeleteMsgTap' bindlongtap='onDeleteMsgLongtap'>
        <text>删除</text>
      </view>
      <view id='{{item.id}}' class='menu-edit' bindtap='onMarkMsgTap' bindlongtap='onMarkMsgLongtap'>
        <text>编辑</text>
      </view>
    </view>
  </view>
</view>
  moveX: 0,  //记录平移距离
  showState: 0, //0 未显示菜单 1显示菜单
  maxMoveLeft: 195, //消息列表项最大左滑距离
  correctMoveLeft: 80, //菜单自动展示的左滑距离
  lastAnimationId: "0",

  onTouchStart: function(e) {
    if (this.showState === 0) {  // 未展示菜单,移动距离从0计算
      this.moveX = 0;
    } else {  // 已展示菜单
      // 与上次操作的同一item,移动距离从 -this.maxMoveLeft 计算
      if (e.currentTarget.id == this.lastAnimationId) {
        this.moveX = -this.maxMoveLeft
      } else { // 与上次操作的不同item, 移动距离从0开始计算
        this.moveX = 0
      }
    }

    this.firstTouchX = e.touches[0].clientX;
    this.translateXMsgItem(e.currentTarget.id, this.moveX, 200);
  },

  onTouchMove: function(e) {
    var moveX = e.touches[0].clientX - this.firstTouchX;
    if (this.showState === 1) {
      // 和上次操作不是同一个item,关闭上次的item
      if (e.currentTarget.id != this.lastAnimationId) {
        this.translateXMsgItem(this.lastAnimationId, 0, 200);
      } else { // 和上次操作的同一个item, 移动距离需要从-this.maxMoveLeft 开始算
        moveX = -this.maxMoveLeft + moveX
      }
    }
    //处理边界情况
    if (moveX > 0) {
      moveX = 0;
    }
    //检测最大左滑距离
    if (moveX < -this.maxMoveLeft) {
      moveX = -this.maxMoveLeft;
    }
    this.moveX = moveX;
    this.translateXMsgItem(e.currentTarget.id, moveX, 0);
  },
  onTouchEnd: function(e) {
    if (this.moveX >= -this.correctMoveLeft) {
      this.moveX = 0;
      this.showState = 0
    } else {
      this.moveX = -this.maxMoveLeft
      this.showState = 1
    }

    let currentId = e.currentTarget.id
    this.translateXMsgItem(currentId, this.moveX, 500);
    this.lastAnimationId = currentId
  },

  translateXMsgItem: function(id, x, duration) {
    var animation = wx.createAnimation({duration:duration});
    animation.translateX(x).step();
    var indexString = 'tagDetail.goodsList['+id+'].itemAnimation'
    this.setData({
      [indexString]: animation.export()
    })
  }
.itemContainer {
  width: 100%;
  height: 150rpx;
  border-bottom: 1rpx solid rgb(109, 21, 21);
  position: relative;
  left: 0;
  top: 0;
  overflow: hidden;
}
 
.myItem {
  position: absolute;
  width: 100%;
  height: 150rpx;
  left: 0;
  top: 0;
  z-index: 100;
  background-color: rgb(231, 188, 188);
}

.menu {
  display: flex;
  position: absolute;
  width: 100%;
  height: 150rpx;
  left: 0;
  top: 0;
  z-index: 0;
  color: #fff;
  text-align: center;
}
 
.menu-delete {
  position: absolute;
  width: 60px;
  height: 148rpx;
  top: 1rpx;
  right: 0;
  background-color: rgb(255, 58, 50);
  line-height: 150rpx;
}
 
.menu-edit {
  position: absolute;
  width: 60px;
  height: 148rpx;
  top: 1rpx;
  right: 60px;
  background-color: rgb(54, 128, 70);
  line-height: 150rpx;
}

 

 

 

 

 

 

posted on 2024-04-21 22:02  mlllily  阅读(107)  评论(0编辑  收藏  举报