skip overlapping labels using greedy placement algorithm
Labels are placed in DOM order, skipping any that would overlap with already-placed labels. Uses AABB intersection test.
This commit is contained in:
@@ -202,7 +202,7 @@ export async function showAriaRefLabels({ page, interactiveOnly = true }: {
|
||||
// Using 'any' types here since this code runs in browser context
|
||||
const labelCount = await page.evaluate(
|
||||
({ refs, containerId, containerStyles, labelStyles }: {
|
||||
refs: Array<{ ref: string; element: { getBoundingClientRect(): { width: number; height: number; left: number; top: number } } }>
|
||||
refs: Array<{ ref: string; element: { getBoundingClientRect(): { width: number; height: number; left: number; top: number; right: number; bottom: number } } }>
|
||||
containerId: string
|
||||
containerStyles: string
|
||||
labelStyles: string
|
||||
@@ -223,6 +223,22 @@ export async function showAriaRefLabels({ page, interactiveOnly = true }: {
|
||||
style.textContent = labelStyles
|
||||
container.appendChild(style)
|
||||
|
||||
// Track placed label rectangles for overlap detection
|
||||
// Each rect is { left, top, right, bottom } in viewport coordinates
|
||||
const placedLabels: Array<{ left: number; top: number; right: number; bottom: number }> = []
|
||||
|
||||
// Estimate label dimensions (11px font + padding)
|
||||
const LABEL_HEIGHT = 16
|
||||
const LABEL_CHAR_WIDTH = 7 // approximate width per character
|
||||
|
||||
// Check if two rectangles overlap
|
||||
const rectsOverlap = (
|
||||
a: { left: number; top: number; right: number; bottom: number },
|
||||
b: { left: number; top: number; right: number; bottom: number }
|
||||
) => {
|
||||
return a.left < b.right && a.right > b.left && a.top < b.bottom && a.bottom > b.top
|
||||
}
|
||||
|
||||
// Create label for each interactive element
|
||||
let count = 0
|
||||
for (const { ref, element } of refs) {
|
||||
@@ -233,16 +249,34 @@ export async function showAriaRefLabels({ page, interactiveOnly = true }: {
|
||||
continue
|
||||
}
|
||||
|
||||
// Calculate label position and dimensions
|
||||
const labelWidth = ref.length * LABEL_CHAR_WIDTH + 8 // +8 for padding
|
||||
const labelLeft = rect.left
|
||||
const labelTop = Math.max(0, rect.top - LABEL_HEIGHT)
|
||||
const labelRect = {
|
||||
left: labelLeft,
|
||||
top: labelTop,
|
||||
right: labelLeft + labelWidth,
|
||||
bottom: labelTop + LABEL_HEIGHT,
|
||||
}
|
||||
|
||||
// Skip if this label would overlap with any already-placed label
|
||||
const overlaps = placedLabels.some((placed) => rectsOverlap(labelRect, placed))
|
||||
if (overlaps) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Place the label
|
||||
const label = doc.createElement('div')
|
||||
label.className = '__pw_label__'
|
||||
label.textContent = ref
|
||||
|
||||
// Position above element, accounting for scroll
|
||||
// Use scrollX/scrollY so labels scroll with the page
|
||||
label.style.left = `${win.scrollX + rect.left}px`
|
||||
label.style.top = `${win.scrollY + Math.max(0, rect.top - 16)}px`
|
||||
label.style.left = `${win.scrollX + labelLeft}px`
|
||||
label.style.top = `${win.scrollY + labelTop}px`
|
||||
|
||||
container.appendChild(label)
|
||||
placedLabels.push(labelRect)
|
||||
count++
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 237 KiB |
@@ -31,7 +31,7 @@
|
||||
- generic [ref=e55]:
|
||||
- text: "Google offered in:"
|
||||
- link [ref=e56] [cursor=pointer]:
|
||||
- /url: https://www.google.com/setprefs?sig=0_WWAwchirMrWB5pgMRu-Ccbzsvw0%3D&hl=it&source=homepage&sa=X&ved=0ahUKEwiz58mLyO-RAxVON94AHXxmKlkQ2ZgBCBU
|
||||
- /url: https://www.google.com/setprefs?sig=0_uKW2_iLdDvITPr98P8jjLIgrMiY%3D&hl=it&source=homepage&sa=X&ved=0ahUKEwjeh4Llye-RAxVrJNAFHaspBugQ2ZgBCBU
|
||||
- text: Italiano
|
||||
- contentinfo [ref=e58]:
|
||||
- generic [ref=e59]: Italy
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 189 KiB |
Reference in New Issue
Block a user