diff --git a/templates/translation.html b/templates/translation.html
index 246aec8..6decc03 100644
--- a/templates/translation.html
+++ b/templates/translation.html
@@ -119,16 +119,20 @@
`;
- // 如果有PDF,用PDF.js渲染
- if (result.original_pdf_url) {
- renderPDF(result.original_pdf_url);
- }
+ // 先计算译文位置(因为已经渲染好了)
+ setTimeout(calculateTranslatedPositions, 100);
- // 计算各页位置并启用滚动同步
- setTimeout(() => {
- calculatePagePositions();
- enableSyncScroll();
- }, 500);
+ // 如果有PDF,用PDF.js渲染,完成后计算位置并启用同步
+ if (result.original_pdf_url) {
+ renderPDF(result.original_pdf_url).then(() => {
+ setTimeout(() => {
+ calculatePdfPositions();
+ enableSyncScroll();
+ }, 200);
+ });
+ } else {
+ setTimeout(enableSyncScroll, 300);
+ }
} catch (error) {
alert('加载对比失败: ' + error.message);
@@ -142,17 +146,17 @@
function renderTranslatedByPage(content) {
if (!content) return '
@@ -165,103 +169,109 @@
return html;
}
- // PDF.js渲染PDF
+ // PDF.js渲染PDF(返回Promise)
async function renderPDF(url) {
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
- try {
- const pdf = await pdfjsLib.getDocument(url).promise;
- pdfDoc = pdf;
+ const pdf = await pdfjsLib.getDocument(url).promise;
+ pdfDoc = pdf;
+
+ const container = document.getElementById('pdfPages');
+ container.innerHTML = '';
+
+ // 渲染所有页面
+ for (let i = 1; i <= pdf.numPages; i++) {
+ // 页码标识
+ const pageNumDiv = document.createElement('div');
+ pageNumDiv.className = 'page-header text-center text-muted mb-2';
+ pageNumDiv.textContent = `— 第 ${i} 页 —`;
+ pageNumDiv.dataset.page = i;
+ container.appendChild(pageNumDiv);
- const container = document.getElementById('pdfPages');
- container.innerHTML = '';
+ const page = await pdf.getPage(i);
+ const canvas = document.createElement('canvas');
+ canvas.className = 'pdf-page-canvas';
+ canvas.style.width = '100%';
+ canvas.style.display = 'block';
+ canvas.style.marginBottom = '20px';
+ canvas.dataset.page = i;
- // 渲染所有页面
- for (let i = 1; i <= pdf.numPages; i++) {
- // 页码标识
- const pageNumDiv = document.createElement('div');
- pageNumDiv.className = 'page-header text-center text-muted mb-2';
- pageNumDiv.textContent = `— 第 ${i} 页 —`;
- pageNumDiv.dataset.page = i;
- container.appendChild(pageNumDiv);
-
- const page = await pdf.getPage(i);
- const canvas = document.createElement('canvas');
- canvas.className = 'pdf-page-canvas';
- canvas.style.width = '100%';
- canvas.style.display = 'block';
- canvas.style.marginBottom = '20px';
- canvas.dataset.page = i;
-
- const context = canvas.getContext('2d');
- const viewport = page.getViewport({ scale: 1.5 });
-
- canvas.height = viewport.height;
- canvas.width = viewport.width;
-
- await page.render({
- canvasContext: context,
- viewport: viewport
- }).promise;
-
- container.appendChild(canvas);
- }
- } catch (error) {
- document.getElementById('pdfContainer').innerHTML =
- '
PDF加载失败: ' + error.message + '
';
+ const context = canvas.getContext('2d');
+ const viewport = page.getViewport({ scale: 1.5 });
+
+ canvas.height = viewport.height;
+ canvas.width = viewport.width;
+
+ await page.render({
+ canvasContext: context,
+ viewport: viewport
+ }).promise;
+
+ container.appendChild(canvas);
}
+
+ return pdf;
}
- // 计算各页位置
- function calculatePagePositions() {
- const originalPanel = document.getElementById('originalPanel');
- const translatedPanel = document.getElementById('translatedPanel');
-
- // PDF各页位置
- pagePositions = [];
- const pdfPages = document.querySelectorAll('#pdfPages .page-header, #pdfPages .pdf-page-canvas');
- pdfPages.forEach(el => {
- if (el.dataset.page) {
- const rect = el.getBoundingClientRect();
- const panelRect = originalPanel.getBoundingClientRect();
- pagePositions.push({
- page: parseInt(el.dataset.page),
- top: rect.top - panelRect.top + originalPanel.scrollTop
- });
- }
- });
-
- // 译文各页位置
+ // 计算译文各页位置(相对于滚动容器顶部)
+ function calculateTranslatedPositions() {
translatedPagePositions = [];
+ const translatedPanel = document.getElementById('translatedPanel');
const translatedPages = document.querySelectorAll('.translated-page');
+
translatedPages.forEach(el => {
const page = parseInt(el.dataset.page);
+ // 使用getBoundingClientRect计算相对位置
const rect = el.getBoundingClientRect();
const panelRect = translatedPanel.getBoundingClientRect();
+ // 相对位置 = 元素top - 容器top + 当前scrollTop
+ const relativeTop = rect.top - panelRect.top + translatedPanel.scrollTop;
translatedPagePositions.push({
page: page,
- top: rect.top - panelRect.top + translatedPanel.scrollTop
+ top: relativeTop
});
});
+
+ console.log('译文页位置:', translatedPagePositions);
}
- // 按页滚动同步
- function syncToPage(sourcePanel, targetPanel, sourcePositions, targetPositions) {
- const scrollTop = sourcePanel.scrollTop;
+ // 计算PDF各页位置(相对于滚动容器顶部)
+ function calculatePdfPositions() {
+ pagePositions = [];
+ const originalPanel = document.getElementById('originalPanel');
+ const pdfPages = document.querySelectorAll('#pdfPages .page-header');
- // 找当前页
- let currentPage = 1;
- for (let i = sourcePositions.length - 1; i >= 0; i--) {
- if (scrollTop >= sourcePositions[i].top - 50) {
- currentPage = sourcePositions[i].page;
- break;
+ pdfPages.forEach(el => {
+ const page = parseInt(el.dataset.page);
+ // 使用getBoundingClientRect计算相对位置
+ const rect = el.getBoundingClientRect();
+ const panelRect = originalPanel.getBoundingClientRect();
+ // 相对位置 = 元素top - 容器top + 当前scrollTop
+ const relativeTop = rect.top - panelRect.top + originalPanel.scrollTop;
+ pagePositions.push({
+ page: page,
+ top: relativeTop
+ });
+ });
+
+ console.log('PDF页位置:', pagePositions);
+ }
+
+ // 根据滚动位置找当前页
+ function findCurrentPage(scrollTop, positions) {
+ for (let i = positions.length - 1; i >= 0; i--) {
+ if (scrollTop >= positions[i].top - 30) {
+ return positions[i].page;
}
}
-
- // 找目标页位置
- const targetPos = targetPositions.find(p => p.page === currentPage);
- if (targetPos) {
- targetPanel.scrollTop = targetPos.top - 20;
+ return 1;
+ }
+
+ // 滚动到指定页
+ function scrollToPage(panel, positions, pageNum) {
+ const pos = positions.find(p => p.page === pageNum);
+ if (pos) {
+ panel.scrollTop = pos.top - 10;
}
}
@@ -270,19 +280,26 @@
const originalPanel = document.getElementById('originalPanel');
const translatedPanel = document.getElementById('translatedPanel');
- if (!originalPanel || !translatedPanel) return;
+ if (!originalPanel || !translatedPanel || pagePositions.length === 0 || translatedPagePositions.length === 0) {
+ console.log('滚动同步未启用: 缺少元素或位置数据');
+ return;
+ }
+
+ console.log('滚动同步已启用');
originalPanel.addEventListener('scroll', function() {
if (!syncScrollEnabled) return;
+ const currentPage = findCurrentPage(this.scrollTop, pagePositions);
syncScrollEnabled = false;
- syncToPage(originalPanel, translatedPanel, pagePositions, translatedPagePositions);
+ scrollToPage(translatedPanel, translatedPagePositions, currentPage);
setTimeout(() => syncScrollEnabled = true, 100);
});
translatedPanel.addEventListener('scroll', function() {
if (!syncScrollEnabled) return;
+ const currentPage = findCurrentPage(this.scrollTop, translatedPagePositions);
syncScrollEnabled = false;
- syncToPage(translatedPanel, originalPanel, translatedPagePositions, pagePositions);
+ scrollToPage(originalPanel, pagePositions, currentPage);
setTimeout(() => syncScrollEnabled = true, 100);
});
}