hldy_app/component/public/Drawer.vue

138 lines
2.7 KiB
Vue
Raw Normal View History

2025-03-27 17:32:12 +08:00
<template>
<view>
2025-05-08 17:34:54 +08:00
<!-- 遮罩层display v-show 控制opacity overlay-show 类控制 -->
2025-05-13 17:18:07 +08:00
<view v-show="isVisible" :class="['overlay', { 'overlay-show': isVisible }]" @click="whiteDrawer" />
2025-05-08 17:34:54 +08:00
2025-03-27 17:32:12 +08:00
<!-- 抽屉 -->
2025-04-11 17:23:45 +08:00
<view :class="['drawer', { 'drawer-open': isVisible }]" :style="drawerStyle">
2025-03-27 17:32:12 +08:00
<view class="drawer-content">
2025-03-28 17:32:44 +08:00
<!-- 抽屉中间的半圆 -->
2025-05-13 17:18:07 +08:00
<view v-show="isVisible && canclose" class="drawer-content-circle" @click="whiteDrawer">
2025-03-28 17:32:44 +08:00
<image class="drawer-img" src="/static/index/zuoyuan.png" />
</view>
2025-03-27 17:32:12 +08:00
<!-- 抽屉内容 -->
<slot />
</view>
</view>
</view>
</template>
<script setup>
import {
2025-04-11 17:23:45 +08:00
ref,
defineProps,
computed
2025-05-08 17:34:54 +08:00
} from 'vue'
// 控制抽屉显示隐藏
const isVisible = ref(false)
2025-03-27 17:32:12 +08:00
2025-05-08 17:34:54 +08:00
// 接收父组件传入的宽度百分比
2025-04-11 17:23:45 +08:00
const props = defineProps({
widNumber: {
type: Number,
2025-05-08 17:34:54 +08:00
default: 85
2025-05-13 17:18:07 +08:00
},
canclose: {
type:Boolean,
default:true
2025-04-11 17:23:45 +08:00
}
})
2025-05-08 17:34:54 +08:00
// 仅动态设置宽度,位置由 transform 控制
const drawerStyle = computed(() => ({
width: `${props.widNumber}%`
}))
// 对外暴露打开方法
function openDrawer() {
isVisible.value = true
}
2025-05-13 17:18:07 +08:00
// 点击空白关闭方法
function whiteDrawer() {
if(props.canclose){
isVisible.value = false
}
}
2025-05-08 17:34:54 +08:00
// 对外暴露关闭方法
function closeDrawer() {
isVisible.value = false
}
2025-03-27 17:32:12 +08:00
defineExpose({
openDrawer,
2025-05-08 17:34:54 +08:00
closeDrawer
})
2025-03-27 17:32:12 +08:00
</script>
2025-03-28 17:32:44 +08:00
<style lang="less" scoped>
2025-03-27 17:32:12 +08:00
/* 遮罩层样式 */
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
2025-05-08 17:34:54 +08:00
will-change: opacity;
transition: opacity 0.3s ease;
opacity: 0;
display: block;
/* 由 v-show 控制 */
2025-03-27 17:32:12 +08:00
}
2025-05-08 17:34:54 +08:00
/* 当 isVisible 为 true 时,添加 overlay-show 类,触发遮罩渐显 */
.overlay-show {
opacity: 1;
}
/* 抽屉整体样式 */
2025-03-27 17:32:12 +08:00
.drawer {
position: fixed;
top: 0;
2025-05-08 17:34:54 +08:00
right: 0;
2025-03-27 17:32:12 +08:00
height: 100vh;
background: #fff;
z-index: 1000;
border-top-left-radius: 80rpx;
border-bottom-left-radius: 80rpx;
2025-05-08 17:34:54 +08:00
/* 使用 transform 做动画,避免布局重排 */
transform: translateX(100%);
transition: transform 0.4s ease;
will-change: transform;
2025-03-27 17:32:12 +08:00
}
2025-05-08 17:34:54 +08:00
/* 抽屉打开时 */
2025-03-27 17:32:12 +08:00
.drawer-open {
2025-05-08 17:34:54 +08:00
transform: translateX(0);
2025-03-27 17:32:12 +08:00
}
.drawer-content {
2025-03-28 17:32:44 +08:00
position: relative;
2025-05-08 17:34:54 +08:00
width: 100%;
height: 100%;
}
2025-03-28 17:32:44 +08:00
2025-05-08 17:34:54 +08:00
.drawer-content-circle {
position: absolute;
top: calc(50% - 55rpx);
left: -40rpx;
width: 100rpx;
height: 110rpx;
border-radius: 50%;
z-index: -1;
background: linear-gradient(to bottom, #dfecfa, #c9dbee);
display: flex;
align-items: center;
clip-path: inset(0 60% 0 0);
}
.drawer-img {
width: 25rpx;
height: 25rpx;
margin-left: 10rpx;
transform: rotate(180deg);
2025-03-27 17:32:12 +08:00
}
</style>