微信小程序实现单选跳跃选择动画

168 阅读2分钟
👏文末分享源代码。记得点赞+关注+收藏!

1.实现效果

在这里插入图片描述

2.实现原理

wx.createAnimation(Object object):创建一个动画实例 animation。调用实例的方法来描述动画。最后通过动画实例的 export 方法导出动画数据传递给组件的 animation 属性

Animation.translateY(number translation):在 Y 轴平移的距离,单位为 px

wx.createSelectorQuery():获取相应id的高度

  • 拿到当前列表数据的高度+当前选中小圆点的高度,计算出translateY的值
let dd = this.data.boxHeight / this.data.items.length;
let ee = this.data.boxCircle / 2;
animation.translateY(index * dd + ee).step();
  • 设置animation ,动画持续时间,500 ms
var animation = wx.createAnimation({
   duration: 500,
    timingFunction: "linear",
    delay: 0
  })

3.实现代码

<view class="mb20 title">radio自定义样式</view>
<radio-group bindchange="radioChange">
  <view class="box">
    <label class="flex-row" wx:for="{{items}}" wx:key="items">
      <view class="cust_label">
        <radio value="{{item.value}}" checked="true" />
        <view class="radio_checked" wx:if="{{curr==item.value}}"></view>
      </view>
      <view class="name {{curr==item.value&&'name_checked' }}">{{item.name}}</view>
    </label>
  </view>
</radio-group>
<view class="mb20 title">单选跳跃选择动画</view>
<view class="flex-row">
  <view class="box" id="box">
    <view wx:for="{{items}}" wx:key="items" class="cust_label" catchtap="choseItem" data-index="{{index}}"></view>
    <view id="box-circle" class="checked" animation="{{animationData}}"></view>
  </view>
  <view>
    <view wx:for="{{items}}" wx:key="items" class="name {{item.checked&&'name_checked' }}" catchtap="choseItem" data-index="{{index}}">{{item.name}}</view>
  </view>
</view>
page {
  background-color: #f3bc90;
  padding: 20px;
}

.box {
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
}

radio {
  display: none;
  opacity: 0;
}

.cust_label {
  border-radius: 50%;
  border: 16rpx solid #e06c35;
  height: 60rpx;
  width: 60rpx;
  margin-bottom: 20rpx;
  margin-right: 20rpx;
  transition: border-color 800ms;
  flex-shrink: 0;
  position: relative;
  box-sizing: border-box;
}


.name {
  font-family: 'susu';
  font-size: 35rpx;
  color: #fff;
  line-height: 60rpx;
  margin-bottom: 20rpx;
}


.radio_checked {
  position: absolute;
  background: #fff;
  border-radius: 50%;
  height: 30rpx;
  width: 30rpx;
  top: 50%;
  left: 50%;
  margin-top: -15rpx;
  margin-left: -15rpx;
}

.name_checked {
  color: #e06c35;
}

.title {
  color: #fff;
  font-size: 26rpx;
}

.checked {
  position: absolute;
  background: #fff;
  border-radius: 50%;
  height: 30rpx;
  width: 30rpx;
  left: 50%;
  margin-left: -25rpx;
  top: 0;
  transform: translateY(-80rpx);
}
Page({

  data: {
    items: [
      {
        name: '选项一二三',
        value: 1,
      },
      {
        name: '选项嘻嘻',
        value: 2,
      },
      {
        name: 'susu3', value: 3,
      },
      {
        name: 'susu4', value: 4,
      },
      {
        name: 'susu5', value: 5,
      },
      {
        name: '喜欢的哈哈哈哈哈哈', value: 6,
      }
    ],
    curr: '',
    animationData: {},
    boxHeight: 0,
    boxCircle: 0
  },
  onReady() {
    let query = wx.createSelectorQuery();
    query.select('#box').boundingClientRect(rect => {
      let height = rect.height;
      this.setData({
        boxHeight: height
      })
    }).exec();
    query.select('#box-circle').boundingClientRect(rect => {
      let height = rect.height;
      this.setData({
        boxCircle: height
      })
    }).exec();
  },

  radioChange(e) {
    console.log('radio发生change事件,携带value值为:', e.detail.value)
    const items = this.data.items
    let index = '';
    items.forEach((item, i) => {
      if (item.value == e.detail.value) {
        index = i;
      }
    })
    this.setData({
      curr: e.detail.value,
    })
  },
  choseItem(e) {
    let { index } = e.currentTarget.dataset, { items } = this.data;
    items.forEach((e, i) => {
      if (index == i) {
        e.checked = true
      } else {
        e.checked = false
      }
    })
    let animation = wx.createAnimation({
      duration: 500,
      timingFunction: "linear",
      delay: 0
    })
    let dd = this.data.boxHeight / this.data.items.length;
    let ee = this.data.boxCircle / 2;
    animation.translateY(index * dd + ee).step();
    this.setData({
      animationData: animation.export(),
      items,
    })
  }
})

4.写在最后

看完本文如果觉得有用,记得点赞+关注+收藏鸭
更多小程序相关,关注💯苏苏的bug,💢苏苏的github,😎苏苏的码云~