| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- Component({
- options: {
- multipleSlots: true,
- addGlobalClass: true
- },
- properties: {
- list: {
- type: Array
- },
- active: {
- type: Number,
- value: 0
- },
- onChenge: {
- type: Function
- },
- showIcon: {
- type: Boolean,
- value: true
- },
- anchor: {
- type: Number,
- value: 0.4 // 锚点位置,0-1,表示选中项中心在容器宽度的比例位置
- },
- mode: {
- type: String,
- value: 'scroll' // 'scroll' 滚动模式, 'flat' 平铺模式
- }
- },
- data: {
- scrollLeft: 0,
- startPoint: 0,
- slipFlag: false,
- },
- lifetimes: {
- attached: function () {
- getApp().globalData.Language.getLanguagePackage(this);
- },
- ready: function () {
- this.setActive();
- }
- },
- methods: {
- tabsChenge(e) {
- const { index } = e.currentTarget.dataset;
- if (this.data.active == index) return;
- this.setData({
- active: index
- }, () => {
- this.setActive();
- });
- },
- setActive() {
- 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) {
- return; // 禁用滑动切换
- this.setData({
- slipFlag: true,
- startPoint: e.touches[0]
- })
- },
- myTouchMove(e) {
- return; // 禁用滑动切换
- let active = this.data.active;
- if (((this.data.startPoint.clientX - e.touches[e.touches.length - 1].clientX) > 80) && this.data.slipFlag) {
- if (active != this.data.list.length - 1) active++;
- this.setData({
- slipFlag: false,
- active
- })
- } else if (((this.data.startPoint.clientX - e.touches[e.touches.length - 1].clientX) < -80) && this.data.slipFlag) {
- if (active != 0) active--;
- this.setData({
- slipFlag: false,
- active
- })
- }
- this.setActive();
- },
- }
- });
|