Skip to content

Commit e697f03

Browse files
Zoom2 try1 (#25)
* wip * 900 px * cleanup * refactor: Add getVirtualItemAndOffsetAt to Reader component Co-authored-by: aider (vertex_ai/gemini-2.5-pro) <aider@aider.chat> * feat: Add getVirtualItemAndOffsetAt to ReaderAPI * feat: Add button to get virtual item and offset Co-authored-by: aider (vertex_ai/gemini-2.5-pro) <aider@aider.chat> * wip * refactor: Rename percentageOffset to percentageOffsetY * feat: Add scroll anchoring during zoom Co-authored-by: aider (vertex_ai/gemini-2.5-pro) <aider@aider.chat> * wip: zoom * improvements * refactor: Add offset adjustment to zoomFitWidth Co-authored-by: aider (vertex_ai/gemini-2.5-pro) <aider@aider.chat> * feat: Add horizontal scroll offset calculation Co-authored-by: aider (vertex_ai/gemini-2.5-pro) <aider@aider.chat> * feat: Center zoom on specified horizontal offset Co-authored-by: aider (vertex_ai/gemini-2.5-pro) <aider@aider.chat> * wip * feat: Allow zoom level adjustment by multiple levels Co-authored-by: aider (vertex_ai/gemini-2.5-pro) <aider@aider.chat> * feat: Add point param to increase/decreaseZoom Co-authored-by: aider (vertex_ai/gemini-2.5-pro) <aider@aider.chat> * feat: Add zoom functionality to App component Co-authored-by: aider (vertex_ai/gemini-2.5-pro) <aider@aider.chat> * wip * test increase by 2 levels * update: version --------- Co-authored-by: aider (vertex_ai/gemini-2.5-pro) <aider@aider.chat>
1 parent 0477733 commit e697f03

8 files changed

Lines changed: 252 additions & 69 deletions

File tree

demo/App.tsx

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,33 @@ import "react-pdf/dist/Page/TextLayer.css";
66
import React, { ChangeEvent, useEffect, useRef, useState } from "react";
77
import { Page, pdfjs } from "react-pdf";
88
import { Reader } from "../src/index";
9-
import { PageChangeEvent, ReaderAPI, RenderPageProps } from "../src/types";
9+
import {
10+
PageChangeEvent,
11+
ReaderAPI,
12+
RenderPageProps,
13+
VirtualItemAndOffset,
14+
} from "../src/types";
1015
import TestHighlightsLayer from "./TestHighlights";
1116
import { highlightData } from "./highlightData";
1217

18+
type ZoomMode = "default" | "zoom-in" | "zoom-out";
19+
1320
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
1421

1522
const LoadingComponent = () => {
1623
return <div>Overidden Loading</div>;
1724
};
1825

1926
function App() {
27+
const [zoomMode, setZoomMode] = useState<ZoomMode>("default");
2028
const [pageNum, setPageNum] = useState<number | null>(null);
2129
const [scale, setScale] = useState<number | null>(0.75);
2230
const [file, setFile] = useState<string>("pdf-open-parameters.pdf");
2331
const [wantPage, setWantPage] = useState<number | null>(null);
2432
const [readerAPI, setReaderAPI] = useState<ReaderAPI | null>(null);
2533
const [offset, setOffset] = useState<number | null>(null);
34+
const [virtualItemAndOffset, setVirtualItemAndOffset] =
35+
useState<VirtualItemAndOffset | null>(null);
2636
const [isLoaded, setIsLoaded] = useState<boolean>(false);
2737
const initialHighlight = useRef(false);
2838

@@ -80,6 +90,41 @@ function App() {
8090
// debugger;
8191
};
8292

93+
const toggleZoomMode = () => {
94+
setZoomMode((prevMode) => {
95+
if (prevMode === "default") return "zoom-in";
96+
if (prevMode === "zoom-in") return "zoom-out";
97+
return "default";
98+
});
99+
};
100+
101+
const handleReaderClick = (event: React.MouseEvent<HTMLDivElement>) => {
102+
if (zoomMode === "default" || !readerAPI) return;
103+
104+
const rect = event.currentTarget.getBoundingClientRect();
105+
const point = {
106+
top: event.clientY - rect.top,
107+
left: event.clientX - rect.left,
108+
};
109+
110+
if (zoomMode === "zoom-in") {
111+
readerAPI.increaseZoom(2, point);
112+
} else if (zoomMode === "zoom-out") {
113+
readerAPI.decreaseZoom(1, point);
114+
}
115+
};
116+
117+
const getCursorForZoomMode = (mode: ZoomMode) => {
118+
switch (mode) {
119+
case "zoom-in":
120+
return "zoom-in";
121+
case "zoom-out":
122+
return "zoom-out";
123+
default:
124+
return "auto";
125+
}
126+
};
127+
83128
useEffect(() => {
84129
if (!readerAPI || initialHighlight.current) return;
85130
readerAPI?.jumpToHighlightArea(highlightData[0]);
@@ -156,6 +201,24 @@ function App() {
156201
jump to highlight
157202
</button>
158203
<div style={{ display: "flex" }}>
204+
<button
205+
onClick={() => {
206+
const res = readerAPI?.getVirtualItemAndOffsetAt();
207+
setVirtualItemAndOffset(res ?? null);
208+
}}
209+
>
210+
get item and offset
211+
</button>
212+
{virtualItemAndOffset && (
213+
<div>
214+
<div>Index: {virtualItemAndOffset.index}</div>
215+
<div>
216+
Offset: {virtualItemAndOffset.percentageOffsetY.toPrecision(4)}
217+
</div>
218+
</div>
219+
)}
220+
</div>
221+
<div style={{ display: "flex", flexDirection: "column" }}>
159222
<button
160223
onClick={() => {
161224
readerAPI?.decreaseZoom();
@@ -178,6 +241,9 @@ function App() {
178241
zoom default
179242
</button>
180243
<div>{readerAPI?.scale?.toString().substring(0, 3)}</div>
244+
<button onClick={toggleZoomMode} style={{ marginLeft: "10px" }}>
245+
Zoom Mode: {zoomMode}
246+
</button>
181247
</div>
182248
<div style={{ display: "flex" }}>
183249
<button
@@ -199,12 +265,14 @@ function App() {
199265
</div>
200266
<div
201267
style={{
202-
width: "700px",
268+
width: "900px",
203269
height: "800px",
204270
borderColor: "gray",
205271
borderWidth: "1px",
206272
borderStyle: "solid",
273+
cursor: getCursorForZoomMode(zoomMode),
207274
}}
275+
onClick={handleReaderClick}
208276
>
209277
<Reader
210278
file={file}

demo/highlightData.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// highlightData is rendered as percentages
2+
// top, left are percentages transalted from top left as origin of the page
3+
// height and width are also percentages
14
export const highlightData = [
25
{
36
top: 42.9255,

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-pdf-headless",
3-
"version": "0.7.0",
3+
"version": "0.8.0",
44
"type": "module",
55
"files": [
66
"src",

src/Page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { Page as ReactPdfPage } from "react-pdf";
22
import { useEffect, useRef } from "react";
33
import { ReaderPageProps, RenderPage, RenderPageProps } from "./types";
4-
import { EXTRA_HEIGHT } from "./Reader";
54

6-
const EXTRA_WIDTH = 5;
5+
export const EXTRA_WIDTH = 5;
76

87
const Page = ({
98
virtualItem,
@@ -60,16 +59,17 @@ const Page = ({
6059
boxShadow: "2px 2px 8px 0 rgba(0, 0, 0, 0.1)",
6160
width: `${innerBoxWidth}px`,
6261
padding: "0px",
63-
margin: "5px",
62+
margin: "0px",
6463
backgroundColor: "white",
6564
display: "flex",
6665
justifyContent: "center",
67-
height: `${`${virtualItem.size - EXTRA_HEIGHT}px`}`,
66+
height: `${virtualItem.size}px`,
6867
}}
6968
className={classes?.pageInnerBox}
7069
>
7170
{shouldRender && (
7271
<div
72+
id="page-wrapper"
7373
style={{
7474
position: "relative",
7575
height: "fit-content",

0 commit comments

Comments
 (0)