- From: Gavin Kistner <phrogz@me.com>
- Date: Wed, 09 Nov 2011 17:18:59 +0000 (GMT)
- To: Gavin Kistner <phrogz@me.com>
- Cc: www-svg@w3.org
- Message-id: <9018756d-cba8-6f4a-fc3f-ffe1c175cc2f@me.com>
On Nov 07, 2011, at 09:03 PM, Gavin Kistner <phrogz@me.com> wrote: My question: is there a better way to accomplish my goal of getting SVG elements coordinated with embedded HTML elements? While writing a workaround for the Webkit bug[1] (transforming points from screen to foreignObject space) I realized that there's no point in round-tripping through screen space for compliant browsers. It's easier to just use foreignObject.getTransformToElement( otherSVGElement ). I now have a solution and test page[2] that works in Firefox and mostly works in Webkit (with the caveat that rotated/skewed foreignObjects don't give the right results, since getBoundingClientRect() gives the screen-space bounding box that no longer touches the corners of the objects). [1] https://bugs.webkit.org/show_bug.cgi?id=71819 [2] http://phrogz.net/SVG/html_location_in_svg_2.svg For archival posterity, here's my code (including Webkit workaround): // Find the four corners (nw/ne/sw/se) of any HTML element embedded in // an SVG document, transformed into the coordinates of an arbitrary SVG // element in the document. // // Usage: // var coords = svgCoordsForHTMLElement( htmlEl, svgEl ); // svgEl may be null to use the root SVG documentElement var svgCoordsForHTMLElement = (function(svg){ var svgNS= svg.namespaceURI, xhtmlNS = "http://www.w3.org/1999/xhtml"; var doc = svg.ownerDocument; var wrap = svg.appendChild(doc.createElementNS(svgNS,'foreignObject')); var body = wrap.appendChild(doc.createElementNS(xhtmlNS,'body')); if (typeof body.getBoundingClientRect != 'function') return; wrap.setAttribute('x',100); var rectIsInForeignObject = body.getBoundingClientRect().left == 0; svg.removeChild(wrap); var pt = svg.createSVGPoint(); return function svgCoordsForHTMLElement(htmlEl,svgEl){ if (!svgEl) svgEl = htmlEl.ownerDocument.documentElement; var coords = {}; for (var o=htmlEl;o&&o.tagName!='foreignObject';o=o.parentNode){} var transform = wrap.getTransformToElement(svgEl); if (!rectIsInForeignObject){ // Workaround https://bugs.webkit.org/show_bug.cgi?id=71819 transform = wrap.getScreenCTM().inverse().multiply(transform); } var rect = htmlEl.getBoundingClientRect(); pt.x = rect.left; pt.y = rect.top; coords.nw = pt.matrixTransform(transform); pt.y = rect.bottom; coords.sw = pt.matrixTransform(transform); pt.x = rect.right; coords.se = pt.matrixTransform(transform); pt.y = rect.top; coords.ne = pt.matrixTransform(transform); return coords; }; })(document.documentElement);
Received on Wednesday, 9 November 2011 17:20:27 UTC