www org mclibre coordenadas consultar apuntes svg d3.js

svg - org - coordenadas en python



¿Cómo obtener las coordenadas absolutas del objeto dentro de un grupo<g>? (5)

Buena demostración aquí: https://codepen.io/netsi1964/pen/pWjwgP

point = point.matrixTransform(svg.getScreenCTM().inverse())

Esto puede ser una pregunta frecuente, así que no dude en señalarme otra respuesta. El tema es difícil de buscar.

Si quiero usar d3.js para obtener un atributo que se declara explícitamente en un objeto SVG, o si lo puse explícitamente usando D3, puedo obtener fácilmente el valor del atributo usando d3.select . Por ejemplo, esto imprime 300:

... <circle id="mycircle" r="10" cx="100" cy="200"> ... d3.select("#mycircle").attr("cx", 300); console.log(d3.select("#mycircle").attr("cx"));

¿Qué sucede si no establezco explícitamente el valor del atributo, pero se "establece" implícitamente en un grupo <g> ? O: ¿Cómo puedo usar el código para averiguar dónde se centra un grupo <g> ? Me gustaría alguna forma de determinar dónde están las cosas dentro del sistema <g> coordenadas absolutas del objeto <svg> . Si supiera dónde estaba <g> , cómo se orienta en el espacio, etc., podría averiguar dónde están los puntos dentro de él. ¿Cómo puedo hacer eso?

BigBadaboom comenta en un comentario sobre una respuesta a esta pregunta que lo que se hereda no es un par de coordenadas, sino un atributo de transform . Así que puedo seleccionar un <g> y obtener el valor del atributo de transformación:

console.log(d3.select("#mygroup").attr("transform"));

que imprime, por ejemplo:

"rotar (-125.93) traducir (0, -25)"

¿Debo analizar eso para averiguar dónde se encuentra <g> en el sistema de coordenadas absolutas?


D3 tiene una función incorporada para analizar transformaciones svg: d3.transform

Podría usarlo para obtener la matriz de traducción ([x, y]) de la transformación, es decir:

var transformText = d3.select("#mygroup").attr("transform"); var translate = d3.transform(transformText).translate; //returns [0,-25]


La excelente respuesta de @ Jshanley en realidad se implementa muy fácilmente en JavaScript sin formato (o en cualquier marco) utilizando la transformación de matriz de SVGPoint.

/** * Get a new XY point in SVG-Space, where X and Y are relative to an existing element. Useful for drawing lines between elements, for example * X : the new X with relation to element, 5 would be ''5'' to the right of element''s left boundary. element.width would be the right edge. * Y : the new Y coordinate, same principle applies * svg: the parent SVG DOM element * element: the SVG element which we are using as a base point. */ function getRelativeXY(x, y, svg, element){ var p = svg.createSVGPoint(); var ctm = element.getCTM(); p.x = x; p.y = y; return p.matrixTransform(ctm); }

Ver también: coordenadas del rectángulo después de la transformación.

Para encontrar los bordes de tu círculo, por ejemplo:

var leftTangent = getRelativeXY(circle.cx-circle.r, circle.y, svg, circle); var rightTangent = getRelativeXY(circle.cx+circle.r, circle.y, svg, circle); var topTangent= getRelativeXY(circle.cx, circle.y-circle.r, svg, circle); var bottomTangent= getRelativeXY(circle.cx, circle.y+ circle.r, svg, circle); var deadCenter= getRelativeXY(circle.cx, circle.y, svg, circle);

Es cierto que no es tan interesante con un círculo liso, pero una vez que el círculo se ha desplazado o estirado, es una gran herramienta para obtener las coordenadas.

Especificaciones de W3

El tutorial más fácil de entender de Microsoft.


Otros aquí ya han mencionado SVGLocatable.getBBox() que es útil para agarrar el cuadro delimitador de un elemento en términos de su propio sistema de coordenadas local. Desafortunadamente, como ha notado, esto no tiene en cuenta ninguna de las transformaciones realizadas en el elemento o en sus elementos principales.

Hay un par de otras funciones disponibles que le ayudarán mucho en el manejo de esas transformaciones.

SVGLocatable.getScreenCTM() le brinda un SVGMatrix representa las transformaciones necesarias para convertir las coordenadas de la ventana SVGMatrix a las coordenadas locales de su elemento. Esto es genial porque tomará en cuenta las transformaciones aplicadas al elemento al que se llama, y ​​cualquier transformación aplicada a los elementos principales. Desafortunadamente, también tiene en cuenta dónde está exactamente el elemento en la pantalla, lo que significa que si tiene contenido antes de su documento svg, o incluso solo algunos márgenes a su alrededor, la matriz devuelta incluirá ese espacio como traducción.

Element.getBoundingClientRect() te permitirá tener en cuenta ese espacio. Si llama a esta función en el propio documento SVG, puede averiguar cuánto está compensado el SVG en la pantalla.

Luego, todo lo que tiene que hacer es combinar los dos cuando desee convertir entre sistemas de coordenadas. HERE hay una buena información sobre cómo funciona un SVGMatrix . Lo importante que debemos saber por ahora es que un SVGMatrix es un objeto con seis propiedades a , b , c , d , e , y que representan una transformación de la siguiente manera:

Digamos que tiene una variable svgDoc que es una referencia al documento svg ( no una selección d3, sino el elemento en sí ). Luego, puede crear una función que se convertirá al sistema de coordenadas de un elemento svg elem siguiente manera.

function convertCoords(x,y) { var offset = svgDoc.getBoundingClientRect(); var matrix = elem.getScreenCTM(); return { x: (matrix.a * x) + (matrix.c * y) + matrix.e - offset.left, y: (matrix.b * x) + (matrix.d * y) + matrix.f - offset.top }; }

Luego, digamos que querías poner un punto en medio de elem , podrías hacer algo como esto:

var bbox = elem.getBBox(), middleX = bbox.x + (bbox.width / 2), middleY = bbox.y + (bbox.height / 2); var absoluteCoords = convertCoords(middleX, middleY); var dot = svg.append(''circle'') .attr(''cx'', absoluteCoords.x) .attr(''cy'', absoluteCoords.y) .attr(''r'', 5);

Por supuesto, probablemente querrá generalizar la función convertCoords para que pueda pasar el elemento objetivo, pero con suerte eso lo pondrá en la dirección correcta. ¡Buena suerte!

Una mejor implementación sería una fábrica que genere una función de conversión para cualquier elemento dado y contexto de documento svg:

function makeAbsoluteContext(element, svgDocument) { return function(x,y) { var offset = svgDocument.getBoundingClientRect(); var matrix = element.getScreenCTM(); return { x: (matrix.a * x) + (matrix.c * y) + matrix.e - offset.left, y: (matrix.b * x) + (matrix.d * y) + matrix.f - offset.top }; }; }

Esto podría usarse de la siguiente manera dado el mismo elem y svgDoc que el ejemplo ingenuo:

var bbox = elem.getBBox(), middleX = bbox.x + (bbox.width / 2), middleY = bbox.y + (bbox.height / 2); // generate a conversion function var convert = makeAbsoluteContext(elem, svgDoc); // use it to calculate the absolute center of the element var absoluteCenter = convert(middleX, middleY); var dot = svg.append(''circle'') .attr(''cx'', absoluteCenter.x) .attr(''cy'', absoluteCenter.y) .attr(''r'', 5);


Para obtener los límites de un elemento SVG, tiene dos opciones:

  1. getBBox() que funciona en todos los elementos SVG (gráficos). Obtiene el cuadro delimitador del elemento en el espacio de coordenadas local. Si el elemento tiene un atributo de transform , afectará al bbox, pero si el elemento principal tiene una transform , no se reflejará en el bbox devuelto.

    http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable

  2. getBoundingClientRect() que es una función de Elemento HTML, pero también funciona para elementos SVG. Devuelve los límites del elemento en el espacio de la pantalla (después de que se hayan aplicado todas las transformaciones).

    https://developer.mozilla.org/en-US/docs/Web/API/Element.getBoundingClientRect