wx-mini-weview
Version:
weixin UI
291 lines (250 loc) • 6.49 kB
JavaScript
const { WvComponentHandler } = require('../../behaviors/WvComponentHandler');
Component({
options: {
styleIsolation: 'apply-shared',
multipleSlots: true
},
behaviors: [
WvComponentHandler({
handleMethods: {
tap: {
show: {},
hide: {}
}
}
}),
],
properties: {
show: {
type: Boolean,
value: false,
observer(newVal) {
if (newVal) {
this.show();
} else {
this.hide();
}
}
},
// 滑出位置:'top', 'right', 'bottom', 'left'
position: {
type: String,
value: 'bottom'
},
// 尺寸设置
width: {
type: String,
value: '100%' // 固定值或vw或auto, 百分比无效
},
height: {
type: String,
value: '100%' // 固定值或vh或auto, 百分比无效
},
remainOffset: {
type: String,
value: '' // 为空时使用width/height,否则使用100vh/100vw减去此值
},
showHeader: {
type: Boolean,
value: true
},
showFooter: {
type: Boolean,
value: false
},
showMask: {
type: Boolean,
value: true
},
maskClosable: {
type: Boolean,
value: true
},
// z-index层级
zIndex: {
type: Number,
value: 9000
},
theme: {
type: String,
value: ''
},
radius: {
type: String,
value: 'var(--wv-border-radius-huge)'
},
closeIcon: {
type: String,
value: 'bi-x-lg' // 为空则不显示关闭按钮
},
// 关闭按钮位置:'top-right', 'top-left', 'bottom-right', 'bottom-left'
closePosition: {
type: String,
value: 'top-right'
},
enableEdgeGesture: {
type: Boolean,
value: false
},
gestureAreaWidth: {
type: Number,
value: 20
}
},
data: {
gestureStart: null,
gestureTriggered: false,
calculatedWidth: '100%',
calculatedHeight: '100%',
visible: false
},
observers: {
'position, width, height, remainOffset': function(position, width, height, remainOffset) {
let calculatedWidth = width;
let calculatedHeight = height;
if (remainOffset) {
if (position === 'left' || position === 'right') {
calculatedWidth = `calc(100vw - ${remainOffset})`;
} else if (position === 'top' || position === 'bottom') {
calculatedHeight = `calc(100vh - ${remainOffset})`;
}
}
this.setData({
calculatedWidth,
calculatedHeight
});
}
},
lifetimes: {
attached() {
this.initGestureTrigger();
},
detached() {
},
ready() {
const that = this
that.toast = that.selectComponent('#slidepanel-toast');
const position = that.data.position;
const positionMap = {
'top': 'top',
'right': 'center-right',
'bottom': 'bottom',
'left': 'center-left'
};
const toastPosition = positionMap[position] || 'bottom';
const animationMap = {
'top': { show: 'slide-top', hide: 'slide-top' },
'right': { show: 'slide-right', hide: 'slide-right' },
'bottom': { show: 'slide-bottom', hide: 'slide-bottom' },
'left': { show: 'slide-left', hide: 'slide-left' }
};
const animations = animationMap[position]
that.toast.setData({
showAnimationType: animations.show,
hideAnimationType: animations.hide,
position: toastPosition,
maskClosable: that.data.maskClosable,
zIndex: that.data.zIndex,
topOffset: '0rpx',
rightOffset: '0rpx',
bottomOffset: '0rpx',
leftOffset: '0rpx',
duration: 0
});
}
},
methods: {
catchTouchMove(e) {
return false;
},
show(callback = null) {
const that = this
that.toast.showSlot(0, callback);
that.data.visible = true
that.triggerEvent('show');
},
hide(callback = null) {
if (this.toast) {
this.toast.hide(() => {
if (callback && typeof callback === 'function') {
callback();
}
});
}
},
onClose() {
this.data.visible = false
this.triggerEvent('hide');
},
isVisible() {
return this.data.visible;
},
initGestureTrigger() {
setTimeout(() => {
this.setData({
gestureTriggered: false
});
}, 100);
},
onGestureTouchStart(e) {
if (!this.data.enableEdgeGesture) return;
this.setData({
gestureStart: {
x: e.touches[0].clientX,
y: e.touches[0].clientY,
time: Date.now()
}
});
},
onGestureTouchMove(e) {
if (!this.data.enableEdgeGesture || !this.data.gestureStart || this.data.gestureTriggered) return;
const touch = e.touches[0];
const start = this.data.gestureStart;
const deltaX = touch.clientX - start.x;
const deltaY = touch.clientY - start.y;
const deltaTime = Date.now() - start.time;
const minDistance = 30;
const maxTime = 300;
switch (this.data.position) {
case 'right':
if (deltaX < -minDistance && Math.abs(deltaY) < Math.abs(deltaX) && deltaTime < maxTime) {
this.triggerGestureShow();
}
break;
case 'left':
if (deltaX > minDistance && Math.abs(deltaY) < Math.abs(deltaX) && deltaTime < maxTime) {
this.triggerGestureShow();
}
break;
case 'bottom':
if (deltaY < -minDistance && Math.abs(deltaX) < Math.abs(deltaY) && deltaTime < maxTime) {
this.triggerGestureShow();
}
break;
case 'top':
if (deltaY > minDistance && Math.abs(deltaX) < Math.abs(deltaY) && deltaTime < maxTime) {
this.triggerGestureShow();
}
break;
}
},
onGestureTouchEnd(e) {
this.setData({
gestureStart: null
});
},
triggerGestureShow() {
if (this.data.gestureTriggered) return;
this.setData({
gestureTriggered: true
}, () => {
this.show();
setTimeout(() => {
this.setData({
gestureTriggered: false
});
}, 1000);
});
}
}
});