Browse Source

refactor(book.vue): 优化元素位置计算逻辑并添加唯一ID

重构getAllElementPositions方法,使用DOM API替代原有实现
为scroll-view和内容元素添加唯一ID以便精确定位
移除不必要的注释代码和调试日志
调整图片样式去除固定高度限制
main
前端-胡立永 2 days ago
parent
commit
ee92c2a082
1 changed files with 103 additions and 28 deletions
  1. +103
    -28
      subPages/home/book.vue

+ 103
- 28
subPages/home/book.vue View File

@ -20,7 +20,9 @@
<swiper class="content-swiper" :current="currentPage - 1" @change="onSwiperChange">
<swiper-item v-for="(page, index) in bookPages" :key="index" class="swiper-item">
<scroll-view scroll-y :scroll-top="scrollTops[index] || 0" :scroll-with-animation="true"
style="height: 100vh;" class="scroll-container" @scroll="onScroll" @touchstart="onTouchStart"
style="height: 100vh;"
:id="`scroll-container-${index}`"
class="scroll-container" @scroll="onScroll" @touchstart="onTouchStart"
@touchmove="onTouchMove" @touchend="onTouchEnd">
<view class="content-area" @click="toggleNavbar">
<view class="title">{{ currentPageTitle }}</view>
@ -40,19 +42,10 @@
<text class="card-line-text">划线重点</text>
</view>
<view v-for="(item, itemIndex) in page" :key="itemIndex" class="text-content">
<image class="card-image" v-if="item && item.type === 'image'" :src="item.imageUrl"
<image class="card-image"
:id="`image-${itemIndex}`"
v-if="item && item.type === 'image'" :src="item.imageUrl"
mode="widthFix"></image>
<!-- <view :class="['english-text-container', 'clickable-text', { 'lead-text': isCardTextHighlighted(page, itemIndex) }]" v-else-if="item && item.type === 'text' && item.language === 'en' && item.content" @click.stop="handleTextClick(item.content, item, index)" >
<text
v-for="(token, tokenIndex) in splitEnglishSentence(item.content)"
:key="tokenIndex"
:class="['english-token', { 'clickable-word': token.isWord && findWordDefinition(token.text) }]"
@click.stop="token.isWord && findWordDefinition(token.text) ? handleWordClick(token.text) : null"
user-select
:style="item.style"
>{{ token.text }}</text>
</view> -->
<!-- <view :class="{ 'lead-text': isCardTextHighlighted(page, itemIndex) }" v-else-if="item && item.type === 'text' && item.language === 'zh' && item.content" @click.stop="handleTextClick(item.content, item, index)"> -->
<view :class="{
'lead-text': isCardTextHighlighted(page, itemIndex),
'introduction-text' : item.isLead,
@ -89,12 +82,12 @@
<!-- 图片页面 -->
<view v-else-if="item.type === 'image'" class="image-container"
:ref="`imageRef_${index}_${itemIndex}`">
:ref="`imageRef_${index}_${itemIndex}`" :id="`image-${itemIndex}`">
<image class="content-image" :src="item.imageUrl" mode="widthFix"></image>
</view>
<!-- 视频页面 -->
<view v-else-if="item.type === 'video'" class="video-content" @click.stop>
<view v-else-if="item.type === 'video'" class="video-content" :id="`video-${itemIndex}`" @click.stop>
<!-- 视频加载状态 -->
<view v-if="videoLoading" class="video-loading">
<text class="loading-text">视频加载中...</text>
@ -795,7 +788,7 @@ export default {
}
}
console.log('开始滚动到文本:', { selector, scrollData });
//console.log(':', { selector, scrollData });
//
this.isScrolling = true;
@ -954,14 +947,15 @@ export default {
},
//
/*
async getAllElementPositions() {
return new Promise((resolve) => {
//
if (this.elementPositionsCache[this.currentPage - 1]) {
resolve(this.elementPositionsCache[this.currentPage - 1]);
return;
}
// if (this.elementPositionsCache[this.currentPage - 1]) {
// resolve(this.elementPositionsCache[this.currentPage - 1]);
// return;
// }
const currentPageData = this.bookPages[this.currentPage - 1];
if (!currentPageData || !Array.isArray(currentPageData)) {
@ -981,9 +975,9 @@ export default {
if (item.type === 'text') {
query.select(`#text-${index}`).boundingClientRect();
} else if (item.type === 'image') {
query.select(`.image-container`).boundingClientRect();
query.select(`#image-${index}`).boundingClientRect();
} else if (item.type === 'video') {
query.select(`.video-content`).boundingClientRect();
query.select(`#video-${index}`).boundingClientRect();
}
}
});
@ -998,19 +992,28 @@ export default {
//
let resultIndex = 1; //
let constTop = 0
let constTopType = {
'text': 10,
'image': 10,
'video': 10,
}
currentPageData.forEach((item, index) => {
if (item && (item.type === 'text' || item.type === 'image' || item.type === 'video')) {
const elementRect = res[resultIndex];
if (elementRect) {
let top = elementRect.top - (containerRect.height / 2);
const currentScrollTop = this.scrollTops[this.currentPage - 1] || 0;
const top = constTop;
// const top = (elementRect.top - containerRect.top) + currentScrollTop;
elementPositions.push({
id : elementRect.id,
index: index,
id: elementRect.id,
index,
type: item.type,
top: top,
top,
height: elementRect.height,
bottom: top + elementRect.height
});
constTop += elementRect.height + constTopType[item.type];
}
resultIndex++;
}
@ -1026,6 +1029,79 @@ export default {
return elementPositions;
});
},
*/
// 使 DOM API H5
async getAllElementPositions() {
// const cached = this.elementPositionsCache[this.currentPage - 1];
// if (cached && Array.isArray(cached)) {
// return cached;
// }
const currentPageData = this.bookPages[this.currentPage - 1];
if (!currentPageData || !Array.isArray(currentPageData)) {
return [];
}
// DOM
await this.$nextTick();
const rootEl = this.$el || document;
let currentPage = this.currentPage - 1;
let containerId = `scroll-container-${currentPage}`;
const containerEl = (rootEl.querySelector ? rootEl.querySelector(`#${containerId}`) : null) || document.querySelector('.scroll-container');
if (!containerEl || typeof containerEl.getBoundingClientRect !== 'function') {
console.warn('[getAllElementPositions] 未找到滚动容器或不支持 DOM API');
return [];
}
const containerRect = containerEl.getBoundingClientRect();
// console.log('document.getElementById containerEl', containerEl);
const currentScrollTop = this.scrollTops[this.currentPage] || 0;
const elementPositions = [];
let constTop = 0
let constTopType = {
'text': 10,
'image': 10,
'video': 10,
}
currentPageData.forEach((item, index) => {
if (!item || !item.type) return;
let el = document.querySelector(`#${containerId} #${item.type}-${index}`);
// console.log('document.getElementById', `${item.type}-${index}`, el.clientHeight, el);
if (el && typeof el.getBoundingClientRect === 'function') {
const rect = el.getBoundingClientRect();
const top = constTop;
elementPositions.push({
id: el.id || '',
index,
type: item.type,
top,
height: rect.height,
bottom: top + rect.height
});
constTop += rect.height + constTopType[item.type];
}
});
if (elementPositions.length > 0) {
this.elementPositionsCache[this.currentPage - 1] = elementPositions;
}
return elementPositions;
},
awaitSleep(time) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, time);
});
},
//
isElementInViewport(elementPosition, currentScrollTop) {
@ -1926,7 +2002,6 @@ export default {
//
clearWordAudioCache() {
this.wordAudioCache = {};
},
// 访
@ -2365,7 +2440,7 @@ export default {
.card-image {
// width: 590rpx;
width: 100%;
height: 268rpx;
//height: 268rpx;
border-radius: 24rpx;
margin: 30rpx auto;
// margin-bottom: 20rpx;


Loading…
Cancel
Save