我花了一些时间,但最终解决了数学问题。这个解决方案需要三个步骤:
- 在你的页面中包含this script(以及SVGPan.js脚本),例如:
<script xlink:href="SVGPanUnscale.js"></script>
- 确定你不想缩放的项目(例如将它们放在一个特殊类或ID的组中,或者在每个元素上放置一个特定的类),然后告诉脚本如何找到这些项目,例如:
unscaleEach("g.non-scaling > *, circle.non-scaling");
- 使用
transform="translate(…,…)"
来放置图表上的每个元素,而不是cx="…" cy="…"
。
只需完成这些步骤,使用SVGPan进行缩放和平移将不会影响标记元素的比例(或旋转、倾斜)。
库
function unscaleEach(selector){
if (!selector) selector = "g.non-scaling > *";
window.addEventListener('mousewheel', unzoom, false);
window.addEventListener('DOMMouseScroll', unzoom, false);
function unzoom(evt){
var r = getRoot(evt.target.ownerDocument);
[].forEach.call(r.querySelectorAll(selector), unscale);
}
}
function unscale(el){
var svg = el.ownerSVGElement;
var xf = el.scaleIndependentXForm;
if (!xf){
xf = el.scaleIndependentXForm = svg.createSVGTransform();
el.transform.baseVal.appendItem(xf);
}
var m = svg.getTransformToElement(el.parentNode);
m.e = m.f = 0;
xf.setMatrix(m);
}
演示代码
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Scale-Independent Elements</title>
<style>
polyline { fill:none; stroke:#000; vector-effect:non-scaling-stroke; }
circle, polygon { fill:#ff9; stroke:#f00; opacity:0.5 }
</style>
<g id="viewport" transform="translate(500,300)">
<polyline points="-100,-50 50,75 100,50" />
<g class="non-scaling">
<circle transform="translate(-100,-50)" r="10" />
<polygon transform="translate(100,50)" points="0,-10 10,0 0,10 -10,0" />
</g>
<circle class="non-scaling" transform="translate(50,75)" r="10" />
</g>
<script xlink:href="SVGPan.js"></script>
<script xlink:href="SVGPanUnscale.js"></script>
<script>
unscaleEach("g.non-scaling > *, circle.non-scaling");
</script>
</svg>
s
倍,则可以将圆形按比例缩放1/s
倍。 - Felix Kling