Quando você passa uma string de marcação $
, ela é analisada como HTML usando a innerHTML
propriedade do navegador em um <div>
(ou outro contêiner adequado para casos especiais como <tr>
). innerHTML
não pode analisar SVG ou outro conteúdo que não seja HTML e, mesmo que pudesse, não seria capaz de dizer que <circle>
deveria estar no espaço de nome SVG.
innerHTML
não está disponível no SVGElement - é uma propriedade apenas do HTMLElement. Atualmente, não há uma innerSVG
propriedade ou outra maneira (*) de analisar o conteúdo em um SVGElement. Por esse motivo, você deve usar métodos no estilo DOM. O jQuery não oferece acesso fácil aos métodos no espaço de nomes necessários para criar elementos SVG. Realmente o jQuery não foi projetado para uso com SVG e muitas operações podem falhar.
O HTML5 promete permitir que você use <svg>
sem um documento xmlns
HTML ( text/html
) dentro do futuro. Mas isso é apenas um hack do analisador (**), o conteúdo SVG ainda será SVGElements no espaço de nome SVG, e não HTMLElements, portanto, você não poderá usá-lo innerHTML
mesmo que pareça parte de um documento HTML.
No entanto, para os navegadores de hoje, você deve usar X HTML (servido corretamente como application/xhtml+xml
; salve com a extensão de arquivo .xhtml para testes locais) para fazer com que o SVG funcione. (De qualquer forma, faz sentido; SVG é um padrão adequadamente baseado em XML.) Isso significa que você precisaria escapar dos <
símbolos dentro do bloco de script (ou incluir em uma seção CDATA) e incluir a xmlns
declaração XHTML . exemplo:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
</head><body>
<svg id="s" xmlns="http://www.w3.org/2000/svg"/>
<script type="text/javascript">
function makeSVG(tag, attrs) {
var el= document.createElementNS('http://www.w3.org/2000/svg', tag);
for (var k in attrs)
el.setAttribute(k, attrs[k]);
return el;
}
var circle= makeSVG('circle', {cx: 100, cy: 50, r:40, stroke: 'black', 'stroke-width': 2, fill: 'red'});
document.getElementById('s').appendChild(circle);
circle.onmousedown= function() {
alert('hello');
};
</script>
</body></html>
*: bem, há o parseWithContext do DOM Nível 3 LS , mas o suporte ao navegador é muito ruim. Edite para adicionar: no entanto, embora não seja possível injetar marcação em um SVGElement, você pode injetar um novo SVGElement em um HTMLElement usando innerHTML
e transferi-lo para o destino desejado. Provavelmente será um pouco mais lento:
<script type="text/javascript"><![CDATA[
function parseSVG(s) {
var div= document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
div.innerHTML= '<svg xmlns="http://www.w3.org/2000/svg">'+s+'</svg>';
var frag= document.createDocumentFragment();
while (div.firstChild.firstChild)
frag.appendChild(div.firstChild.firstChild);
return frag;
}
document.getElementById('s').appendChild(parseSVG(
'<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" onmousedown="alert(\'hello\');"/>'
));
]]></script>
**: Eu odeio a maneira como os autores do HTML5 parecem ter medo de XML e determinados a colocar recursos baseados em XML na bagunça suja que é HTML. O XHTML resolveu esses problemas anos atrás.
RMB
>edit as html
na tag html e pressionar enter, tudo será exibido (mas todos os ouvintes de eventos desaparecerão). Depois de ler esta resposta, mudei minhas chamadas createElement para createElementNS e agora tudo funciona!d3.select('body').append('svg').attr('width','100%');
$.parseXML
.A resposta aceita mostra uma maneira muito complicada. Como Forresto afirma em sua resposta , " parece adicioná-los no explorador DOM, mas não na tela " e a razão para isso são diferentes namespaces para html e svg.
A solução mais fácil é "atualizar" svg inteiro. Após anexar o círculo (ou outros elementos), use o seguinte:
Isso faz o truque. O círculo está na tela.
Ou, se desejar, use um contêiner div:
E envolva seu svg dentro do container div:
O exemplo funcional:
http://jsbin.com/ejifab/1/edit
As vantagens desta técnica:
$('svg').prepend('<defs><marker></marker><mask></mask></defs>');
como você faz no jQuery.$("#cont").html($("#cont").html());
seus atributos, podem ser editados usando o jQuery.EDITAR:
A técnica acima funciona apenas com SVG "codificado" ou manipulado pelo DOM (= document.createElementNS etc.). Se o Raphael for usado para criar elementos, (de acordo com meus testes), a vinculação entre objetos do Raphael e o SVG DOM será interrompida se
$("#cont").html($("#cont").html());
for usada. A solução alternativa para isso é não usar$("#cont").html($("#cont").html());
nada e, em vez disso, usar documento SVG fictício.Este SVG fictício é primeiro uma representação textual do documento SVG e contém apenas os elementos necessários. Se queremos, por exemplo. Para adicionar um elemento de filtro ao documento do Raphael, o manequim pode ser algo parecido
<svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>
. A representação textual é primeiro convertida para DOM usando o método $ ("body"). Append () do jQuery. E quando o elemento (filter) está no DOM, ele pode ser consultado usando métodos jQuery padrão e anexado ao documento SVG principal criado por Raphael.Por que esse manequim é necessário? Por que não adicionar um elemento de filtro estritamente ao documento criado pelo Rafael? Se você tentar usando, por exemplo.
$("svg").append("<circle ... />")
, ele é criado como elemento html e nada está na tela, conforme descrito nas respostas. Mas se todo o documento SVG for anexado, o navegador manipulará automaticamente a conversão de namespace de todos os elementos no documento SVG.Um exemplo esclarece a técnica:
A demonstração completa dessa técnica está disponível em: http://jsbin.com/ilinan/1/edit .
(Ainda não faço ideia, por
$("#cont").html($("#cont").html());
que não funciona ao usar o Raphael. Seria um corte muito curto.)fonte
$("#cont").html($("#cont").html());
funcionou muito bem no Chrome, mas não funcionou no IE 11 para mim.A biblioteca D3, cada vez mais popular, lida muito bem com as peculiaridades de anexar / manipular svg. Você pode considerar usá-lo em oposição aos hacks do jQuery mencionados aqui.
HTML
Javascript
fonte
O JQuery não pode anexar elementos
<svg>
(parece adicioná-los no explorador DOM, mas não na tela).Uma solução alternativa é anexar um
<svg>
com todos os elementos necessários à página e modificar os atributos dos elementos usando.attr()
.http://jsfiddle.net/8FBjb/1/
fonte
<circle>
ou outros elementos individualmente, usando métodos DOM complexos e lentos (por exemplo,createDocumentFragment()
oucreateElementNS()
), anexe todo o documento svg ao container. Em vez de $ ('body'), é claro que também pode haver alguns $ ('div'). Depois disso, o documento svg está no DOM e pode ser consultado de maneira familiar usando, por exemplo. $ ('c'). attr ('preenchimento', 'vermelho').Não vi alguém mencionar esse método, mas
document.createElementNS()
é útil nesse caso.Você pode criar os elementos usando Javascript baunilha como nós DOM normais com o espaço para nome correto e, em seguida, jQuery-ify-los a partir daí. Igual a:
O único lado negativo é que você precisa criar cada elemento SVG com o espaço para nome certo individualmente ou isso não funcionará.
fonte
Encontrei uma maneira fácil que funciona com todos os navegadores que tenho (Chrome 49, Edge 25, Firefox 44, IE11, Safari 5 [Win], Safari 8 (MacOS)):
fonte
Eu posso ver um círculo no firefox, fazendo duas coisas:
1) Renomeando arquivo de html para xhtml
2) Mude o script para
fonte
Com base na resposta de @ chris-dolphin, mas usando a função auxiliar:
fonte
$svg.append($s('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'));
Se a sequência que você precisa anexar for SVG e você adicionar o espaço para nome adequado, poderá analisar a sequência como XML e anexar ao pai.
fonte
A resposta aceita por Bobince é uma solução curta e portátil. Se você não apenas anexar SVG, mas também manipulá-lo, tente a biblioteca JavaScript "Pablo" (escrevi). Isso parecerá familiar para os usuários do jQuery.
Seu exemplo de código ficaria assim:
Você também pode criar elementos SVG em tempo real, sem especificar a marcação:
fonte
Eu sugeriria que seria melhor usar o ajax e carregar o elemento svg de outra página.
Onde href é o local da página com o svg. Dessa forma, você pode evitar qualquer efeito instável que possa ocorrer ao substituir o conteúdo html. Além disso, não se esqueça de desembrulhar o svg após o carregamento:
fonte
Isso está funcionando para mim hoje com o FF 57:
Faz:
fonte
$(this).clone()
está clonando um elemento SVG (e são filhos, se houver). Olhe além do uso detext()
. Estou pegando um único tspan com "Your New" e terminando com duas colheres de chá, uma com "Your" (preto) e outra com "New" (azul com linha). Caramba, de 0 votos para -1 :-(fonte
Uma maneira muito mais simples é gerar seu SVG em uma string, criar um elemento HTML do wrapper e inserir a string svg no elemento HTML usando
$("#wrapperElement").html(svgString)
. Isso funciona muito bem no Chrome e Firefox.fonte