Introdução ao SVG na Web
Introdução ao SVG na Web
gráficos
vetoriais
na
web com
helderdarocha helder@[Link]
Programa
Uma introdução abrangente a SVG 1.1
[Link]
[Link]
O que é SVG?
100 px
Dimensões (opcional)
100 px
Sistema de coordenadas
r = 50
viewBox
200
(100,100)
origem + dimensões
200
Sistema de coordenadas
r = 25px
100 px
viewBox
(50px,50px)
origem + dimensões
100 px
XSLT XML
Como exibir
Abra em um browser!
Opera
Chrome
Safari
Firefox
[Link]
Como exibir
Qualquer plataforma
Opera
Chrome
Safari
Firefox
Opera
Chrome
Safari
Firefox
<p>Com
Img</p>
<img
src="[Link]"/>
<p>Com
Object</p>
<object
data="[Link]"></object>
<p>Com
Embed</p>
<embed
src="[Link]"/>
</body>
</html>
[Link]
Como usar em HTML5 (2)
Embutir no código
<html>
<head>
<style>
svg
{
border:
red
dashed
1px;
height:
200px;
width:
200px;
}
circle
{fill:
red}
</style>
</head>
<body>
<h1>SVG
embutido</h1>
[Link]
<svg
viewBox="0
0
200
200">
<circle
r="50"
cx="100"
cy="100"
fill="green"
/>
</svg>
</body>
</html>
Como usar em CSS
<html>
<head>
<style>
#circulo
{
background-‐image:
url([Link]);
height:
100%;
width:
100%;
}
#container
{
height:
200px;
width:
200px;
border:
blue
dashed
1px;
}
</style>
</head>
<body>
<h1>SVG
background
CSS</h1>
<div
id="container">
<div
id="circulo"></div>
</div>
</body>
</html>
[Link]
Como usar em CSS 3
<html>
<head> Máscara SVG em CSS 3
<style>
#paraiba
{
-‐webkit-‐mask-‐image:
url([Link]);
-‐webkit-‐mask-‐origin:
padding;
-‐webkit-‐mask-‐position:
180px
220px;
-‐webkit-‐transform:
scale(2.8);
}
</style>
</head>
<body>
<h1>Mascaras
SVG
e
CSS3</h1>
<img
src="imagens/[Link]"
id="paraiba">
</body>
</html>
css3_mascara.html
SVG vs. Canvas
Objetos em XML vs
Operações JavaScript
<h1>HTML5
Canvas</h1>
<canvas
id="desenho1"
height="300"
width="300"></canvas>
<script>
var
acanvas
=
[Link]("desenho1");
var
ctx
=
[Link]("2d");
[Link]
=
"#ff459a";
[Link](50,50,
150,150);
</script>
Fallbacks
Em caso de erro, use tecnologia alternativa (HTML/CSS/PNG)
<img
src="[Link]"
onerror="[Link]='[Link]'"/>
E se não funcionar?
Workarounds
Às vezes funciona se escrever o SVG de outro jeito
Fallbacks
Em caso de erro, use tecnologia alternativa (HTML/CSS/PNG)
<img
src="[Link]"
onerror="[Link]='[Link]'"/>
Polyfills
• Modernizr + bibliotecas [Link], raphaël e [Link]
• FakeSmile
breve tutorial
Componentes gráficos
<rect> – Retângulo
<circle> – Círculo
<ellipse> – Elipse
<line> – Linha reta
<polyline> – Linha com múltiplos segmentos
<polygon> – Polígono
<image> - Imagem bitmap
<text> - Texto
<path> - Caminho arbitrário (curvas, linhas, etc.)
Pintura
Dois atributos para pintar componentes
preenchimento (fill)
contorno, ou traço (stroke)
Pintura
Dois atributos para pintar componentes
preenchimento (fill)
contorno, ou traço (stroke)
<svg
xmlns="[Link]
<circle
r="50"
cx="100"
cy="100"
fill="green"/>
<circle
r="50"
cx="125"
cy="125"
fill="#008000"
fill-‐opacity="0.5"/>
<circle
r="50"
cx="150"
cy="150"
fill="#080"
fill-‐opacity="0.2"/>
</svg>
Traço
stroke: cor
stroke-width: espessura [Link]
circle
{
<?xml-‐stylesheet
type="text/css"
stroke-‐width:
10;
href="[Link]"?>
stroke-‐opacity:
0.5;
}
<svg
xmlns="[Link]
#c1
{
viewBox="0
0
300
300">
fill:
green;
stroke:
blue;
<circle
r="75"
cx="100"
cy="100"
fill-‐opacity:
0.6;
}
id="c2"/>
#c2
{
<circle
r="50"
cx="150"
cy="150"
fill:
#f00;
id="c1"/>
stroke:
yellow;
</svg> }
[Link]
Linha simples <line>
[Link]
<svg
xmlns="[Link]
<ellipse
cx="200"
cy="100"
rx="190"
ry="90"
fill="yellow"
fill-‐opacity="0.5"
stroke="#00f"
stroke-‐width="1"
stroke-‐dasharray="5
5"/>
<ellipse
cx="250"
cy="150"
rx="75"
ry="125"
fill="red"
fill-‐opacity="0.2"
stroke="#f00"
stroke-‐width="5"
stroke-‐opacity="0.5"/>
<ellipse
cx="300"
cy="200"
rx="40"
ry="150"
fill="black"
fill-‐opacity="0"
stroke="#0f0"
stroke-‐width="20"
stroke-‐opacity="0.2"
/>
</svg>
Polígono aberto <polyline>
points – lista de coords x,y (0,0) 150
<polyline
points="150,150
50,150
100,20
150
150,50
200,200
50,200
[Link]
20,154
48,82
32,20"
fill="yellow"
fill-‐opacity="0.2"
stroke="red"
stroke-‐width="10"/>
Polígono fechado <polygon>
Similar a <polyline>, mas sempre fechada
points – lista de coords x,y com vértices
<polygon
points="150,150
50,250
50,150
100,50
200,50
250,100
300,150
[Link]
350,250
250,250"
fill="red"
fill-‐opacity="0.2"
stroke-‐opacity="0.5"
stroke="navy"
stroke-‐width="10"
stroke-‐linecap="round"
stroke-‐linejoin="round"
stroke-‐dasharray="40
20
5
20"/>
Texto <text>
<svg
...
viewBox="-‐10
-‐50
200
200">
<rect
x="0"
y="0"
height="36"
width="180"
...
/>
Retângulo e texto com
<text
font-‐size="36"
mesmas coordenadas x,y
x="0"
y="0">Agora</text>
</svg>
<svg
...>
<defs>
<rect
id="preto"
x="0"
y="0"
width="20"
height="20"
fill="rgb(64,32,32)"
/>
<rect
id="branco"
x="0"
y="0"
width="20"
height="20"
fill="rgb(255,225,200)"
/>
</defs>
<svg
...>
<defs>
...
<g
id="quatroCasas"
transform="translate(10,10)">
<use
xlink:href="#preto"
/>
<use
xlink:href="#branco"
transform="translate(20)"/>
<use
xlink:href="#branco"
transform="translate(0,20)"/>
<use
xlink:href="#preto"
transform="translate(20,20)"/>
</g>
</defs>
<use
xlink:href="#quatroCasas"
/>
</svg>
Por que usar <defs> e <use>?
Tabuleiro de xadrez SVG 66
linhas
sem <defs> e <use> ~3500
chars
</defs>
Tabuleiro com <defs> e <use>
<defs>
<rect
id="preto"
...
fill="rgb(64,32,32)"
/>
<rect
id="branco"
...
fill="rgb(255,225,200)"
/>
<g
id="quatroCasas">
<use
xlink:href="#preto"
/>
<use
xlink:href="#branco"
transform="translate(20)"/>
<use
xlink:href="#branco"
transform="translate(0,20)"/>
<use
xlink:href="#preto"
transform="translate(20,20)"/>
</g>
<g
id="filaDupla">
<use
xlink:href="#quatroCasas"
/>
<use
xlink:href="#quatroCasas"
transform="translate(40)"
/>
<use
xlink:href="#quatroCasas"
transform="translate(80)"
/>
<use
xlink:href="#quatroCasas"
transform="translate(120)"
/>
</g>
<g
id="tabuleiro">
<use
xlink:href="#filaDupla"
/>
<use
xlink:href="#filaDupla"
transform="translate(0,40)"
/>
<use
xlink:href="#filaDupla"
transform="translate(0,80)"
/>
<use
xlink:href="#filaDupla"
transform="translate(0,120)"
/>
</g>
</defs>
28
linhas
<defs>
+ reuso! ~1400
chars
1. M100,100 L150,200 z
(100,100)
(150,200)
Linhas retas
H ou h + coordenadas x linhas retas horizontais
V ou v + coordenadas y linhas retas verticais
L ou l + pares de coords x,y linhas retas em qq direção
1. M100,100
L150,200
z
2. M100,100
L150,200
h50
z
1. Parte de (150,200)
2. Avança 50 unidades na horizontal
(0,0)
3. Fecha figura (desenha linha)
(
( (200,200)
Linhas retas
H ou h + coordenadas x linhas retas horizontais
V ou v + coordenadas y linhas retas verticais
L ou l + pares de coords x,y linhas retas em qq direção
1. M100,100
L150,200
z
2. M100,100
L150,200
h50
z
3. M100,100
L150,200
h50
v-‐100
z
1. Parte de (200,200)
2. Sobe 100 unidades na vertical (0,0)
3. Fecha figura (desenha linha)
( z (200,100)
( (
Linhas retas
H ou h + coordenadas x linhas retas horizontais
V ou v + coordenadas y linhas retas verticais
L ou l + pares de coords x,y linhas retas em qq direção
1. M100,100
L150,200
z
2. M100,100
L150,200
h50
z
3. M100,100
L150,200
h50
v-‐100
z
4. M100,100
L150,200
h50
v-‐100
l-‐50,50
z
(0,0)
1. Parte de (200,100)
(100,100) z (200,
2. Volta 50 un. e desce 50 un. z
3. Fecha figura (desenha linha) z (150,150)
(
Linhas retas
H ou h + coordenadas x linhas retas horizontais
V ou v + coordenadas y linhas retas verticais
L ou l + pares de coords x,y linhas retas em qq direção
1. M100,100
L150,200
z
2. M100,100
L150,200
h50
z
3. M100,100
L150,200
h50
v-‐100
z
4. M100,100
L150,200
h50
v-‐100
l-‐50,50
z
5. M100,100
L150,200
h50
v-‐100
l-‐50,50
L150,50
100,50
z
(0,0)
(100,50)
(150,50)
1.(100,100)
Parte de (150,150) z (200,100) ( z
2. Desenha linha para (150,50) z
3. Desenha linhaz para (100,50)
4. Fecha figura (desenha linha)
(150,200) (200,200)
Curvas Bézier cúbicas
Curva normal: C ou c com coordenadas x1,y1
x2,y2 x,y onde
x,y = coordenadas do ponto final
x1,y1
= coordenadas do controle tangencial do ponto inicial
x2,y2
= coordenadas do controle tangencial do ponto final
ry y
rx
θ
x
M0,0
L0,-‐100
A100,100
0
0,0
-‐100,0
L0,0
z
M-‐100,-‐100
L0,-‐100
A100,100
0
1,0
-‐100,0
L-‐100,-‐100
z
M0,0
L0,-‐100
A100,100
0
1,1
-‐100,0
L0,0
z
Exemplos de arcos simples
<path
d="M300,200
h-‐150
a150,150
0
1,0
150,-‐150
z"
fill="red"
stroke="blue"
stroke-‐width="5"
/>
fill="none"
stroke="red"
stroke-‐width="5"
/>
[ ]
a11
a12
a13
matrix(a11,a12,a13,a21,a22,a23)
a21
a22
a23
matriz de transformações 0
0
1
<use
xlink:href="#coords"
stroke="black"
/>
<use
xlink:href="#coords"
stroke="red" rotate_scale.svg
transform="translate(200,100)
rotate(30)
scale(1.5)"
/>
skew()
Distorção
de
cisalhamento
(graus)
...
<use
xlink:href="#coords"
stroke="black"
/>
<use
xlink:href="#coords"
[Link]
stroke="red"
transform="translate
(100,100)
skewX(50)"
/>
Em cascata
<g
transform="translate(-‐10,-‐20)">
<g
transform="scale(2)">
<g
transform="rotate(45)">
<g
transform="translate(5,10)">
<!-‐-‐
elementos
-‐-‐>
</g>
</g> Fonte:
W3C
(especificação
SVG)
</g>
<g
transform="translate(-‐10,-‐20)
</g>
scale(2)
rotate(45)
translate(5,10)">
<!-‐-‐
elementos
-‐-‐>
</g>
Transformações equivalentes
offset
<linearGradient>
Atributos x1/x2 e y1/y2
y1
10%
<radialGradient>
Atributos cx, cy e r
Valores relativos ao gráfico (0 - 100%)
Pontos de parada marcados com <stop>
[Link]
[Link]
(fonte)
x = Resultado
Clipping <clipPath>
<defs>
<clipPath
id="poly">
<circle
r="152"
+
cx="254"
+
cy="245"/>
</clipPath>
</defs>
<image
xlink:href="[Link]"
x="0"
y="0"
height="500"
width="500"
clip-‐path="url(#poly)"/>
<filter
id="f1">
<feGaussianBlur
stdDeviation="5"
/>
</filter>
</defs>
<symbol
id="transistorPNP"
viewBox="-‐1
-‐1
22
22">
<use
xlink:href="#baseColetor"
/>
<line
x1="0"
x2="9"
y1="20"
y2="10"
marker-‐end="url(#seta)"
/>
Símbolo
</symbol>
"transistorPNP"
sendo reusado
<marker
id="setaPNP"
viewBox="0
0
10
10"
como "seta" de
refX="0"
refY="5"
orient="auto"
uma polyline
markerUnits="userSpaceOnUse"
markerWidth="50"
markerHeight="50">
<use
xlink:href="#transistorPNP"
x="0"
y="0"
height="10"
width="10"
transform="rotate(-‐90,5,5)"
/>
</marker>
Image sprites e fontes
Símbolos podem ser agrupados em um SVG e
referenciados pelo ID para reuso
• Coleção de fontes usando <font>, <glyph>, ...
• Coleção de ícones usando <symbol>, ...
Referenciáveis via ID / XLink
<defs>
<symbol
id="twitter-‐icon"
viewBox="0
0
32
32">
<path
d="..."
/>
</symbol>
...
</defs>
<use
xlink:href="#twitter-‐icon"
/>
randomX
height
Calculando valores para
criar círculos SVG em
width posições e cores aleatórias
script_3.js
Dimensões
do
SVG
Criação dinâmica de objetos
(exemplo: parte 2 de 3)
function
criarCirculo(evt)
{
...
var
svgNS
=
"[Link]
var
circulo
=
[Link](svgNS,
"circle");
[Link](null,
"cx",
randomX);
[Link](null,
"cy",
randomY);
[Link](null,
"fill",
color);
[Link](null,
"r",
[Link](null,
"r"));
[Link]("click",
criarCirculo,
false);
[Link](circulo);
}
Círculo criado com cx, cy e fill aleatórios
adicionado ao parentNode (<svg>) script_3.js
Criação dinâmica de objetos
(exemplo: parte 3 de 3)
<svg
xmlns="[Link]
width="500"
height="500">
</svg>
</svg>
<svg
xmlns="[Link]
<image
id="trends"
xlink:href="[Link]"
height="100"
width="250"
x="50"
y="50"
/>
<g
stroke="blue"
stroke-‐width="2">
<line
x1="200"
x2="200"
y1="175"
y2="225"/>
...
</g>
...
<animate
attributeName="x"
calcMode="linear"
values="50;150;200;500"
dur="4s"
begin="click"
fill="freeze"
xlink:href="#trends"
/>
</svg>
0s 0.4s 3.6s
smil_4_keyTimes.svg
values + keyTimes + keySplines
Trecho 1: movimento linear
Trecho 2: começa lento, acelera no meio, depois desacelera
Trecho 3: dispara no início e desacelera até parar
<animate
attributeName="x"
values="50;
200;
350;
500"
dur="4s"
keyTimes="0;
0.333;
0.667;
1"
begin="click"
keySplines="0.0,0.0
1.0,1.0;
0.5,0.0
0.5,1.0;
0.0,0.75
0.25,1.0;"
calcMode="spline"
fill="freeze"
xlink:href="#security"
/>
smil_5_keySplines.svg
<animateTransform>
Porque <animate> não funciona com
funções de transformação de coordenadas
<animateTransform
attributeName="transform"
type="rotate
ou
translate
ou
scale
ou
skewX
ou
skewY
"/>
Exemplo <animateTransform>
(parte 1 de 3)
<svg
...>
<defs>
<rect
id="r"
x="50"
y="-‐10"
height="20"
width="75"
rx="10"
fill="blue"
/>
</defs>
<g
id="g">
<use
xlink:href="#r"
opacity="1"/>
</g>
</svg>
Um retângulo com
cantos arredondados
Exemplo <animateTransform>
(parte 2 de 3)
<g>
<use
xlink:href="#r"
opacity="1"/>
<use
xlink:href="#r"
opacity=".9"
transform="rotate(30)
scale(0.95)"
/>
<use
xlink:href="#r"
opacity=".8"
transform="rotate(60)
scale(0.9)"
/>
<use
xlink:href="#r"
opacity=".7"
transform="rotate(90)
scale(0.85)"
/>
<use
xlink:href="#r"
opacity=".6"
transform="rotate(120)
scale(0.8)"
/>
<use
xlink:href="#r"
opacity=".5"
transform="rotate(150)
scale(0.75)"
/>
<use
xlink:href="#r"
opacity=".4"
transform="rotate(180)
scale(0.7)
"
/>
<use
xlink:href="#r"
opacity=".35"
transform="rotate(210)
scale(0.65)"
/>
<use
xlink:href="#r"
opacity=".3"
transform="rotate(240)
scale(0.6)
"
/>
<use
xlink:href="#r"
opacity=".25"
transform="rotate(270)
scale(0.55)"
/>
<use
xlink:href="#r"
opacity=".2"
transform="rotate(300)
scale(0.5)"
/>
<use
xlink:href="#r"
opacity=".15"
transform="rotate(330)
scale(0.45)"
/>
</g>
"Escadaria"
em espiral
Exemplo <animateTransform>
(parte 3 de 3)
<svg
...>
<defs>
<rect
id="r"
x="50"
y="-‐10"
height="20"
width="75"
rx="10"
fill="blue"
/>
</defs>
<g
transform="translate(150,150)"
<animateTransform
attributeName="transform"
type="rotate"
begin="0s"
dur="1s"
calcMode="discrete"
values="330;300;270;240;210;180;150;120;90;60;30"
repeatCount="indefinite"/>
<use
xlink:href="#r"
opacity="1"/>
...
"Escadaria"
<use
xlink:href="#r"
opacity=".15"
transform="rotate(330)
scale(0.45)"
/>
girando
</g>
</svg>
<animateMotion>
Objeto move-se por caminho que pode ser
• xlink:href="#path" (referência para um <path> )
• Atributo path: sintaxe do atributo d do elemento <path>
• Elemento filho <mpath xlink:href="#path" />
[Link] [Link]
Qual a alternativa?
• Google sugere usar polyfills
• Solução rápida mas ineficiente (scripts, CPU)
• Bibliotecas que geram SVG e CSS
[Link] [Link]
• Animações CSS 3!
Alternativas W3C
Há uma sobreposição de soluções
<g
class="monster-‐trends__right-‐arm">
<use
xlink:href="#right-‐arm-‐background"
fill="yellow"
stroke="blue"/>
<use
xlink:href="#right-‐arm-‐detail"
fill="blue"
/>
<animateTransform
attributeName="transform"
dur="2s"
type="rotate"
values="0
120
30;45
120
35;0
120
30"
repeatCount="indefinite"/>
</g>
SVG + animações CSS3
<style
type="text/css">
.monster-‐trends__right-‐arm
{
animation:
right-‐arm-‐values
2s
infinite;
transform-‐origin:
30%
70%;
}
@keyframes
right-‐arm-‐values
{
0%
{
transform:
rotate(0deg);
}
50%
{
transform:
rotate(45deg);
}
100%
{
transform:
rotate(0deg);
}
}
</style>
<g
class="monster-‐trends__right-‐arm">
<use
xlink:href="#right-‐arm-‐background"
fill="yellow"
stroke="blue"/>
<use
xlink:href="#right-‐arm-‐detail"
fill="blue"
/>
</g>
SVG2
Working draft!
• Muito mais integração com CSS
• CSS compositing & blending
• CSS3 2D+3D transforms
• CSS masking
• Filter Effects 1.0
• CSS Color
• Paint servers (+CSS gradients em SVG)
• Elemento <star>
• Interoperabilidade com HTML5 Canvas
• Novos objetos em SVG DOM
• ...
Conclusões
SVG 1.1 é solução eficiente para gráficos vetoriais
• Leve, escalável, reusável e padrão aberto W3C
• Elementos e estilos manipuláveis como objetos
• Compatibilidade com HTML5 e CSS3
• Suporte quase universal para gráficos estáticos na Web
• Amplo suporte em ferramentas gráficas
Conclusões
SVG 1.1 é solução eficiente para gráficos vetoriais
• Leve, escalável, reusável e padrão aberto W3C
• Elementos e estilos manipuláveis como objetos
• Compatibilidade com HTML5 e CSS3
• Suporte quase universal para gráficos estáticos na Web
• Amplo suporte em ferramentas gráficas
Ainda existem problemas
• Compatibilidade (resolvidos com workarounds)
• Falta de suporte para animações
• Duplicação de funcionalidades
Conclusões
SVG 1.1 é solução eficiente para gráficos vetoriais
• Leve, escalável, reusável e padrão aberto W3C
• Elementos e estilos manipuláveis como objetos
• Compatibilidade com HTML5 e CSS3
• Suporte quase universal para gráficos estáticos na Web
• Amplo suporte em ferramentas gráficas
Ainda existem problemas
• Compatibilidade (resolvidos com workarounds)
• Falta de suporte para animações
• Duplicação de funcionalidades
SVG2: +interoperabilidade com CSS3 e HTML5
Referências
Este material é baseado em Tutorial SVG (Helder da Rocha, 2010) disponível em
[Link]
Especificações
• SVG 1.1 Second Edition. [Link]/TR/SVG/ August 2011
• SVG 2 Working Draft. [Link] July 2015
• SMIL 3 [Link]/TR/SMIL/ December 2008
• CSS 2 [Link] April 2008
• DOM 3 [Link] April 2004
Exemplos
• Aplicação Orbitas (gera órbitas planetárias em SVG): [Link]/astronomia/orbitas escrito em
helder@[Link]