|
@@ -17,49 +17,99 @@ Component({
|
|
|
showIcon: {
|
|
showIcon: {
|
|
|
type: Boolean,
|
|
type: Boolean,
|
|
|
value: true
|
|
value: true
|
|
|
|
|
+ },
|
|
|
|
|
+ anchor: {
|
|
|
|
|
+ type: Number,
|
|
|
|
|
+ value: 0.4 // 锚点位置,0-1,表示选中项中心在容器宽度的比例位置
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
data: {
|
|
data: {
|
|
|
scrollLeft: 0,
|
|
scrollLeft: 0,
|
|
|
- startPoint: 0, //记录滑动的初始位置
|
|
|
|
|
- slipFlag: false, //定义 滑动事件 节流阀, 防止一次滑动触发多次滑动事件
|
|
|
|
|
|
|
+ startPoint: 0,
|
|
|
|
|
+ slipFlag: false,
|
|
|
},
|
|
},
|
|
|
lifetimes: {
|
|
lifetimes: {
|
|
|
attached: function () {
|
|
attached: function () {
|
|
|
- getApp().globalData.Language.getLanguagePackage(this)
|
|
|
|
|
|
|
+ getApp().globalData.Language.getLanguagePackage(this);
|
|
|
|
|
+ },
|
|
|
|
|
+ ready: function () {
|
|
|
|
|
+ this.setActive();
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
tabsChenge(e) {
|
|
tabsChenge(e) {
|
|
|
- const {
|
|
|
|
|
- index
|
|
|
|
|
- } = e.currentTarget.dataset;
|
|
|
|
|
|
|
+ const { index } = e.currentTarget.dataset;
|
|
|
if (this.data.active == index) return;
|
|
if (this.data.active == index) return;
|
|
|
this.setData({
|
|
this.setData({
|
|
|
active: index
|
|
active: index
|
|
|
|
|
+ }, () => {
|
|
|
|
|
+ this.setActive();
|
|
|
});
|
|
});
|
|
|
- this.setActive();
|
|
|
|
|
},
|
|
},
|
|
|
setActive() {
|
|
setActive() {
|
|
|
- const that = this,
|
|
|
|
|
- active = this.data.active,
|
|
|
|
|
- query = wx.createSelectorQuery().in(this)
|
|
|
|
|
- query.select('#active' + active).boundingClientRect(function (res) {
|
|
|
|
|
- that.setData({
|
|
|
|
|
- scrollLeft: res.right - res.width
|
|
|
|
|
- })
|
|
|
|
|
- }).exec();
|
|
|
|
|
- this.triggerEvent("onChenge", active)
|
|
|
|
|
|
|
+ const that = this;
|
|
|
|
|
+ const active = this.data.active;
|
|
|
|
|
+ const anchor = this.data.anchor;
|
|
|
|
|
+ const query = wx.createSelectorQuery().in(this);
|
|
|
|
|
+
|
|
|
|
|
+ query.select('.scroll').fields({ rect: true, scrollOffset: true })
|
|
|
|
|
+ .select(`#active${active}`).boundingClientRect()
|
|
|
|
|
+ .selectAll('.item').boundingClientRect()
|
|
|
|
|
+ .exec((res) => {
|
|
|
|
|
+ const container = res[0];
|
|
|
|
|
+ const elem = res[1];
|
|
|
|
|
+ const items = res[2];
|
|
|
|
|
+
|
|
|
|
|
+ if (!container || !elem || !items || items.length === 0) return;
|
|
|
|
|
+
|
|
|
|
|
+ // 容器宽度通过 right - left 计算
|
|
|
|
|
+ const containerWidth = container.right - container.left;
|
|
|
|
|
+ const containerLeft = container.left;
|
|
|
|
|
+ const currentScrollLeft = container.scrollLeft || 0;
|
|
|
|
|
+
|
|
|
|
|
+ const firstItem = items[0];
|
|
|
|
|
+ const lastItem = items[items.length - 1];
|
|
|
|
|
+
|
|
|
|
|
+ // 第一个元素相对于内容左边界的偏移(通常为0)
|
|
|
|
|
+ const firstItemLeftContent = firstItem.left - containerLeft + currentScrollLeft;
|
|
|
|
|
+ // 最后一个元素右边界相对于内容左边界的偏移
|
|
|
|
|
+ const lastItemRightContent = lastItem.left - containerLeft + currentScrollLeft + lastItem.width;
|
|
|
|
|
+ const contentWidth = lastItemRightContent - firstItemLeftContent;
|
|
|
|
|
+
|
|
|
|
|
+ const viewportWidth = containerWidth;
|
|
|
|
|
+ const maxScrollLeft = Math.max(0, contentWidth - viewportWidth);
|
|
|
|
|
+
|
|
|
|
|
+ // 选中元素在内容中的左偏移(相对于第一个元素)
|
|
|
|
|
+ const elemLeftContent = elem.left - containerLeft + currentScrollLeft - firstItemLeftContent;
|
|
|
|
|
+
|
|
|
|
|
+ // 目标:元素中心位于可视区域宽度 * anchor 处
|
|
|
|
|
+ const targetElemLeftInViewport = viewportWidth * anchor - elem.width / 2;
|
|
|
|
|
+
|
|
|
|
|
+ let targetScrollLeft = elemLeftContent - targetElemLeftInViewport;
|
|
|
|
|
+
|
|
|
|
|
+ // 边界限制
|
|
|
|
|
+ if (targetScrollLeft < 0) targetScrollLeft = 0;
|
|
|
|
|
+ if (targetScrollLeft > maxScrollLeft) targetScrollLeft = maxScrollLeft;
|
|
|
|
|
+
|
|
|
|
|
+ // 避免微小移动
|
|
|
|
|
+ if (Math.abs(targetScrollLeft - currentScrollLeft) < 1) return;
|
|
|
|
|
+
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ scrollLeft: targetScrollLeft
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ this.triggerEvent("onChenge", active);
|
|
|
},
|
|
},
|
|
|
myTouchStart(e) {
|
|
myTouchStart(e) {
|
|
|
- return;
|
|
|
|
|
|
|
+ return; // 禁用滑动切换
|
|
|
this.setData({
|
|
this.setData({
|
|
|
slipFlag: true,
|
|
slipFlag: true,
|
|
|
startPoint: e.touches[0]
|
|
startPoint: e.touches[0]
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
myTouchMove(e) {
|
|
myTouchMove(e) {
|
|
|
- return;
|
|
|
|
|
|
|
+ return; // 禁用滑动切换
|
|
|
let active = this.data.active;
|
|
let active = this.data.active;
|
|
|
if (((this.data.startPoint.clientX - e.touches[e.touches.length - 1].clientX) > 80) && this.data.slipFlag) {
|
|
if (((this.data.startPoint.clientX - e.touches[e.touches.length - 1].clientX) > 80) && this.data.slipFlag) {
|
|
|
if (active != this.data.list.length - 1) active++;
|
|
if (active != this.data.list.length - 1) active++;
|
|
@@ -77,4 +127,4 @@ Component({
|
|
|
this.setActive();
|
|
this.setActive();
|
|
|
},
|
|
},
|
|
|
}
|
|
}
|
|
|
-})
|
|
|
|
|
|
|
+});
|