我的情况是HTML文档中有多个SVG元素。元素是使用HTML规则,盒子模型,flexbox布局的,现在我告诉网格将很快开始使用。这个jsfiddle是一个例子,显示了一对填充的抛物线,使用二次路径操作绘制了公共端点和稍微不同的控制点。其他情况可能是各种厚度的简单水平或对角线。
在小提琴的第一个SVG中,两个端点在同一个SVG块中,并且尺寸(以SVG为单位)是众所周知的,并且绘制抛物线很简单。 (控制点也在这里显示)
然而,接下来的两个SVG证明了这个问题。端点位于单独的SVG中,由未知数量的“东西”分隔,此处由一些文本表示。很明显,javascript将需要重写端点和控制点的坐标,以便抛物线(或其他)可以连接两者。
如何获得第二个SVG中端点相对于第三个SVG坐标系的SVG单位坐标,以便将抛物线连接到其左端点?
可以做出一个可能简化的假设:SVG单位到像素的坐标比率对于任何绘图都是一致的,尽管为了增加复杂性,比率可能会不时变化(触发需要重新计算和重新绘制交叉 - SVG项目。)
一个可能复杂的问题是大多数端点将嵌套在两层嵌套的SVG元素中:外部SVG的SVG单元与CSS像素的大小相同,但内部SVG将具有这个不同的单元大小可能会不时变化。
可以根据需要向解决方案添加ID或CLASS。
/**CSS*/
svg { overflow: visible; }
<!--HTML -->
<svg width="12cm" height="6cm" viewBox="0 0 1200 600"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<title>Example quad01 - quadratic Bézier commands in path data</title>
<desc>Picture showing a "Q" a "T" command,
along with annotations showing the control points
and end points</desc>
<rect x="1" y="1" width="1198" height="598"
fill="none" stroke="blue" stroke-width="1" />
<path d="M500,300 Q300,50 100,300 Q300,75 500,300"
fill="green" stroke="green" stroke-width="1" />
<!-- End points -->
<g fill="black" >
<circle cx="100" cy="300" r="3"/>
<circle cx="500" cy="300" r="3"/>
</g>
<!-- Control points and lines from end points to control points -->
<g fill="#888888" >
<circle cx="300" cy="50" r="3"/>
<circle cx="300" cy="75" r="3"/>
</g>
<path d="M100,300 L300,50 L500,300
L300,75 L100,300"
fill="none" stroke="#888888" stroke-width="1" />
</svg>
<br>
<svg width="2cm" height="6cm" viewBox="0 0 200 600"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<title>Example quad01 - quadratic Bézier commands in path data</title>
<desc>SVG left endpoint</desc>
<rect x="1" y="1" width="198" height="598"
fill="none" stroke="blue" stroke-width="1" />
<!-- End points -->
<g fill="black" >
<circle cx="100" cy="300" r="3"/>
</g>
</svg>
some stuff here
<svg width="2cm" height="6cm" viewBox="0 0 200 600"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<title>Example quad01 - quadratic Bézier commands in path data</title>
<desc>SVG right endpoint</desc>
<rect x="1" y="1" width="198" height="598"
fill="none" stroke="blue" stroke-width="1" />
<path d="M100,300 Q-100,50 -300,300 Q-100,75 100,300"
fill="green" stroke="green" stroke-width="1" />
<!-- End points -->
<g fill="black" >
<circle cx="100" cy="300" r="3"/>
</g>
</svg>
(一般来说,坐标不会有相同的Y位置,这个例子很简单:但我只需要一种确定端点在适当坐标系中的位置的方法。)
答案 0 :(得分:0)
这对我来说很难弄明白,但是一位同事帮助了我们,我们终于对此感到困惑。解决方案结果相当简单。
我们困惑的方式,似乎有一个坐标转换矩阵,可用于从SVG用户坐标转换为浏览器像素......并通过其逆转回SVG用户坐标。这是通过以下方式为每个起始和结束元素获得的:
start = document.getElementById('startSVGElement');
spt = start.createSVGPoint();
sCTM = start.getScreenCTM();
end = document.getElementById('endSVGElement');
ept = end.createSVGPoint();
eCTM = end.getScreenCTM();
然后,要从起始元素中的点(100,400)绘制到结束元素中的点(50,60),请填写以下点:
spt.x = 100;
spt.y = 400;
ept.x = 50;
ept.y = 60;
现在转换魔术:根据CTM将结束点从SVG空间转换为浏览器像素空间,然后使用起始元素CTM逆转换回SVG空间:
ept_in_start = ept.matrixTransform( eCTM ).matrixTransform( sCTM.inverse())
现在spt和ept_in_start具有相对于同一元素(起始元素)和相同坐标系(起始元素的SVG空间)的坐标,您可以使用这些坐标绘制任何您想要的东西,基于坐标。
当然,如果页面重排,则必须重新计算并重绘。并且您必须确保为每个端点的(x,y)坐标获得正确的CTM ...如果您有嵌套的SVG和转换,则有许多重叠的坐标系。