我想使用弧连接两个SVG点(例如两个圆的中心)。如果只有一个连接,则行(<path>
)将是直的。如果有两个连接,则两者都将被舍入并且将是对称的,这样:
所以,实际上,规则很少:
从1开始,如果连接数为:
,那很明显应该有一个值k
,用于定义相同点之间两个连接之间的距离。
穿过椭圆弧中间的切线应与连接两个点的直线平行。显然,线的中间将垂直于切线。
我很难得到一个公式来计算A
元素中的<path>
参数。
到目前为止,我所做的是:
<path d="M100 100, A50,20 0 1,0 300,100" stroke="black" fill="transparent"/>
M100 100
很明确:这是起点(移至100,100 )300,100
0
代替20
,我会获得一条直线。1,0
替换为1,1
,则会翻转路径。我不知道如何计算A参数。我读过the docs,但想象仍然不清楚。如何计算这些值?
svg {
width: 100%;
height: 100%;
position: absolute;
}
&#13;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<?xml version="1.0" standalone="no" ?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<!-- Connect A(100,100) with B(300, 100) -->
<path d="M100 100, A50,0 0 1,0 300,100" stroke="black" fill="transparent" />
<path d="M100 100, A50,20 0 1,0 300,100" stroke="black" fill="transparent" />
<path d="M100 100, A50,20 0 1,1 300,100" stroke="black" fill="transparent" />
<path d="M100 100, A50,30 0 1,0 300,100" stroke="black" fill="transparent" />
<path d="M100 100, A50,30 0 1,1 300,100" stroke="black" fill="transparent" />
<!-- A(100, 100) B(300, 400) -->
<path d="M100 100, A50,0 57 1,0 300,400" stroke="black" fill="transparent" />
<path d="M100 100, A50,20 57 1,0 300,400" stroke="black" fill="transparent" />
<path d="M100 100, A50,20 57 1,1 300,400" stroke="black" fill="transparent" />
</svg>
</body>
</html>
&#13;
我使用SVG.js创建路径。
答案 0 :(得分:17)
你需要圆弧,让自己的生活变得非常困难。
如果使用二次曲线,那么几何变得非常简单 - 只需将中心X坐标偏移Y坐标差异的一半,反之亦然。
function arc_links(dwg,x1,y1,x2,y2,n,k) {
var cx = (x1+x2)/2;
var cy = (y1+y2)/2;
var dx = (x2-x1)/2;
var dy = (y2-y1)/2;
var i;
for (i=0; i<n; i++) {
if (i==(n-1)/2) {
dwg.line(x1,y1,x2,y2).stroke({width:1}).fill('none');
}
else {
dd = Math.sqrt(dx*dx+dy*dy);
ex = cx + dy/dd * k * (i-(n-1)/2);
ey = cy - dx/dd * k * (i-(n-1)/2);
dwg.path("M"+x1+" "+y1+"Q"+ex+" "+ey+" "+x2+" "+y2).stroke({width:1}).fill('none');
}
}
}
function create_svg() {
var draw = SVG('drawing').size(300, 300);
arc_links(draw,50,50,250,50,2,40);
arc_links(draw,250,50,250,250,3,40);
arc_links(draw,250,250,50,250,4,40);
arc_links(draw,50,250,50,50,5,40);
draw.circle(50).move(25,25).fill('#fff').stroke({width:1});
draw.circle(50).move(225,25).fill('#fff').stroke({width:1});
draw.circle(50).move(225,225).fill('#fff').stroke({width:1});
draw.circle(50).move(25,225).fill('#fff').stroke({width:1});
}
create_svg();
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.3.2/svg.min.js"></script>
<div id="drawing"></div>
&#13;
答案 1 :(得分:3)
这是一个使用弧的解决方案,而不是二次曲线。
// Internal function
function connectInternal(x1,y1,x2,y2,con){
var dx=x2-x1
var dy=y2-y1
var dist=Math.sqrt(dx*dx+dy*dy)
if(dist==0 || con==0){
return "M"+x1+","+y1+"L"+x2+","+y2
}
var xRadius=dist*0.75
var yRadius=dist*0.3*(con*0.75)
var normdx=dx/dist
if(normdx<-1)normdx=-1
if(normdx>1)normdx=1
var angle=Math.acos(normdx)*180/Math.PI
if(x1>x2){
angle=-angle
}
return "M"+x1+","+y1+"A"+xRadius+","+yRadius+","+
angle+",00"+x2+","+y2+
"M"+x1+","+y1+"A"+xRadius+","+yRadius+","+
angle+",01"+x2+","+y2
}
// Returns an SVG path that represents
// "n" connections between two points.
function connect(x1,y1,x2,y2,n){
var ret=""
var con=n
if(con%2==1){
ret+=connectInternal(x1,y1,x2,y2,con)
con-=1
}
for(var i=2;i<=con;i+=2){
ret+=connectInternal(x1,y1,x2,y2,i)
}
return ret
}
答案 2 :(得分:2)
要绘制SVG路径的弧,您需要2个点和半径,有2个点,只需要计算给定距离的半径即可。
半径公式:
let r = (d, x) => 0.125*d*d/x + x/2;
其中:
d
-点之间的距离
x
-圆弧之间的距离
它源自勾股定理:
a
这是点之间距离的一半
let r = (d, x) => !x?1e10:0.125*d*d/x + x/2;
upd();
function upd() {
let n = +count.value;
let s = +step.value/10;
let x1 = c1.getAttribute('cx'), y1 = c1.getAttribute('cy');
let x2 = c2.getAttribute('cx'), y2 = c2.getAttribute('cy');
let dx = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
paths.innerHTML = [...Array(n)].map((_, i) => [
n%2&&i===n-1?0:1+parseInt(i/2),
i%2
]).map(i => `<path d="${[
'M', x1, y1,
'A', r(dx, s*i[0]), r(dx, s*i[0]), 0, 0, i[1], x2, y2
].join(' ')}"></path>`).join('');
}
<input id="count" type="range" min=1 max=9 value=5 oninput=upd() >
<input id="step" type="range" min=1 max=200 value=100 oninput=upd() >
<svg viewbox=0,0,300,100 stroke=red fill=none >
<circle id=c1 r=10 cx=50 cy=60></circle>
<circle id=c2 r=10 cx=250 cy=40></circle>
<g id=paths></g>
</svg>