v136 · miscellaneous

Coordinate Transform Lab

The key challenge with isPointInFill, isPointInStroke, and getCharNumAtPosition accepting DOMPointInit: you must convert screen (viewport) coordinates to element-local coordinates first. This lab shows the transform math and lets you click SVG shapes to see the live conversion using plain {x, y} object literals.

checking isPointInFill(DOMPointInit)… checking isPointInStroke(DOMPointInit)…
Before Chrome 136, isPointInFill({x, y}) accepted an SVGPoint created via svg.createSVGPoint(). Chrome 136 upgrades to DOMPointInit, so you can pass a plain object literal {x: 50, y: 80}. The coordinates must be in the element's local coordinate system (after CTM inversion).

Click to hit-test

Hello SVG
Click anywhere on the SVG to test hit detection.

Manual coordinate test

These are element-local coordinates (after group transform).

Hit-test results

Click on the SVG or use the manual test.

Coordinate conversion code (old vs new)

// OLD: createSVGPoint + matrix inverse function hitTestOld(svgEl, element, screenX, screenY) { const pt = svgEl.createSVGPoint(); pt.x = screenX; pt.y = screenY; const ctm = element.getScreenCTM(); const localPt = pt.matrixTransform(ctm.inverse()); return element.isPointInFill(localPt); // SVGPoint } // NEW (Chrome 136): DOMPointInit — plain object literal function hitTestNew(element, screenX, screenY) { const ctm = element.getScreenCTM(); const inv = ctm.inverse(); // Convert screen → local using DOMMatrix const dm = new DOMMatrix([inv.a, inv.b, inv.c, inv.d, inv.e, inv.f]); const local = dm.transformPoint({ x: screenX, y: screenY }); return element.isPointInFill({ x: local.x, y: local.y }); // DOMPointInit ✓ } // isPointInStroke and getCharNumAtPosition work the same way: element.isPointInStroke({ x: local.x, y: local.y }); textEl.getCharNumAtPosition({ x: local.x, y: local.y });