2012-01-13 16 views
11

Tengo un pequeño widget svg cuyo propósito es mostrar una lista de ángulos (ver imagen).¿Cómo hacer una "línea" de SVG con un borde a su alrededor?

En este momento, los ángulos son elementos de línea, que solo tienen un trazo y no se llenan. Pero ahora me gustaría tener un color de "relleno interno" y un "trazo/borde" a su alrededor. Supongo que el elemento de línea no puede manejar esto, entonces, ¿qué debería usar en su lugar?

Observe que la línea-tapa del trazo de la línea se redondea. Me gustaría mantener este efecto en la solución.

Angle Line

<svg height="160" version="1.1" viewBox="-0.6 -0.6 1.2 1.2" width="160" xmlns="http://www.w3.org/2000/svg"> 
    <g> 
    <g> 
     <circle class="sensorShape" cx="0" cy="0" fill="#FFF" r="0.4" stroke="black" stroke-width="0.015"/> 
     <line stroke="black" stroke-width="0.015" x1="0" x2="0" y1="-0.4" y2="0.4"/> 
     <line stroke="black" stroke-width="0.015" x1="-0.4" x2="0.4" y1="0" y2="0"/> 
    </g> 
    <g class="lsNorthAngleHandsContainer"> 
     <line data-angle="348" stroke="red" stroke-linecap="round" stroke-width="0.04" transform="rotate(348)" x1="0" x2="0" y1="0" y2="-0.4"/> 
     <text font-size="0.08" transform="translate(-0.02316467632710395,-0.45125904029352226)"> 
     348 
     </text> 
    </g> 
    </g> 
</svg> 

Respuesta

14

Añadir una segunda línea, con las mismas coordenadas, pero más delgado ancho de línea:

<g class="lsNorthAngleHandsContainer"> 
    <line data-angle="348" stroke="red" stroke-linecap="round" stroke-width="0.04" transform="rotate(348)" x1="0" x2="0" y1="0" y2="-0.4"/> 
    <line data-angle="348" stroke="yellow" stroke-linecap="round" stroke-width="0.025" transform="rotate(348)" x1="0" x2="0" y1="0" y2="-0.4"/> 
3

Parece que su línea es opaco, por lo que sólo puede dibujar una línea delgada con el color "interna" en la parte superior de la línea más gruesa con el color "fuera".

+0

Gracias, esa es una buena idea. Pero, ¿cómo me aseguraré de que la línea "superior" esté centrada exactamente en el centro de la línea "inferior"? –

+1

Simplemente use las mismas coordenadas con un ancho de línea más delgado. Con tapas redondeadas se verá correcto. – Janne

+0

¡Ah, ahora que lo pienso, creo que tienes razón! Gracias Janne. –

2

Se puede usar un rect con las esquinas redondeadas, pero la matemática cambia un poco:

<rect data-angle="348" stroke="red" stroke-linecap="round" stroke-width="0.02" fill="#FF0" transform="rotate(348, 0, 0)" x="-0.02" y="-0.4" width=".06" height=".4" rx=".03" ry=".03"/> 

http://jsfiddle.net/RNAuP/

+0

Eso es lo que originalmente pensé que sería la solución. Sin embargo, el tuyo no se ve tan bien como el de Janne. Los puntos inicial y final de la rect no se alinean perfectamente en el centro del círculo y en el contorno del círculo. –

+0

Si puede alinearlo correctamente, esta solución parece más fácil de manipular (por ejemplo, si quería añadir/eliminar dinámicamente el contorno, lo cual hago). Entonces, esto se vuelve poco manejable por una razón diferente ... tienes que usar el punto medio de cada "lado corto" del recto. –

+0

Es una cuestión de aritmética, debe restar el ancho del borde del centro de rotación http://jsfiddle.net/F5e74/, francamente creo que dos líneas es una solución más simple. – Duopixel

0

También puede hacerlo con una ruta, aunque es complicado con los bits redondos:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ 
    <!-- I often use entities to be able to change lot of numbers at once in static SVG, also kind of makes the paths more readable. 
     Obvisouly, if you're generating the path you can use the same variables in code to append to d --> 
    <!ENTITY handFill "0.01"> 
    <!ENTITY handFill2 "0.02"><!-- Should be 2 * handFill to be centered --> 
    <!ENTITY handStroke "0.005"><!-- Should be less than handFill2 to not hide fill --> 
]> 
<svg height="160" version="1.1" viewBox="-0.6 -0.6 1.2 1.2" width="160" xmlns="http://www.w3.org/2000/svg"> 
    <g> 
    <g> 
     <circle class="sensorShape" cx="0" cy="0" fill="#FFF" r="0.4" stroke="black" stroke-width="0.015"/> 
     <line stroke="black" stroke-width="0.015" x1="0" x2="0" y1="-0.4" y2="0.4"/> 
     <line stroke="black" stroke-width="0.015" x1="-0.4" x2="0.4" y1="0" y2="0"/> 
    </g> 
    <g class="lsNorthAngleHandsContainer"> 
     <path d=" 
     M -&handFill;,0 l0,-0.4 
     a &handFill;,&handFill; 0 0,1 &handFill2;,0 
     l 0,0.4 
     a &handFill;,&handFill; 0 0,1 -&handFill2;,0 
     " stroke="red" stroke-linecap="round" stroke-width="&handStroke;" fill="yellow" transform="rotate(348)" /> 
     <text font-size="0.08" transform="translate(-0.02316467632710395,-0.45125904029352226)"> 
     348 
     </text> 
    </g> 
    </g> 
</svg> 
2

Encontré la solución elegante inspirada en illustration al artículo W3C sobre filling and stroking. Básicamente, se mueve camino a las definiciones y utilizar esta definición para dibujar dos elementos:

<svg width="200" height="200" viewBox="0 0 100 100"> 
    <defs> 
     <line id="line1" x1="25" x2="75" y1="25" y2="75"/> 
    </defs> 
    <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#line1" class="stroke"></use> 
    <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#line1" class="line"></use> 
</svg> 

Mediante el uso de <defs> y <use> se puede cambiar sólo elemento de ruta para actualizar ambas líneas. JSFiddle demo

Cuestiones relacionadas