@@ -87,7 +87,7 @@ export class PDFJSHighlightManager {
87
87
coordinates,
88
88
pageNumber : selection . pageNumber ,
89
89
text : selection . text ,
90
- creationScale : this . pdfViewer . currentScale || 1 , // Store scale at creation time
90
+ coordinateScale : coordinates . coordinateScale , // Store the scale at which coordinates were calculated
91
91
} ;
92
92
93
93
// Store highlight
@@ -169,7 +169,7 @@ export class PDFJSHighlightManager {
169
169
}
170
170
171
171
/**
172
- * Convert selection to coordinates using PDF.js viewport
172
+ * Convert selection to coordinates using PDF.js text layer
173
173
*/
174
174
private convertSelectionToCoordinates (
175
175
selection : SelectionInfo ,
@@ -186,52 +186,73 @@ export class PDFJSHighlightManager {
186
186
return null ;
187
187
}
188
188
189
- const viewport = pageView . viewport ;
190
189
const pageElement = pageView . div ;
191
-
192
190
if ( ! pageElement ) {
193
191
console . error ( "Page element not found" ) ;
194
192
return null ;
195
193
}
196
194
197
- const pageRect = pageElement . getBoundingClientRect ( ) ;
195
+ // Find the text layer within the page
196
+ const textLayer = pageElement . querySelector ( ".textLayer" ) ;
197
+ if ( ! textLayer ) {
198
+ console . error (
199
+ "Text layer not found for page:" ,
200
+ selection . pageNumber ,
201
+ ) ;
202
+ return null ;
203
+ }
204
+
205
+ const textLayerRect = textLayer . getBoundingClientRect ( ) ;
206
+ const currentScale = this . pdfViewer . currentScale || 1 ;
198
207
199
- // Calculate bounds from selection rectangles relative to page
208
+ console . log ( "🔍 Text layer rect:" , textLayerRect ) ;
209
+ console . log ( "🔍 Current scale:" , currentScale ) ;
210
+
211
+ // Calculate bounds from selection rectangles relative to text layer
200
212
let minLeft = Infinity ;
201
213
let maxRight = - Infinity ;
202
214
let minTop = Infinity ;
203
215
let maxBottom = - Infinity ;
204
216
205
217
for ( const rect of selection . rects ) {
206
- const relativeLeft = rect . left - pageRect . left ;
207
- const relativeTop = rect . top - pageRect . top ;
208
- const relativeRight = rect . right - pageRect . left ;
209
- const relativeBottom = rect . bottom - pageRect . top ;
218
+ console . log ( "🔍 Selection rect:" , rect ) ;
219
+
220
+ // Calculate position relative to text layer
221
+ const relativeLeft = rect . left - textLayerRect . left ;
222
+ const relativeTop = rect . top - textLayerRect . top ;
223
+ const relativeRight = rect . right - textLayerRect . left ;
224
+ const relativeBottom = rect . bottom - textLayerRect . top ;
210
225
211
226
minLeft = Math . min ( minLeft , relativeLeft ) ;
212
227
maxRight = Math . max ( maxRight , relativeRight ) ;
213
228
minTop = Math . min ( minTop , relativeTop ) ;
214
229
maxBottom = Math . max ( maxBottom , relativeBottom ) ;
215
230
}
216
231
217
- return {
232
+ const coordinates = {
218
233
x : minLeft ,
219
234
y : minTop ,
220
235
width : maxRight - minLeft ,
221
236
height : maxBottom - minTop ,
222
237
pageRect : {
223
- width : pageRect . width ,
224
- height : pageRect . height ,
238
+ width : textLayerRect . width ,
239
+ height : textLayerRect . height ,
225
240
} ,
241
+ // Store coordinates are relative to text layer at current scale
242
+ coordinateScale : currentScale ,
243
+ coordinateSystem : "textLayer" , // Mark that these coordinates are relative to text layer
226
244
} ;
245
+
246
+ console . log ( "🔍 Calculated coordinates:" , coordinates ) ;
247
+ return coordinates ;
227
248
} catch ( error ) {
228
249
console . error ( "Failed to convert selection to coordinates:" , error ) ;
229
250
return null ;
230
251
}
231
252
}
232
253
233
254
/**
234
- * Render highlight on the page using DOM overlay with scale-aware positioning
255
+ * Render highlight on the page using text layer positioning
235
256
*/
236
257
private renderHighlight ( highlightData : any ) : void {
237
258
try {
@@ -245,8 +266,15 @@ export class PDFJSHighlightManager {
245
266
246
267
const pageElement = pageView . div ;
247
268
248
- // Create or get highlight layer
249
- let highlightLayer = pageElement . querySelector (
269
+ // Find the text layer within the page
270
+ const textLayer = pageElement . querySelector ( ".textLayer" ) ;
271
+ if ( ! textLayer ) {
272
+ console . error ( "Text layer not found for rendering highlight" ) ;
273
+ return ;
274
+ }
275
+
276
+ // Create or get highlight layer within the text layer
277
+ let highlightLayer = textLayer . querySelector (
250
278
".pdfjs-highlight-layer" ,
251
279
) ;
252
280
if ( ! highlightLayer ) {
@@ -261,7 +289,7 @@ export class PDFJSHighlightManager {
261
289
pointer-events: none;
262
290
z-index: 1;
263
291
` ;
264
- pageElement . appendChild ( highlightLayer ) ;
292
+ textLayer . appendChild ( highlightLayer ) ;
265
293
}
266
294
267
295
// Create highlight element
@@ -272,40 +300,56 @@ export class PDFJSHighlightManager {
272
300
highlightData . id ,
273
301
) ;
274
302
275
- // Get current scale and calculate scaled coordinates
276
- const currentScale = this . pdfViewer . currentScale || 1 ;
277
- const creationScale = highlightData . creationScale || 1 ;
278
303
const coords = highlightData . coordinates ;
304
+ const currentScale = this . pdfViewer . currentScale || 1 ;
279
305
280
- // Scale the coordinates: (original coordinates / creation scale) * current scale
281
- const scaleRatio = currentScale / creationScale ;
282
- const scaledCoords = {
283
- x : coords . x * scaleRatio ,
284
- y : coords . y * scaleRatio ,
285
- width : coords . width * scaleRatio ,
286
- height : coords . height * scaleRatio ,
306
+ // For text layer coordinates, we don't need to apply additional scaling
307
+ // since the text layer itself scales with PDF.js
308
+ let finalCoords = {
309
+ x : coords . x ,
310
+ y : coords . y ,
311
+ width : coords . width ,
312
+ height : coords . height ,
287
313
} ;
288
314
315
+ // Only apply scaling if coordinates were stored with a different coordinate system
316
+ if ( coords . coordinateSystem !== "textLayer" ) {
317
+ // Legacy coordinates or coordinates from page-relative system
318
+ const coordinateScale =
319
+ coords . coordinateScale ||
320
+ highlightData . coordinateScale ||
321
+ 1 ;
322
+ const scaleRatio = currentScale / coordinateScale ;
323
+ finalCoords = {
324
+ x : coords . x * scaleRatio ,
325
+ y : coords . y * scaleRatio ,
326
+ width : coords . width * scaleRatio ,
327
+ height : coords . height * scaleRatio ,
328
+ } ;
329
+ }
330
+
331
+ console . log ( "🎨 Rendering highlight with coords:" , finalCoords ) ;
332
+
289
333
highlightElement . style . cssText = `
290
334
position: absolute;
291
- left: ${ scaledCoords . x } px;
292
- top: ${ scaledCoords . y } px;
293
- width: ${ scaledCoords . width } px;
294
- height: ${ scaledCoords . height } px;
335
+ left: ${ finalCoords . x } px;
336
+ top: ${ finalCoords . y } px;
337
+ width: ${ finalCoords . width } px;
338
+ height: ${ finalCoords . height } px;
295
339
background-color: ${ highlightData . color } ;
296
- opacity: 0.3 ;
340
+ opacity: 0.8 ;
297
341
pointer-events: auto;
298
342
border-radius: 2px;
299
343
transition: opacity 0.15s ease;
300
344
` ;
301
345
302
346
// Add hover effect
303
347
highlightElement . addEventListener ( "mouseenter" , ( ) => {
304
- highlightElement . style . opacity = "0.5 " ;
348
+ highlightElement . style . opacity = "1 " ;
305
349
} ) ;
306
350
307
351
highlightElement . addEventListener ( "mouseleave" , ( ) => {
308
- highlightElement . style . opacity = "0.3 " ;
352
+ highlightElement . style . opacity = "0.8 " ;
309
353
} ) ;
310
354
311
355
// Add click handler for highlight interaction
@@ -381,9 +425,13 @@ export class PDFJSHighlightManager {
381
425
y : highlightData . coordinates . y ,
382
426
width : highlightData . coordinates . width ,
383
427
height : highlightData . coordinates . height ,
428
+ coordinateScale : highlightData . coordinates . coordinateScale ,
429
+ coordinateSystem :
430
+ highlightData . coordinates . coordinateSystem ||
431
+ "textLayer" ,
384
432
} ,
385
433
color : highlightData . color ,
386
- opacity : 0.3 ,
434
+ opacity : 0.8 ,
387
435
content : highlightData . text ,
388
436
storage : "pdfjs" as const ,
389
437
createdAt : new Date ( ) . toISOString ( ) ,
@@ -404,10 +452,17 @@ export class PDFJSHighlightManager {
404
452
return {
405
453
id : apiAnnotation . id ,
406
454
color : apiAnnotation . color ,
407
- coordinates : apiAnnotation . coordinates ,
455
+ coordinates : {
456
+ ...apiAnnotation . coordinates ,
457
+ // For legacy data without coordinateSystem, assume page-based coordinates
458
+ coordinateSystem :
459
+ apiAnnotation . coordinates ?. coordinateSystem || "page" ,
460
+ coordinateScale :
461
+ apiAnnotation . coordinates ?. coordinateScale || 1 ,
462
+ } ,
408
463
pageNumber : apiAnnotation . page ,
409
464
text : apiAnnotation . content || "" ,
410
- creationScale : 1 , // Assume existing highlights were created at 1x scale
465
+ coordinateScale : apiAnnotation . coordinates ?. coordinateScale || 1 ,
411
466
} ;
412
467
}
413
468
0 commit comments