|
|
|
@ -373,9 +373,9 @@ export default { |
|
|
|
if (Math.abs(previousScrollTop - scrollTop) > 5) { |
|
|
|
// 检测是否为手动滚动(如果正在自动滚动中,但滚动位置与预期不符,则认为是手动滚动) |
|
|
|
if (this.isScrolling) { |
|
|
|
// 如果滚动差异很大,可能是用户手动滚动,中断自动滚动状态 |
|
|
|
// 提高手动滚动检测阈值,减少误判 |
|
|
|
const scrollDifference = Math.abs(previousScrollTop - scrollTop); |
|
|
|
if (scrollDifference > 50) { // 调整阈值,避免误判 |
|
|
|
if (scrollDifference > 80) { // 从50提高到80,减少误判 |
|
|
|
console.log('🖐️ 检测到手动滚动,中断自动滚动状态'); |
|
|
|
this.isScrolling = false; |
|
|
|
this.lastUserScrollTime = Date.now(); // 记录手动滚动时间 |
|
|
|
@ -841,7 +841,8 @@ export default { |
|
|
|
const currentScroll = this.scrollTops[this.currentPage - 1] || 0; |
|
|
|
const scrollDifference = Math.abs(preciseScrollTop - currentScroll); |
|
|
|
|
|
|
|
if (scrollDifference > 20) { |
|
|
|
// 提高滚动阈值,减少不必要的微小滚动 |
|
|
|
if (scrollDifference > 30) { // 从20提高到30 |
|
|
|
this.$set(this.scrollTops, this.currentPage - 1, preciseScrollTop); |
|
|
|
console.log('✅ 使用精确位置滚动:', { |
|
|
|
selector, |
|
|
|
@ -856,7 +857,7 @@ export default { |
|
|
|
}, 200); |
|
|
|
} else { |
|
|
|
resetScrollingState(); |
|
|
|
console.log('📍 目标已在视野内,无需滚动'); |
|
|
|
console.log('📍 目标已在最佳可视位置,无需滚动'); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 精确计算失败,使用原有的查询方法作为备用 |
|
|
|
@ -910,7 +911,8 @@ export default { |
|
|
|
const currentScroll = this.scrollTops[this.currentPage - 1] || 0; |
|
|
|
const scrollDifference = Math.abs(finalScrollTop - currentScroll); |
|
|
|
|
|
|
|
if (scrollDifference > 20) { // 进一步降低滚动阈值,提高响应性 |
|
|
|
// 提高滚动阈值,减少不必要的微小滚动 |
|
|
|
if (scrollDifference > 30) { // 从20提高到30,与精确滚动保持一致 |
|
|
|
this.$set(this.scrollTops, this.currentPage - 1, finalScrollTop); |
|
|
|
|
|
|
|
// 滚动完成后重置状态 |
|
|
|
@ -928,7 +930,7 @@ export default { |
|
|
|
} else { |
|
|
|
// 不需要滚动,立即重置状态 |
|
|
|
resetScrollingState(); |
|
|
|
console.log('📍 目标已在视野内,无需滚动'); |
|
|
|
console.log('📍 目标已在最佳可视位置,无需滚动'); |
|
|
|
} |
|
|
|
} else { |
|
|
|
console.error('❌ 未找到目标元素或scroll-view:', { |
|
|
|
@ -1035,6 +1037,75 @@ export default { |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
// 检查元素是否在可视范围内 |
|
|
|
isElementInViewport(elementPosition, currentScrollTop) { |
|
|
|
const screenHeight = uni.getSystemInfoSync().windowHeight; |
|
|
|
const viewportTop = currentScrollTop; |
|
|
|
const viewportBottom = currentScrollTop + screenHeight; |
|
|
|
|
|
|
|
// 元素的顶部和底部位置 |
|
|
|
const elementTop = elementPosition.top; |
|
|
|
const elementBottom = elementPosition.bottom; |
|
|
|
|
|
|
|
// 检查元素是否完全或部分在可视范围内 |
|
|
|
const isVisible = elementBottom > viewportTop && elementTop < viewportBottom; |
|
|
|
|
|
|
|
// 计算元素在可视范围内的比例 |
|
|
|
const visibleTop = Math.max(elementTop, viewportTop); |
|
|
|
const visibleBottom = Math.min(elementBottom, viewportBottom); |
|
|
|
const visibleHeight = Math.max(0, visibleBottom - visibleTop); |
|
|
|
const visibilityRatio = visibleHeight / elementPosition.height; |
|
|
|
|
|
|
|
return { |
|
|
|
isVisible, |
|
|
|
visibilityRatio, |
|
|
|
elementTop, |
|
|
|
elementBottom, |
|
|
|
viewportTop, |
|
|
|
viewportBottom |
|
|
|
}; |
|
|
|
}, |
|
|
|
|
|
|
|
// 计算最佳滚动位置 |
|
|
|
calculateOptimalScrollPosition(targetElement, currentScrollTop) { |
|
|
|
const screenHeight = uni.getSystemInfoSync().windowHeight; |
|
|
|
|
|
|
|
// 检查当前元素的可见性 |
|
|
|
const visibility = this.isElementInViewport(targetElement, currentScrollTop); |
|
|
|
|
|
|
|
// 如果元素已经完全可见且在合适位置,不需要滚动 |
|
|
|
if (visibility.isVisible && visibility.visibilityRatio > 0.8) { |
|
|
|
// 检查元素是否在屏幕的合适位置(上方1/3到2/3之间) |
|
|
|
const elementCenter = (targetElement.top + targetElement.bottom) / 2; |
|
|
|
const relativePosition = (elementCenter - currentScrollTop) / screenHeight; |
|
|
|
|
|
|
|
if (relativePosition >= 0.2 && relativePosition <= 0.7) { |
|
|
|
console.log('📍 元素已在最佳可视位置,无需滚动'); |
|
|
|
return null; // 不需要滚动 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 计算目标滚动位置:让元素显示在屏幕上方1/3处(更舒适的阅读位置) |
|
|
|
const optimalOffsetRatio = 0.3; // 30%的位置,比1/4更舒适 |
|
|
|
const offsetFromTop = screenHeight * optimalOffsetRatio; |
|
|
|
|
|
|
|
// 考虑元素高度,确保不会被截断 |
|
|
|
const elementHeight = targetElement.height; |
|
|
|
const adjustedOffset = Math.min(offsetFromTop, screenHeight * 0.1); // 最小10%偏移 |
|
|
|
|
|
|
|
const targetScrollTop = Math.max(0, targetElement.top - adjustedOffset); |
|
|
|
|
|
|
|
console.log('🎯 计算最佳滚动位置:', { |
|
|
|
currentVisibility: visibility, |
|
|
|
elementHeight, |
|
|
|
optimalOffsetRatio, |
|
|
|
adjustedOffset, |
|
|
|
targetScrollTop |
|
|
|
}); |
|
|
|
|
|
|
|
return targetScrollTop; |
|
|
|
}, |
|
|
|
|
|
|
|
// 计算精确的滚动位置 |
|
|
|
async calculatePreciseScrollPosition(scrollData, elementPositions) { |
|
|
|
if (!elementPositions || elementPositions.length === 0) { |
|
|
|
@ -1063,18 +1134,16 @@ export default { |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
// 计算滚动位置:让目标元素显示在屏幕上方1/4处 |
|
|
|
const screenHeight = uni.getSystemInfoSync().windowHeight; |
|
|
|
const offsetFromTop = screenHeight * 0.25; |
|
|
|
// 获取当前滚动位置 |
|
|
|
const currentScrollTop = this.scrollTops[this.currentPage - 1] || 0; |
|
|
|
|
|
|
|
// 目标滚动位置 = 目标元素顶部位置 - 偏移量 |
|
|
|
const targetScrollTop = Math.max(0, targetElement.top - offsetFromTop); |
|
|
|
// 使用优化的滚动位置计算 |
|
|
|
const targetScrollTop = this.calculateOptimalScrollPosition(targetElement, currentScrollTop); |
|
|
|
|
|
|
|
console.log('🎯 精确滚动位置计算:', { |
|
|
|
targetElementIndex, |
|
|
|
targetElement, |
|
|
|
screenHeight, |
|
|
|
offsetFromTop, |
|
|
|
currentScrollTop, |
|
|
|
targetScrollTop |
|
|
|
}); |
|
|
|
|
|
|
|
|