Actualmente construyendo una aplicación SVG basada en navegador. Dentro de esta aplicación, el usuario puede diseñar y posicionar varias formas, incluidos los rectángulos.
Cuando aplico stroke-width
a un rect
elemento SVG de say 1px
, el trazo se aplica al rect
desplazamiento y al recuadro del s de diferentes maneras por diferentes navegadores. Esto está resultando problemático, especialmente cuando trato de calcular el ancho exterior y la posición visual de un rectángulo y colocarlo junto a otros elementos.
Por ejemplo:
- Firefox agrega 1px de inserción (abajo e izquierda) y 1px de compensación (arriba y derecha)
- Chrome agrega 1px de inserción (superior e izquierda) y 1px de compensación (inferior y derecha)
Mi única solución hasta ahora sería dibujar los bordes reales yo mismo (probablemente con la path
herramienta) y colocar los bordes detrás del elemento trazado. Pero esta solución es una solución desagradable, y preferiría no seguir este camino si es posible.
Entonces mi pregunta es, ¿puedes controlar cómo stroke-width
se dibuja un SVG en los elementos?
paint-order
parámetro, donde puede especificar, que el relleno se debe representar en la parte superior del trazo, por lo que obtendrá la "alineación externa", consulte jsfiddle.net/hne0kyLg/1Respuestas:
No, no puede especificar si el trazo se dibuja dentro o fuera de un elemento. Hice una propuesta al grupo de trabajo SVG para esta funcionalidad en 2003, pero no recibió apoyo (ni discusión).
Como señalé en la propuesta,
Editar : esta respuesta puede ser incorrecta en el futuro. Debería ser posible para lograr estos resultados usando SVG efectos vectoriales , mediante la combinación
veStrokePath
conveIntersect
(por 'interior') o conveExclude
(por 'exterior). Sin embargo, Vector Effects todavía es un módulo borrador en funcionamiento sin implementaciones que todavía pueda encontrar.Edición 2 : la especificación del borrador SVG 2 incluye una
stroke-alignment
propiedad (con centro | dentro | fuera de los valores posibles). Esta propiedad puede llegar a ser UA eventualmente.Edición 3 : Divertida y decepcionantemente, el grupo de trabajo SVG se ha eliminado
stroke-alignment
de SVG 2. Puede ver algunas de las preocupaciones descritas después de la prosa aquí .fuente
ACTUALIZACIÓN: El
stroke-alignment
atributo fue el 1 de abril de 2015 movido a una especificación completamente nueva llamada SVG Strokes .A partir del borrador del editor SVG 2.0 del 26 de febrero de 2015 (y posiblemente desde el 13 de febrero ),
lacon los valoresstroke-alignment
propiedad esta presenteinner
,center
(predeterminado) youter
.Parece funcionar de la misma manera que la
stroke-location
propiedad propuesta por @Phrogz y lastroke-position
sugerencia posterior . Esta propiedad ha sido planificada desde al menos 2011, pero aparte de una anotación que decía, nunca se ha detallado en la especificación ya que se aplazó , hasta ahora, al parecer.
Ningún navegador admite esta propiedad, o, que yo sepa, ninguna de las nuevas funciones de SVG 2, todavía, pero espero que lo hagan pronto a medida que la especificación madure. Esta ha sido una propiedad que personalmente he instado a tener, y estoy muy feliz de que finalmente esté allí en la especificación.
Parece haber algunos problemas en cuanto a cómo debe comportarse la propiedad en las rutas abiertas, así como en los bucles. Estos problemas, muy probablemente, prolongarán las implementaciones en todos los navegadores. Sin embargo, actualizaré esta respuesta con nueva información a medida que los navegadores comiencen a admitir esta propiedad.
fuente
stroke-alignment
se especifica en SVG Strokes, un borrador de trabajo del W3C. Mientras tanto, el borrador del editor SVG 2 W3C dice que una propiedad de posicionamiento de trazo debe estar en la especificación SVG en svgwg.org/svg2-draft/painting.html#SpecifyingStrokePaint , pero esa especificación ya ha alcanzado el estado de recomendación de candidato W3C y no existe tal propiedad en la especificación aparte de un enlace a lastroke-position
propuesta, haciendo que parezca que ese no será el caso.Encontré una manera fácil, que tiene algunas restricciones, pero funcionó para mí:
Aquí un ejemplo de trabajo:
fuente
<use>
? ¿Por qué no simplemente poner la ruta y la ruta de recorte directamente? Esto funciona muy bien:<svg width="240" height="240" viewBox="0 0 1024 1024"> <path id="ld" d="M256,0 L0,512 L384,512 L128,1024 L1024,384 L640,384 L896,0 L256,0 Z" clip-path="url(#clip)" stroke="#0081C6" stroke-width="160" fill="#00d2b8"/> <clipPath id="clip"> <use xlink:href="#ld"/> </clipPath> </svg>
. (Sí, esto es un SVG completamente razonable y correcto y se reproducirá correctamente en todas partes. No temas la recurrencia.)Puede usar CSS para diseñar el orden de los trazos y rellenos. Es decir, golpee primero y luego llene segundo, y obtenga el efecto deseado.
MDN en
paint-order
: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/paint-orderCódigo CSS:
fuente
Aquí hay una función que calculará cuántos píxeles necesita agregar, usando el trazo dado, en la parte superior, derecha, inferior e izquierda, todo en función del navegador:
fuente
Como han señalado las personas anteriores, tendrá que volver a calcular un desplazamiento a las coordenadas de la trayectoria del trazo o duplicar su ancho y luego enmascarar un lado u otro, porque SVG no solo no admite de forma nativa la alineación del trazo de Illustrator, sino que PostScript tampoco .
La especificación para trazos en el Manual PostScript de Adobe, 2da edición dice: " 4.5.1 Trazos: el operador de trazo dibuja una línea de cierto grosor a lo largo de la ruta actual. Para cada segmento recto o curvo en el camino, el trazo dibuja una línea centrada en el segmento con lados paralelos al segmento ". (énfasis suyo)
El resto de la especificación no tiene atributos para compensar la posición de la línea. Cuando Illustrator le permite alinearse dentro o fuera, vuelve a calcular el desplazamiento de la ruta real (porque todavía es computacionalmente más barato que la sobreimpresión y luego el enmascaramiento). Las coordenadas de ruta en el documento .ai son referencia, no lo que se rastrilla o exporta a un formato final.
Debido a que el formato nativo de Inkscape es SVG de especificaciones, no puede ofrecer una característica que carece de especificaciones.
fuente
Aquí hay una solución para el
rect
uso de límites internossymbol
yuse
.Ejemplo : https://jsbin.com/yopemiwame/edit?html,output
SVG :
Nota: Asegúrese de reemplazar el
?
enuse
los valores reales.Antecedentes : La razón por la que esto funciona es porque el símbolo establece una nueva ventana gráfica mediante la sustitución
symbol
consvg
y la creación de un elemento en el DOM sombra. Estosvg
de la sombra DOM se vincula a suSVG
elemento actual . Tenga en cuenta quesvg
s puede anidarse y cada unosvg
crea una nueva ventana gráfica, que recorta todo lo que se superpone, incluido el borde superpuesto. Para obtener una descripción mucho más detallada de lo que está sucediendo, lea este fantástico artículo de Sara Soueidan.fuente
No sé qué tan útil será eso, pero en mi caso simplemente creé otro círculo con borde solamente y lo coloqué "dentro" de la otra forma.
fuente
Una posible solución (sucia) es mediante el uso de patrones,
Aquí hay un ejemplo con un triángulo interior:
https://jsfiddle.net/qr3p7php/5/
fuente
La solución de Xavier Ho de duplicar el ancho del trazo y cambiar el orden de la pintura es brillante, aunque solo funciona si el relleno es de color sólido, sin transparencia.
He desarrollado otro enfoque, más complicado pero funciona para cualquier relleno. También funciona en elipses o caminos (con el último hay algunos casos de esquina con comportamiento extraño, por ejemplo, caminos abiertos que se cruzan entre sí, pero no mucho).
El truco es mostrar la forma en dos capas. Uno sin trazo (solo relleno) y otro solo con trazo de doble ancho (relleno transparente) y pasado a través de una máscara que muestra la forma completa, pero oculta la forma original sin trazo.
fuente