微信小程序自定义sheet-action,实现底部弹出动画
2020-04-04 本文已影响0人
smallzip
效果
小程序自定义sheet-action.gif小程序自定义底部弹出modal框组件,仿照小程序sheet-action的效果,封装成组件直接在其他业务页面公用。
- 底部弹出动画使用的是小程序的animation,弹出动画可以根据自行需求去替换。
- modal顶部有一条短的横线,向下滑动可以触发隐藏modal
- 点击阴影部分可以触发隐藏modal
使用方法
- 在业务页面引入组件
// pages/index/index.json
{
"usingComponents": {
"product-cart": "../../components/product-cart/index"
}
}
// pages/index/index.js
Page({
data: {
show: false // true:显示 false:隐藏
},
showModal(){
this.setData({
show:true
})
},
)}
- show参数是boolean值
// pages/index/wswl
<view>
<button bindtap="showModal">点击</button>
<product-cart show="{{show}}"></product-cart>
</view>
组件源码
// pages/index/components/buy/index.js
let pageY = 0;
Component({
options: {
styleIsolation: 'isolated'
},
/**
* 组件的属性列表
*/
properties: {
show: {
type: Boolean,
value: false
}
},
/**
* 组件的初始数据
*/
data: {
list: [{
name: '快递',
selected: 1,
},
{
name: '自提',
selected: 0
}
],
animate: {},
hideModal: false, //模态框的状态 false-隐藏 true-显示
},
/**
* 数据监听
*/
observers: {
'show': function(val) {
if (val) {
this.showModal()
} else {
this.hideModal()
}
}
},
/**
* 组件的方法列表
*/
methods: {
// 显示遮罩层
showModal() {
this.setData({
hideModal: true
})
const animation = wx.createAnimation({
duration: 500,
timingFunction: 'ease',
})
// 先显示背景再执行动画,translateY(0)偏移量为0代表显示默认高度
setTimeout(() => {
animation.translateY(0).step()
this.setData({
animate: animation.export()
})
}, 50)
},
// 隐藏遮罩层
hideModal() {
const animation = wx.createAnimation({
duration: 500,
timingFunction: 'ease',
})
// 设置为100vh可以确保滚动到底部,可以按照自己的内容高度设置,能够滑到底部即可
animation.translateY('100vh').step()
this.setData({
animate: animation.export(),
})
// 先执行动画,再隐藏组件
setTimeout(() => {
this.setData({
hideModal: false
})
}, 300)
},
// 移动
touchMove(e) {
const clientY = e.changedTouches[0].clientY
if (clientY - pageY > 0 && clientY - pageY > 50) {
this.hideModal()
}
},
// 触摸开始
touchStart(e) {
pageY = e.changedTouches[0].clientY;
},
// 选择类型
changeItem(e) {
const {
index
} = e.currentTarget.dataset
this.data.list.forEach((e, i) => {
if (i == index) {
e.selected = 1
} else {
e.selected = 0
}
})
this.setData({
list: this.data.list
})
},
// 确认
confirm() {
this.hideModal()
},
}
})
<!--pages/index/components/buy/index.wxml-->
<view class="box" hidden="{{!hideModal}}">
<view class="empty-box" bindtap="hideModal" id="empty-box"></view>
<scroll-view scroll-y style="max-height:80vh;">
<view class="content" style="transform:translateY({{translateY}}px);" animation="{{animate}}">
<!-- boll -->
<view class="header" bindtouchstart="touchStart" bindtouchmove="touchMove">
<view></view>
</view>
<!-- 快递类型 -->
<view>
<view class="item" wx:for="{{list}}" wx:key="index" bindtap="changeItem" data-index="{{index}}">
<view class="item-name">{{item.name}}</view>
<view>
<view class="item-no-selected" wx:if="{{item.selected==0}}"></view>
<image class="item-selected" wx:if="{{item.selected==1}}" src="/assets/images/choose.png"></image>
</view>
</view>
</view>
<!-- 按钮 -->
<view class="button" bindtap="confirm">
<view>确认</view>
</view>
</view>
</scroll-view>
</view>
/* pages/index/components/buy/index.wxss */
.flex {
display: flex;
align-items: center;
}
.box {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
}
.empty-box {
flex: 1;
background-color: transparent;
}
/* 内容视图 */
.content {
width: 100vw;
background: rgba(255, 255, 255, 1);
opacity: 1;
border-radius: 20px 20px 0px 0px;
z-index: 1001;
}
/* 头部 */
.header {
position: relative;
height: 80rpx;
width: 100vw;
}
.header > view {
position: absolute;
top: 26rpx;
left: calc(50vw - 30rpx);
width: 60rpx;
height: 10rpx;
background: rgba(161, 166, 175, 1);
opacity: 0.6;
border-radius: 6rpx;
}
/* 快递 */
.item {
display: flex;
align-items: center;
justify-content: space-between;
width: calc(100vw - 80rpx);
padding: 0 40rpx;
height: 100rpx;
background: rgba(255, 255, 255, 1);
opacity: 1;
}
.item-no-selected {
width: 36rpx;
height: 36rpx;
background: rgba(255, 255, 255, 1);
border: 2rpx solid rgba(112, 112, 112, 1);
border-radius: 50%;
opacity: 0.5;
}
.item-selected {
width: 40rpx;
height: 40rpx;
}
/* 按钮 */
.button {
width: 100vw;
padding: 80rpx 40rpx 20rpx 40rpx;
}
.button >view {
width: calc(100% - 80rpx);
height: 98rpx;
border-radius: 50rpx;
line-height: 98rpx;
text-align: center;
font-size: 32rpx;
font-family: PingFang SC;
font-weight: bold;
color: rgba(255, 255, 255, 1);
background: rgba(237, 58, 74, 1);
opacity: 1;
}