tag examples code attribute javascript svg svg.js

javascript - examples - title html css



Crear svg arcos entre dos puntos (2)

Aquí hay una solución que usa arcos, como se solicita, en lugar de curvas cuadráticas.

// 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 }

Quiero conectar dos puntos SVG (por ejemplo, los centros de dos círculos) usando arcos. Si solo hay una conexión, la línea ( <path> ) será recta. Si hay dos conexiones, ambas serán redondeadas y serán simétricas, de esta manera:

Entonces, de hecho, hay pocas reglas:

  1. Todo debe ser simétrico a la línea imaginaria que conecta los dos puntos.
  2. Desde 1, es obvio que si el número de conexiones es:

    • extraño: no mostramos la línea recta
    • incluso: mostramos la línea recta
  3. Debe haber un valor k que defina la distancia entre dos conexiones entre los mismos puntos.

  4. La tangente que pasa por el medio del arco elíptico debe ser paralela a la línea recta que conecta los dos puntos. Y obviamente, el centro de la línea será perpendicular a la tangente.

Estoy luchando por obtener una fórmula para calcular los parámetros A en el elemento <path> .

Lo que hice hasta ahora es:

<path d="M100 100, A50,20 0 1,0 300,100" stroke="black" fill="transparent"/>

  • M100 100 es claro: ese es el punto de partida ( pasar a 100,100 )
  • Los dos últimos números también son claros. El camino termina en 300,100
  • También vi que si pongo 0 lugar de 20 , obtengo una línea recta.
  • Si reemplazo 1,0 por 1,1 , la ruta se voltea.

Lo que no sé es cómo calcular los parámetros A. Leo los documentos , pero el imaginar todavía no está claro para mí. ¿Cómo calcular estos valores?

svg { width: 100%; height: 100%; position: absolute; }

<!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>

Estoy usando SVG.js para crear las rutas.


Te estás haciendo la vida muy difícil al requerir arcos circulares.

Si utiliza curvas cuadráticas en su lugar, la geometría se vuelve muy simple: simplemente desplace la coordenada X central a la mitad de la diferencia en las coordenadas Y, y viceversa.

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();

<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.3.2/svg.min.js"></script> <div id="drawing"></div>