Component({ options: { // 关键修改:设置样式隔离选项 styleIsolation: 'shared' // 完全共享页面和组件样式 }, properties: { visible: { type: Boolean, value: false, observer: function (newVal) { if (newVal) { this.showModal(); } else { this.hideModal(); } } }, modalContentClass: { type: String, value: '' } }, data: { animationClass: 'modal-transition', // 保持过渡效果类 containerHeight: '25vh', // 设置为1/4屏幕高度 initialTranslate: '100%', // 初始在屏幕外 startY: 0, // 触摸起始位置 currentState: 'hidden', // 'hidden', 'bottom', 'half', 'full' states: { bottom: { height: '25vh', translate: '0' }, // 1/4屏幕高度,设置translate为0使其正确显示在底部 full: { height: '100vh', translate: '0' } // 全屏高度 } }, methods: { showModal() { this.setData({ visible: true, currentState: 'bottom', // 默认显示1/4屏幕高度 containerHeight: this.data.states['bottom'].height, initialTranslate: this.data.states['bottom'].translate }); }, hideModal() { this.setData({ initialTranslate: '100%', // 设置为底部位置 currentState: 'hidden' }); setTimeout(() => { if (this.data.currentState === 'hidden') { this.setData({ visible: false }); } }, 300); // 与动画时间一致 }, onHideModal() { this._triggerCloseEvent(); }, // 遮罩层点击事件(如果有遮罩层的话) onOverlayTap() { this._triggerCloseEvent(); }, // 共用的关闭事件触发方法 _triggerCloseEvent() { this.triggerEvent('close'); }, preventTouchMove() {}, onTouchStart(e) { this.setData({ startY: e.touches[0].clientY }); this.setData({ animationClass: '' }); // 开始拖动时移除过渡效果,使拖动更跟手 }, onTouchMove(e) { if (!this.data.visible) return; const currentY = e.touches[0].clientY; const deltaY = currentY - this.data.startY; let newTranslate = ''; // 根据当前状态和拖动方向计算新的位移 if (this.data.currentState === 'full') { newTranslate = `calc(0px + ${deltaY}px)`; // 从全屏位置开始拖 } else if (this.data.currentState === 'bottom') { newTranslate = `calc(75vh + ${deltaY}px)`; // 从1/4屏幕高度位置开始拖 } // 限制拖动范围,不能拖出屏幕顶部或底部之外 if (this.data.currentState === 'full' && parseInt(newTranslate) > 0) { newTranslate = '0'; } else if (this.data.currentState === 'bottom' && deltaY < -300) { // 向下拖动不超过屏幕 newTranslate = 'calc(75vh - 300px)'; } this.setData({ initialTranslate: newTranslate }); }, onTouchEnd(e) { const endY = e.changedTouches[0].clientY; const deltaY = endY - this.data.startY; const threshold = 50; // 判断状态切换的阈值 // 根据拖动距离和方向,以及当前状态,决定下一个状态 let nextState = this.data.currentState; if (Math.abs(deltaY) > threshold) { if (deltaY > 0) { // 向下拖 if (this.data.currentState === 'full') { nextState = 'bottom'; } } else { // 向上拖 if (this.data.currentState === 'bottom') { nextState = 'full'; } } } else { // 拖动距离小于阈值,则回到当前状态 nextState = this.data.currentState; } // 在切换状态前,添加过渡动画类 this.setData({ animationClass: 'modal-transition' }, () => { // 在回调中执行状态切换,确保动画类已经设置 this.switchToState(nextState); }); }, switchToState(state) { if (state === 'hidden') { this.hideModal(); return; } const targetState = this.data.states[state]; if (targetState) { this.setData({ currentState: state, containerHeight: targetState.height, initialTranslate: targetState.translate }); // 通知父组件状态变化 this.triggerEvent('stateChange', { state: state }); } } } });