download original
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>KevLinDev - Tutorials - SVG - Transformations</title>
<link href="../../../../common/kevlindev.css" type="text/css" rel="stylesheet" />
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
</head>
<script type="text/ecmascript"><![CDATA[
var svgns = "http://www.w3.org/2000/svg";
function init(e) {
if ( window.svgDocument == null )
svgDocument = e.target.ownerDocument;
}
/*****
*
* getTransformToElement
*
* This function is a part of the SVG DOM, but currently it is not
* implemented in the Adobe SVG Viewer. This code recreates that
* functionality
*
*****/
function getTransformToElement(node) {
// Initialize our CTM the node's Current Transformation Matrix
var CTM = node.getCTM();
// Work our way through the ancestor nodes stopping at the
// SVG Document
while ( ( node = node.parentNode ) != svgDocument ) {
// Multiply the new CTM to the one with what we've
// accumulated so far
CTM = node.getCTM().multiply(CTM);
}
return CTM;
}
/*****
*
* findUserCoord
*
*****/
function findUserCoord(evt) {
// Get the target
var target = evt.target;
// Get the outermost SVG element
var SVGRoot = svgDocument.rootElement;
// Get a CTM that accumulates all transforms leading up
// to the node that fired this event
var CTM = getTransformToElement(target);
// Find the inverse of that transform so that we can map
// mouse coordinates back to the node's coordinate space
var iCTM = CTM.inverse();
// The SVG pan and zoom values are not included in the
// accumulated CTM that we calculated earlier. These
// value must be handled separately
var trans = SVGRoot.currentTranslate;
var scale = SVGRoot.currentScale;
// Create a couple of points to work with
var p1 = SVGRoot.createSVGPoint();
var p2;
// Remove the current pan and zoom from the mouse coordinate
p1.x = ( evt.clientX - trans.x ) / scale;
p1.y = ( evt.clientY - trans.y ) / scale;
// Map this coordinate into the node's coordinate space
p2 = p1.matrixTransform(iCTM);
// Show the results
var tspans = target.parentNode.getElementsByTagNameNS(svgns, "tspan");
tspans.item(1).firstChild.data = evt.clientX;
tspans.item(3).firstChild.data = evt.clientY;
tspans.item(5).firstChild.data = p2.x;
tspans.item(7).firstChild.data = p2.y;
}
]]></script>
<body>
<div id="logo"></div>
<p id="path"><a href="../../../../index.htm">Home</a> :: <a href="../../../index.htm">Tutorials</a> :: <a href="../../index.htm">SVG</a> :: Transformations</p>
<div id="simple-content">
<p>This example shows how you can accumulate all transformations that lead to the final rendering of an element. Using the inverse of this transformation and by taking the current zoom and pan into account, you can convert the current mouse position to a coordinate within the element's coordinate space.</p>
<p>The image below shows the same rectangle with various transformations applied to it. The untransformed rectangle is defined with the following SVG:</p>
<pre><rect x="-2" y="0" width="10" height="10"/>
</pre>
<p>Based on this rectangle's definition, the x user coordinates should range from [-2, 8] and the y user coordinates should range from [0,10].</p>
<p>Try different zoom levels and panning. The mouse coordinates will reflect the current zoom and pan settings, but the user coordinates should remain within the intervals listed above. I have noticed slight errors with the rotated and skewed versions of the rectangle. I welcome any suggestions on how I can improve the accuracy of these calculations.</p>
<p>A future version of this example will take the viewBox into account.</p>
<hr />
</div>
<div align="center">
Hello World!!!
<embed width="402" height="402" src="transformCursor.svg" type="image/svg+xml" />
</div>
<div id="footer">
<p class="copyright">Copyright 2000-2003, Kevin Lindsey</p>
</div>
</body>
</html>
back to svg
(C) 1998-2017 Olaf Klischat <olaf.klischat@gmail.com>