Files
ebiz-ai-knowledge-manage/public/pdfjs-dist/web/layer.js
陈昱达 5ab8576d3b feat(web): 添加注释图标和 Alt 文本图标
- 新增多个注释相关图标,包括检查、评论、帮助、插入、键、新段落、无图标、笔记、回形针、段落和图钉图标
- 添加 Alt 文本图标
- 增加版权信息文件
2025-04-08 19:28:15 +08:00

334 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
var LAYER_CHANGE_ACTIVE_CLASS = 'layerChange-active'
// 获取 button 元素
var layerChangeButton = document.getElementById('layerChange');
var isLayerChangeButtonActive = () => {
return layerChangeButton.classList.contains(LAYER_CHANGE_ACTIVE_CLASS)
}
var getLocale = () => {
console.log('test-iframe-locale', localStorage.getItem('umi-locale') ,localStorage.getItem('locale') , '')
return localStorage.getItem('umi_locale') || localStorage.getItem('locale') || 'zh-CN';
}
// 添加tooltip
function createHoverTooltip(element, tooltipText, id, options = {}) {
const tooltip = document.createElement('div');
tooltip.className = `tooltip-${id} tooltip`;
tooltip.style.display = 'none';
tooltip.style.zIndex = '999';
document.body.appendChild(tooltip);
const defaultOptions = {
offset: { y: 10 },
delay: 200,
duration: 200,
};
const mergedOptions = { ...defaultOptions, ...options };
let tooltipTimer;
function positionTooltip() {
const rect = element.getBoundingClientRect();
const tooltipRect = tooltip.getBoundingClientRect();
const left = rect.left + (rect.width - tooltipRect.width) / 2;
const top = rect.bottom + mergedOptions.offset.y;
tooltip.style.left = `${left}px`;
tooltip.style.top = `${top}px`;
}
function showTooltip() {
tooltip.textContent = tooltipText;
tooltip.style.display = 'block';
tooltip.style.opacity = '0';
tooltip.style.transition = `opacity ${mergedOptions.duration}ms`;
positionTooltip();
setTimeout(() => {
tooltip.style.opacity = '1';
}, 10);
}
function hideTooltip() {
tooltip.style.opacity = '0';
setTimeout(() => {
tooltip.style.display = 'none';
}, mergedOptions.duration);
}
element.addEventListener('mouseenter', () => {
tooltipTimer = setTimeout(showTooltip, mergedOptions.delay);
});
element.addEventListener('mouseleave', () => {
clearTimeout(tooltipTimer);
hideTooltip();
});
window.addEventListener('resize', positionTooltip);
window.addEventListener('scroll', positionTooltip);
// 返回对象,包含 updateTooltipText 函数
return {
updateTooltipText: (newText) => {
tooltipText = newText;
positionTooltip()
if (tooltip.style.display !== 'none') {
showTooltip();
tooltipText = newText;
}
}
};
}
const tooltipLayer = createHoverTooltip(layerChangeButton, getLocale() === 'zh-CN' ? '隐藏识别结果': 'Hide recognition results', 'layerChange', { offset: { y: 22 } });
window.addEventListener('storage', function(event) {
// 检查事件是否与监听的键相关
if (event.key === 'umi_locale'|| event.key === 'locale') {
const text = isLayerChangeButtonActive() ? event?.newValue === 'zh-CN' ? '隐藏识别结果': 'Hide recognition results': getLocale() === 'zh-CN' ? '显示识别结果': 'Display recognition results'
tooltipLayer?.updateTooltipText(text)
}
});
// 添加点击事件监听器
layerChangeButton.addEventListener('click', function() {
// 检查当前 button 的选中状态
if (isLayerChangeButtonActive()) {
// 如果已经处于选中状态,则移除选中状态的 class
const annotationLayerList = document.getElementsByClassName('annotationLayer')
Array?.from(annotationLayerList)?.forEach(element => {
var extractLayer = element.querySelector('#extractLayer');
if(extractLayer) {
extractLayer.style.opacity = 0
}
});
console.log('test-dd', annotationLayerList, typeof annotationLayerList)
tooltipLayer?.updateTooltipText( getLocale() === 'zh-CN' ? '显示识别结果': 'Display recognition results')
this.classList.remove(LAYER_CHANGE_ACTIVE_CLASS);
} else {
// 如果未处于选中状态,则添加选中状态的 class
this.classList.add(LAYER_CHANGE_ACTIVE_CLASS);
tooltipLayer?.updateTooltipText(getLocale() === 'zh-CN' ? '隐藏识别结果': 'Hide recognition results')
const scale = 0.943 / 0.7071 * window?.PDFViewerApplication?.pdfViewer?._currentScale || 1
window.renderExtractLayer(window.pdfExtractData, Number(0), scale)
const annotationLayerList = document.getElementsByClassName('annotationLayer')
Array?.from(annotationLayerList)?.forEach(element => {
var extractLayer = element.querySelector('#extractLayer');
if(extractLayer) {
extractLayer.style.opacity = 1
}
})
}
});
// 获取显示消息的元素
const messageDisplay = document.getElementById('messageDisplay');
function removeDuplicates(arr) {
return [...new Set(arr)];
}
window.addEventListener('error', function(event) {
if (event.target && event.target.tagName === 'SCRIPT') {
console.error("Script error detected: ", event);
}
}, true);
// 添加消息监听器
window.addEventListener('message', function(event) {
const receivedMessage = event.data;
const data = receivedMessage?.data
const type = receivedMessage?.type
function setHasRenderAnimatedPage (num) {
if(!window.hasRenderAnimatedPage ) {
window.hasRenderAnimatedPage = []
}
if( typeof window.hasRenderAnimatedPage === 'object'){
window.hasRenderAnimatedPage = removeDuplicates([...window.hasRenderAnimatedPage, num])
}
}
let animatingBox = new Map()
function renderExtractLayer(data, pageNum, scale) {
// 判断按钮是开的还是关的
if(!isLayerChangeButtonActive()) return;
const bboxes = data?.[pageNum]?.bboxes || []
function drawBoxes(boxes, scale) {
if(animatingBox.get(pageNum)) return
// const annotationLayer = document.querySelector('.canvasWrapper');
const pageLayer = document.getElementsByClassName('page')?.[pageNum]
const annotationLayer = pageLayer.querySelectorAll('.annotationLayer')?.[0];
// annotationLayer.removeAttribute('hidden');
if(!annotationLayer) {
// console.error('error: annotationLayer has not been rendered')
return
}
const extractLayer = annotationLayer.querySelector('#extractLayer');
// 因为pdfjs只会缓存8页的内容所以采用每次切换移除重建canvas的方式
if (extractLayer) {
extractLayer?.remove();
}
annotationLayer.style.width = '100%';
annotationLayer.style.height = '100%'
annotationLayer.style.position = 'absolute';
annotationLayer.style.top = 0;
annotationLayer.style.left = 0;
const computedLayer = document.querySelector('.canvasWrapper');
const canvas = document.createElement('canvas');
canvas.id = 'extractLayer'
const w = pageLayer?.offsetWidth - 18;
const h = pageLayer?.offsetHeight - 18;
canvas.width = true ? `${w}` : '100%';
canvas.height = true ? `${h}`: '100%';
canvas.style.width = true ? `${w}px` : '100%';
canvas.style.height = true ? `${h}px`: '100%';
canvas.style.position = 'absolute';
canvas.style.top = 0;
canvas.style.left = 0;
annotationLayer.append(canvas)
const ctx = canvas.getContext('2d');
// 移除之前的画布内容
// ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
// console.log('renderExtractLayer: draw boxes')
function drawPartialRect(ctx, box, progress, scale) {
const [x, y, x2, y2]= box.bbox.map((i) => (i * scale));
const width = x2 - x;
const height = y2 - y;
const color = box?.color?.line
const fillColor = box?.color?.fill
ctx.beginPath();
ctx.strokeStyle = color;
// 左边竖线
ctx.moveTo(x, y);
ctx.lineTo(x, y2);
// 上边横线
ctx.moveTo(x, y);
ctx.lineTo(x + width * (progress < 0 ? 0: progress), y);
// 右边竖线 (只在进度完成时绘制)
if (progress === 1) {
ctx.moveTo(x2, y);
ctx.lineTo(x2, y2);
ctx.fillStyle = fillColor;
ctx.fillRect(x, y, width, height);
}
// 下边横线
ctx.moveTo(x, y2);
ctx.lineTo(x + width * (progress < 0 ? 0: progress), y2);
ctx.stroke();
}
function fillRect(ctx, box, scale) {
const [x, y, x2, y2]= box.bbox.map((i) => (i * scale));
const width = x2 - x;
const height = y2 - y;
const color = box?.color?.fill
ctx.fillStyle = color;
ctx.fillRect(x, y, width, height);
}
function animateBox(ctx, box, duration = 1000) {
const startTime = performance.now();
function animate(currentTime) {
const elapsedTime = currentTime - startTime;
const progress = Math.min(elapsedTime / duration, 1);
// ctx.clearRect(...box.bbox); // 清除之前的绘制
drawPartialRect(ctx, box, progress, scale);
if (progress < 1) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
}
async function animateAllBoxes() {
// const [index, value] of array.entries()
for (const [index, box] of boxes?.entries()) {
await animateBox(ctx, box, 600); // 动画时间改为500ms
await new Promise(resolve => setTimeout(resolve, 200)); // 每个框之间的延迟也减少到100ms
}
// 所有线框动画完成后,一次性填充所有矩形
// ctx.clearRect(...box.bbox); // 清除之前的绘制
// boxes.forEach(box => fillRect(ctx, box, scale));
console.log("test-animate All animations completed and boxes filled");
animatingBox.set(pageNum, false)
}
boxes.forEach((box, index) => {
drawPartialRect(ctx, box, 1, scale);
});
canvas.style.width = false ? `${w}px` : '100%';
canvas.style.height = false ? `${h}px`: '100%';
ctx.restore();
}
!!bboxes?.length&&drawBoxes(bboxes, scale);
}
// init extractLayer data
if(type === 'initExtractLayerData') {
const scale = 0.943 / 0.7071 * window?.PDFViewerApplication?.pdfViewer?._currentScale || 1
const currentPageNumber = window?.PDFViewerApplication?.pdfViewer?._currentPageNumber || 1
window.pdfExtractData = data;
window.renderExtractLayer = renderExtractLayer
// window.renderExtractLayer(window.pdfExtractData, currentPageNumber - 1, scale)
// use the picture view rather than outlined view
window.renderExtractLayer(window.pdfExtractData, Number(0), scale)
window?.PDFViewerApplication?.pdfSidebar?.switchView(1, false)
}
if(type === 'pageChange') {
if(window.renderExtractLayer
&& window.pdfExtractData
) {
const scale = 0.943 / 0.7071 * window?.PDFViewerApplication?.pdfViewer?._currentScale || 1
const currentPageNumber = data || 0
window.renderExtractLayer(window.pdfExtractData, Number(0), scale)
window.renderExtractLayer(window.pdfExtractData, Number(data), scale)
} else if(!window.pdfExtractData) {
// console.error('extract pdf render data has not been initialized')
}
}
if( type === 'title') {
const odlPdfTitle = document.getElementById("odl-pdf-title");
odlPdfTitle.innerText = data;
}
if( type === 'setPage') {
window?.PDFViewerApplication?.eventBus?.dispatch("pagenumberchanged", {
value: data
})
}
if( type === '') {
}
});