跳转到内容

订单详情

刀刀

1/2/2025

0 字

0 分钟

前置知识

路由栈

微信小程序中,可通过 getCurrentPages() 获取路由栈数组,最新打开的路由信息对象在最后一项,后进先出的形式排列。

动画

官方文档指路:动画

订单详情页中,顶部的导航栏是自定义的,并且还能在页面滚动时拥有动画效果。

此处用到了微信官方提供的 animate 动画 API,该接口定义如下:

js
this.animate(selector, keyframes, duration, ScrollTimeline)

⚠ 注意

目前只支持 scroll-view

参数说明

属性类型默认值必填说明
selectorString选择器(同 SelectorQuery.select 的选择器格式)
keyframesArray关键帧信息
durationNumber动画持续时长(毫秒为单位)
scrollTimelineObject

keyframes 中对象的结构

属性类型默认值必填说明
offsetNumber关键帧的偏移,范围[0-1]
easeStringlinear动画缓动函数
transformOriginString基点位置,即 CSS transform-origin
backgroundColorString背景颜色,即 CSS background-color
bottomNumber/String底边位置,即 CSS bottom
heightNumber/String高度,即 CSS height
leftNumber/String左边位置,即 CSS left
widthNumber/String宽度,即 CSS width
opacityNumber不透明度,即 CSS opacity
rightNumber右边位置,即 CSS right
topNumber/String顶边位置,即 CSS top
matrixArray变换矩阵,即 CSS transform matrix
matrix3dArray三维变换矩阵,即 CSS transform matrix3d
rotateNumber旋转,即 CSS transform rotate
rotate3dArray三维旋转,即 CSS transform rotate3d
rotateXNumberX 方向旋转,即 CSS transform rotateX
rotateYNumberY 方向旋转,即 CSS transform rotateY
rotateZNumberZ 方向旋转,即 CSS transform rotateZ
scaleArray缩放,即 CSS transform scale
scale3dArray三维缩放,即 CSS transform scale3d
scaleXNumberX 方向缩放,即 CSS transform scaleX
scaleYNumberY 方向缩放,即 CSS transform scaleY
scaleZNumberZ 方向缩放,即 CSS transform scaleZ
skewArray倾斜,即 CSS transform skew
skewXNumberX 方向倾斜,即 CSS transform skewX
skewYNumberY 方向倾斜,即 CSS transform skewY
translateArray位移,即 CSS transform translate
translate3dArray三维位移,即 CSS transform translate3d
translateXNumberX 方向位移,即 CSS transform translateX
translateYNumberY 方向位移,即 CSS transform translateY
translateZNumberZ 方向位移,即 CSS transform translateZ

ScrollTimeline 中对象的结构

属性类型默认值必填说明
scrollSourceString指定滚动元素的选择器(只支持 scroll-view),该元素滚动时会驱动动画的进度
orientationStringvertical指定滚动的方向。有效值为 horizontal 或 vertical
startScrollOffsetNumber指定开始驱动动画进度的滚动偏移量,单位 px
endScrollOffsetNumber指定停止驱动动画进度的滚动偏移量,单位 px
timeRangeNumber起始和结束的滚动范围映射的时间长度,该时间可用于与关键帧动画里的时间 (duration) 相匹配,单位 ms
示例代码
javascript
  this.animate('.avatar', [{
    borderRadius: '0',
    borderColor: 'red',
    transform: 'scale(1) translateY(-20px)',
    offset: 0,
  }, {
    borderRadius: '25%',
    borderColor: 'blue',
    transform: 'scale(.65) translateY(-20px)',
    offset: .5,
  }, {
    borderRadius: '50%',
    borderColor: 'blue',
    transform: `scale(.3) translateY(-20px)`,
    offset: 1
  }], 2000, {
    scrollSource: '#scroller',
    timeRange: 2000,
    startScrollOffset: 0,
    endScrollOffset: 85,
  })

  this.animate('.search_input', [{
    opacity: '0',
    width: '0%',
  }, {
    opacity: '1',
    width: '100%',
  }], 1000, {
    scrollSource: '#scroller',
    timeRange: 1000,
    startScrollOffset: 120,
    endScrollOffset: 252
  })

实现

  1. 获取路由栈
  2. 获取当前页面实例(即路由栈数组最后一项)
  3. 在页面渲染完毕之后绑定动画效果
  4. 自定义导航栏
js
const pages = getCurrentPages()
js
const pageInstance = pages.at(-1) as any
js
onReady(() => {
  // 动画效果,导航栏背景色
  pageInstance.animate(
    '.navbar',
    [
      {
        borderRadius: '0',
        borderColor: 'red',
        transform: 'scale(1) translateY(-20px)',
        offset: 0,
      },
      {
        borderRadius: '25%',
        borderColor: 'blue',
        transform: 'scale(.65) translateY(-20px)',
        offset: 0.5,
      },
      {
        borderRadius: '50%',
        borderColor: 'blue',
        transform: `scale(.3) translateY(-20px)`,
        offset: 1,
      },
    ],
    2000,
    {
      scrollSource: '#scroller',
      timeRange: 2000,
      startScrollOffset: 0,
      endScrollOffset: 85,
    },
  )

  pageInstance.animate(
    '.navbar', // 选择器
    [{ backgroundColor: 'transparent' }, { backgroundColor: '#f8f8f8' }], // 关键帧信息
    1000, // 动画持续时长
    {
      scrollSource: '#scroller', // scroll-view 的选择器
      startScrollOffset: 0, // 开始滚动偏移量
      endScrollOffset: 50, // 停止滚动偏移量
      timeRange: 1000, // 时间长度
    },
  )
  // 动画效果,导航栏标题
  pageInstance.animate('.navbar .title', [{ color: 'transparent' }, { color: '#000' }], 1000, {
    scrollSource: '#scroller',
    timeRange: 1000,
    startScrollOffset: 0,
    endScrollOffset: 50,
  })
  // 动画效果,导航栏返回按钮
  pageInstance.animate('.navbar .back', [{ color: '#fff' }, { color: '#000' }], 1000, {
    scrollSource: '#scroller',
    timeRange: 1000,
    startScrollOffset: 0,
    endScrollOffset: 50,
  })
})
vue
 <!-- 自定义导航栏: 默认透明不可见, scroll-view 滚动到 50 时展示 -->
<view class="navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
  <view class="wrap">
    <navigator
      v-if="pages.length > 1"
      open-type="navigateBack"
      class="back icon-left"
    ></navigator>
    <navigator v-else url="/pages/index/index" open-type="switchTab" class="back icon-home">
    </navigator>
    <view class="title">订单详情</view>
  </view>
</view>

通过为盒子设置类名的方式,使用 animate API 实现绑定类名的盒子实现动画效果。