上下滑弹框(仿高德)

这是一个Vue组件的实现,用于创建一个搜索面板,面板高度根据触摸滑动动态变化,同时包含搜索框和内容滚动区域。组件通过监听touchstart, touchmove和touchend事件来处理滑动手势,从而改变面板高度。当高度超过一定阈值时,内容区域启用滚动。此外,组件还提供了占位符、后缀图标、最小高度、中间高度和显示线条等配置选项。
摘要由CSDN通过智能技术生成
<template>
    <view class="panel"  @touchmove.stop="touchmoveHandle" @touchstart.stop="touchstartHandle" @touchend.stop="touchendHandle" :style="{height: `${height}px`}" :class="{search_radius: !isScroll}">
        <!-- <view class="search_wrapper">
            <view class="search_content">
                <view class="search_content_input">
                    <uni-icons class="search_icon" type="search" size="22" color="#394353"></uni-icons>
                    <text class="search_text">{{placeholder}}</text>
                </view>
                <image class="search_suffix" :src="suffixIcon" mode="aspectFill"></image>
            </view>
        </view> -->
        <view class="tapBoxTouchLine" v-if="showLine">
            <view class="line"></view>
        </view>
        <view class="panel_content">
            <scroll-view :scroll-y="isScroll" style="height: 100%">
                <slot></slot>
            </scroll-view>
        </view>
    </view>
</template>

<script>
    export default {
        props: {
            placeholder: {
                type: String,
                default: "请输入搜索内容"
            },
            suffixIcon: {
                type: String,
                default: "/static/audio.png"
            },
            minHeight: {
                type: Number,
                default: 220
            },
            middleHeight: {
                type: Number,
                default: 380
            },
            showLine: {
                type: Boolean,
                default: true
            },
        },
        created() {
             const info = uni.getSystemInfoSync()
             // console.log(info)
             this.maxHeight = info.windowHeight
             console.log(this.maxHeight);
        },
        data() {
            return {
                maxHeight: 1000,
                height: 230,
                lastY: 0,
                up: true,
                direction_flag: true,
                isScroll: false
            };
        },
        methods: {
            touchstartHandle(event) {
                this.lastY = event.touches[0].pageY;
            },
            touchendHandle(event) {
                if (this.up) {
                    if (this.height < this.middleHeight) {
                        this.height = this.middleHeight
                        this.isScroll = false
                    } else {
                        this.height = this.maxHeight
                        this.isScroll = true
                    }
                } else {
                    if (this.height < this.middleHeight) {
                        this.height = this.minHeight
                        this.isScroll = false
                    } else {
                        this.height = this.middleHeight
                        this.isScroll = false
                    }
                }
                this.direction_flag = true
            },
            touchmoveHandle(event) {
                let currentY = event.touches[0].pageY
                let transformHeight = currentY - this.lastY
                this.height = this.height - (transformHeight / 20)
                if (this.height > this.maxHeight) {
                    this.height = this.maxHeight
                }
                if (this.height < this.minHeight) {
                    this.height = this.minHeight
                }
                if (this.direction_flag) {
                    this.direction_flag = false
                    if (transformHeight > 0) {
                        // 下滑
                        this.up = false
                    } else {
                        // 上滑
                        this.up = true
                    }
                }

            }
        }
    }
</script>

<style lang="scss">
    .tapBoxTouchLine {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .line {
        margin: 0px;
        vertical-align: middle;
        border-bottom: 8rpx solid rgb(68, 68, 68);
        width: 60rpx;
        transform: scaleY(0.5);
    }
    .panel {
        z-index: 999;
        position: absolute;
        bottom: 0;
        width: 100vw;
        background-color: #ffffff;
        padding: 30rpx 20rpx;
        box-sizing: border-box;
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        align-items: center;
        transition-duration: .5s;
        .search_wrapper {
            display: flex;
            justify-content: center;
            align-items: center;
            width: 100%;
            margin-bottom: 20rpx;

            .search_content {
                height: 74rpx;
                width: 100%;
                display: flex;
                justify-content: space-between;
                align-items: center;
                background-color: #EBF0F3;
                border-radius: 16rpx;
                border: 1rpx solid #DFE4E7;
                padding: 0 20rpx;

                .search_content_input {
                    flex: 1;
                    display: flex;
                    justify-content: flex-start;
                    align-items: center;

                    .search_icon {
                        margin-right: 10rpx;
                    }

                    .search_text {
                        color: #595E5F;
                        font-size: 32rpx;
                        letter-spacing: 1.8rpx;
                    }
                }

                .search_suffix {
                    width: 48rpx;
                    height: 48rpx;

                    image {
                        width: 100%;
                        height: 100%;
                    }
                }
            }
        }

        .panel_content {
            width: 100%;
            height: 100%;
        }
    }
    
    .search_radius {
        border-radius: 50rpx 50rpx 0 0;
        box-shadow: 0 -8rpx 30rpx rgba(109, 109, 109, 0.1);
    }
</style>

引入与使用

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值