Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>It took me a while, but I finally got the math clean. This solution requires three things:</p> <ol> <li>Include <a href="http://phrogz.net/svg/libraries/SVGPanUnscale.js" rel="noreferrer">this script</a> in your page (along with the SVGPan.js script), e.g.<br> <code>&lt;script xlink:href="SVGPanUnscale.js"&gt;&lt;/script&gt;</code></li> <li>Identify the items you want not to scale (e.g. place them in a group with a special class or ID, or put a particular class on each element) and then tell the script how to find those items, e.g.<br> <code>unscaleEach("g.non-scaling &gt; *, circle.non-scaling");</code></li> <li><strong>Use <code>transform="translate(…,…)"</code> to place each element on the diagram, <em>not</em> <code>cx="…" cy="…"</code>.</strong></li> </ol> <p>With just those steps, zooming and panning using SVGPan will not affect the scale (or rotation, or skew) of marked elements.</p> <h2>Demo: <a href="http://phrogz.net/svg/scale-independent-elements.svg" rel="noreferrer">http://phrogz.net/svg/scale-independent-elements.svg</a></h2> <h2>Library</h2> <pre class="lang-js prettyprint-override"><code>// Copyright 2012 © Gavin Kistner, !@phrogz.net // License: http://phrogz.net/JS/_ReuseLicense.txt // Undo the scaling to selected elements inside an SVGPan viewport function unscaleEach(selector){ if (!selector) selector = "g.non-scaling &gt; *"; window.addEventListener('mousewheel', unzoom, false); window.addEventListener('DOMMouseScroll', unzoom, false); function unzoom(evt){ // getRoot is a global function exposed by SVGPan var r = getRoot(evt.target.ownerDocument); [].forEach.call(r.querySelectorAll(selector), unscale); } } // Counteract all transforms applied above an element. // Apply a translation to the element to have it remain at a local position function unscale(el){ var svg = el.ownerSVGElement; var xf = el.scaleIndependentXForm; if (!xf){ // Keep a single transform matrix in the stack for fighting transformations // Be sure to apply this transform after existing transforms (translate) xf = el.scaleIndependentXForm = svg.createSVGTransform(); el.transform.baseVal.appendItem(xf); } var m = svg.getTransformToElement(el.parentNode); m.e = m.f = 0; // Ignore (preserve) any translations done up to this point xf.setMatrix(m); } </code></pre> <h2>Demo Code</h2> <pre class="lang-svg prettyprint-override"><code>&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"&gt; &lt;title&gt;Scale-Independent Elements&lt;/title&gt; &lt;style&gt; polyline { fill:none; stroke:#000; vector-effect:non-scaling-stroke; } circle, polygon { fill:#ff9; stroke:#f00; opacity:0.5 } &lt;/style&gt; &lt;g id="viewport" transform="translate(500,300)"&gt; &lt;polyline points="-100,-50 50,75 100,50" /&gt; &lt;g class="non-scaling"&gt; &lt;circle transform="translate(-100,-50)" r="10" /&gt; &lt;polygon transform="translate(100,50)" points="0,-10 10,0 0,10 -10,0" /&gt; &lt;/g&gt; &lt;circle class="non-scaling" transform="translate(50,75)" r="10" /&gt; &lt;/g&gt; &lt;script xlink:href="SVGPan.js"&gt;&lt;/script&gt; &lt;script xlink:href="SVGPanUnscale.js"&gt;&lt;/script&gt; &lt;script&gt; unscaleEach("g.non-scaling &gt; *, circle.non-scaling"); &lt;/script&gt; &lt;/svg&gt; </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload