Как создать кликабельные аннотации в библиотеке react-pdf?

У меня есть компонент для просмотра PDF файлов. Я добавил свойство <i>renderAnnotationLayer={true}</i> в <i>Page</i> и импортировал стили через <i>import 'react-pdf/dist/Page/AnnotationLayer.css';</i>, поскольку они, по моему мнению, необходимы для корректной работы. На <i>localhost</i> ссылки открываются как в мобильном, так и в обычном режиме. Однако после развертывания изменений на сайт в мобильном режиме ссылки перестают открываться и не работают даже с мобильного устройства. <br/> У меня есть вопросы по компоненту: <br/> SCSS: <br/>
  • 15 апреля 2025 г. 21:35
Ответы на вопрос 2
Для создания кликабельных аннотаций в библиотеке `react-pdf` и обеспечения корректного поведения на мобильных устройствах, вам нужно выполнить несколько шагов. Опишу основные моменты и дам советы по решению проблем, которые могут возникнуть.

### Шаги для создания кликабельных аннотаций:

1. **Убедитесь, что вы используете последние версии библиотек**:
   - Убедитесь, что у вас установлена актуальная версия `react-pdf`. Проверяйте документацию для получения информации о совместимости и новых функциях.

2. **Использование свойства `renderAnnotationLayer`**:
   - Убедитесь, что вы правильно передаете свойство `renderAnnotationLayer={true}` в компоненте `<Page>`. Например:

   ```jsx
   <Page pageNumber={pageNumber} renderAnnotationLayer={true} />
   ```

3. **Импорт стилей анноций**:
   - Правильно импортируйте стили для аннотаций. Вы уже упомянули об этом, но важно убедиться, что путь корректен:

   ```jsx
   import 'react-pdf/dist/Page/AnnotationLayer.css';
   ```

4. **Настройка обработчиков событий**:
   - Если аннотации не работают на мобильных устройствах, возможно, проблема в том, как вы обрабатываете события. Проверьте, что у вас есть обработчики для кликов по аннотациям, которые открывают ссылки или выполняют другие действия.

### Пример обработки кликов:

Можно использовать личные обработчики событий, чтобы открыть URL ссылок из аннотаций, например:

```jsx
const handleAnnotationClick = (url) => {
  window.open(url, '_blank');
};

// Компонент для отображения страницы
<Page
  pageNumber={pageNumber}
  renderAnnotationLayer={true}
  onClick={(event) => {
    const target = event.target;
    if (target.tagName === 'A') {
      event.preventDefault();
      const url = target.href;
      handleAnnotationClick(url);
    }
  }}
/>
```

### Проблемы с мобильным режимом:

Если ссылки не работают в мобильном браузере после развертывания, раcсмотрите следующие рекомендации:

1. **Проверка CORS**:
   - Убедитесь, что ваш сервер позволяет доступ к PDF файлам из других доменов (CORS настройки).

2. **Тестирование на различных устройствах**:
   - Протестируйте на разных мобильных устройствах и браузерах, чтобы исключить проблемы, связанные с совместимостью.

3. **Просмотр консоли**:
   - Проверьте консоль на наличие ошибок JavaScript или стилей, которые могут свидетельствовать о проблемах в вашем коде или конфигурации.

4. **Кроссбраузерное тестирование**:
   - Иногда поведение может отличаться в зависимости от браузера. Проверьте, как работает ваш компонент в различных браузерах (например, Chrome, Safari, Firefox).

5. **Обновление зависимостей**:
   - Убедитесь, что все зависимости вашего проекта являются актуальными. Иногда проблемы решаются просто обновлением.

Если приведенные рекомендации не помогут, можете предоставить больше деталей о вашем проекте, и я постараюсь помочь вам найти конкретное решение.
Решил проблему сам, оставлю решение, проблема заключается в том, что все ссылки аннотаций размещаются поверх через абсолютную позицию, из-за этого, если нарушаются пропорции экрана, т.е. ширины, все ссылки съезжают, я убрал из компонента TextLayer как scss, так и пропст в , после добавил ref в div, ref={documentWrapperRef}, и в Page добавил вот такую запись width={documentWrapperRef.current?.getBoundingClientRect().width || undefined}. Все работает отлично, вот рабочий код: 
'use client';
import { useRef } from 'react';
import { Document, Page, pdfjs } from 'react-pdf';

// COMPONENTS
import { useModalControl } from '@components/modals/document-modal/hooks/useModalControl';
import { usePdfViewer } from '@components/modals/document-modal/hooks/usePdfViewer';
import { PdfControls } from './components/PdfControls';

// STYLES
import 'react-pdf/dist/Page/AnnotationLayer.css';
import style from './DocumentModal.module.scss';

// Установите worker
pdfjs.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString();

interface DocumentModalProps {
	isOpen: boolean;
	onClose: () => void;
	documentUrl: string;
}

export const DocumentModal = ({ isOpen, onClose, documentUrl }: DocumentModalProps) => {
	const dialogRef = useModalControl(isOpen);
	const documentWrapperRef = useRef<HTMLDivElement>(null);
	const {
		scale,
		isLoading,
		error,
		numPages,
		handleZoomIn,
		handleZoomOut,
		handleLoadSuccess,
		handleLoadError,
		handleDownload,
	} = usePdfViewer();

	if (!isOpen) return null;

	return (
		<dialog ref={dialogRef} className={style['document-modal']} onClose={onClose}>
			<div
				className={style['document-modal__overlay']}
				onClick={e => {
					if (e.target === e.currentTarget) {
						onClose();
					}
				}}
			>
				<div className={style['document-modal__wrapper']}>
					<PdfControls
						scale={scale}
						onZoomIn={handleZoomIn}
						onZoomOut={handleZoomOut}
						onDownload={() => handleDownload(documentUrl)}
						onClose={onClose}
					/>

					<div className={style['document-modal__content']} ref={documentWrapperRef}>
						{isLoading && <div className={style['document-modal__loader']}>Загрузка документа...</div>}
						{error && <div className={style['document-modal__error']}>{error}</div>}

						<Document
							file={documentUrl}
							onLoadSuccess={handleLoadSuccess}
							onLoadError={handleLoadError}
							loading={null}
							noData={null}
							externalLinkTarget='_blank'
						>
							{Array.from(new Array(numPages), (el, index) => (
								<Page
									key={`page_${index + 1}`}
									pageNumber={index + 1}
									renderAnnotationLayer={true}
									scale={scale}
									className={style['document-modal__page']}
									loading={null}
									width={documentWrapperRef.current?.getBoundingClientRect().width || undefined}
								/>
							))}
						</Document>
					</div>
				</div>
			</div>
		</dialog>
	);
};
Похожие вопросы