1.实现效果
radioChange.gif2.实现原理
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
}
})
var 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,
})
}
})
网友评论