duidui_mini_program/components/resize-box/index.js
2026-03-27 10:41:46 +08:00

105 lines
3.1 KiB
JavaScript

Component({
properties: {
// 当前高度
height: {
type: Number,
value: 200
},
// 最小高度
minHeight: {
type: Number,
value: 100
},
// 最大高度
maxHeight: {
type: Number,
value: 400
},
// 预设高度点,用于自动吸附
presetHeights: {
type: Array,
value: [100, 150, 200, 250, 300, 350, 400]
},
showHandle: {
type: Boolean,
value: true
}
},
data: {
isResizing: false,
currentStyle: '',
currentHeight: 200
},
observers: {
'height': function (val) {
// 只有非拖动时才同步外部高度
if (!this.data.isResizing) {
this.setData({ currentHeight: val });
}
}
},
methods: {
startResize(e) {
const touch = e.touches[0];
this.startY = touch.clientY;
this.startHeight = this.data.currentHeight;
this.setData({
isResizing: true,
currentStyle: 'transition: none;'
});
// 触发开始事件
this.triggerEvent('resizestart', {
height: this.data.height
});
},
onResize(e) {
if (!this.data.isResizing) return;
const touch = e.touches[0];
const deltaY = touch.clientY - this.startY;
let newHeight = this.startHeight + deltaY;
// 限制高度范围
newHeight = Math.max(this.properties.minHeight,
Math.min(newHeight, this.properties.maxHeight));
this.setData({
currentHeight: newHeight
});
// 触发改变事件
this.triggerEvent('resize', {
height: newHeight
});
},
endResize() {
if (!this.data.isResizing) return;
const targetHeight = this.calculateTargetHeight(this.data.currentHeight);
this.setData({
isResizing: false,
currentStyle: 'transition: height 0.3s cubic-bezier(.4,0,.2,1);',
currentHeight: targetHeight
});
// 触发结束事件
this.triggerEvent('resizeend', {
height: targetHeight
});
},
calculateTargetHeight(currentHeight) {
return this.properties.presetHeights.reduce((prev, curr) =>
Math.abs(curr - currentHeight) < Math.abs(prev - currentHeight) ? curr : prev
);
}
}
});