hldy_app_mini/component/public/Drawer.vue

138 lines
2.7 KiB
Vue
Raw Normal View History

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