我有一个XHTML页面,其中SVG作为<svg>
元素嵌入其中。我需要实现扩展,但是要求内部<text>
元素不能扩展。一个显而易见的解决方案是
<svg ...>
<!-- Root <g> to programmatically `setAttribute("transform", ...)` -->
<g transform="scale(0.5)">
<!-- Various inner elements here -->
<!-- Here is a text element.
Additional <g> is to apply text position which
*must* depend on the scaling factor set above -->
<g transform="translate(100 50)">
<!-- Apply the opposite scaling factor.
Must be done for every `<text>` element on each change of the scaling factor... -->
<text x="0" y="0" transform="scale(2)">Hello, World!</text>
</g>
</g>
</svg>
有没有比这更好的解决方案?也许,有一种方法可以“重置”内部<text>
元素上的结果缩放因子?该代码必须适用于Firefox和Chrome。
UPD 即可。还有一个选项可以将文本元素放在要缩放的元素之外,并手动控制文本元素的位置。它避免了由于缩放而出现在文本上的视觉故障。目前我使用这种方法。
答案 0 :(得分:5)
SVG Tiny 1.2中定义了transform="ref(svg)"
。据我所知,除Opera(Presto)之外的任何浏览器都没有实现。
<svg xmlns="http://www.w3.org/2000/svg" font-size="24" text-rendering="geometricPrecision">
<!-- Root <g> to programmatically `setAttribute("transform", ...)` -->
<text x="0" y="1em" stroke="gray" fill="none">Hello, World!</text>
<g transform="scale(0.5) rotate(25)">
<!-- Various inner elements here -->
<!-- Here is a text element.
Additional <g> is to apply text position which
*must* depend on the scaling factor set above -->
<g transform="translate(100 50)">
<!-- Apply the opposite scaling factor.
Must be done for every `<text>` element on each change of the scaling factor... -->
<text x="0" y="1em" transform="ref(svg)">Hello, World!</text>
</g>
</g>
</svg>
在上面的例子中,文本应出现在灰色轮廓所在的位置(在左上角)。不应对具有transform="ref(svg)"
的元素应用旋转或缩放,为了进行转换,它就好像它是根svg元素的直接子元素。
答案 1 :(得分:4)
如果可以接受(a)使用JavaScript并且(b)通过transform="translate(…,…)"
在元素本身或包装组中指定每个未缩放元素的位置(就像你所做的那样),那么你可以使用我的未标记代码:
http://phrogz.net/svg/libraries/SVGPanUnscale.js
正如您在演示中所看到的,它会撤消除转换(包括缩放,旋转和倾斜)之外的所有转换,同时保持元素位于它们应该位于的位置。
另请参阅此演示,该演示允许您使用SVGPan缩放和平移图形,同时保持某些标记元素不缩放:
http://phrogz.net/svg/scale-independent-elements.svg
以下是您需要的所有代码:
// Copyright 2012 © Gavin Kistner, !@phrogz.net
// License: http://phrogz.net/JS/_ReuseLicense.txt
// Removes 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);
}
以下是演示代码,以防JSFiddle关闭:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:x="http://www.w3.org/1999/xlink"
font-size="36">
<g transform="matrix(1 0 0 1 0 0)">
<g transform="translate(100 50)"><text x="0" y="1em">A!</text></g>
<g transform="translate(200 150)"><text x="0" y="1em">B!</text></g>
<g transform="translate(150 75)"><text x="0" y="1em">C!</text></g>
</g>
<script x:href="http://phrogz.net/svg/libraries/SVGPanUnscale.js"></script>
<script>
var root = document.querySelector('g'),
text = document.querySelectorAll('text'),
xf = root.transform.baseVal.getItem(0);
// Keep scaling, spinning, and sliding the outer graphic
// but "unscale" each text element afterwards.
setInterval(function(){
var m = xf.matrix.scale(0.99).translate(10,0).rotate(1);
xf.setMatrix(m);
[].forEach.call(text,unscale);
},100);
</script>
</svg>
答案 2 :(得分:1)
试试这个
<强> HTML 强>
<svg>
<g transform="scale(0.5)">
<g transform="translate(100 50)">
<text x="0" y="0">Hello, World!</text>
</g>
</g>
</svg>
找到逆矩阵并仅添加所需的转换。
var svg = document.getElementsByTagName('svg')[0];
var text = document.querySelectorAll('text')[0];
var matrix = svg.createSVGTransformFromMatrix(text.getCTM().inverse().translate(100,50));
text.transform.baseVal.initialize(matrix);
JsFiddle - http://jsfiddle.net/uPSc4/10/