jquery append no funciona con svg elemento?

Asumiendo este:

<html>
<head>
 <script type="text/javascript" src="jquery.js"></script>
 <script type="text/javascript">
 $(document).ready(function(){
  $("svg").append('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>');
 });
 </script>
</head>
<body>
 <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px">
 </svg>
</body>

Por qué no puedo ver nada?

Que navegador ?

OriginalEl autor | 2010-09-04

13 Kommentare

  1. 225

    Cuando se pasa una cadena de marcado en $, se analiza como HTML utilizando el navegador innerHTML propiedad en un <div> (o en otro recipiente apropiado para casos especiales como <tr>). innerHTML no se puede analizar SVG o no el contenido HTML, y aunque se pudiera no ser capaz de decir que <circle> iba a ser en el SVG espacio de nombres.

    innerHTML no está disponible en SVGElement—es una propiedad de HTMLElement sólo. Tampoco existe en la actualidad un innerSVG de propiedad o de otra forma(*) para analizar el contenido en un SVGElement. Por esta razón, usted debe utilizar DOM estilo de métodos. jQuery no le da el acceso fácil a los nombres de espacios de los métodos necesarios para crear elementos SVG. Realmente jQuery no está diseñado para su uso con SVG a todos y muchas operaciones pueden fallar.

    HTML5 promete para permitir el uso de <svg> sin un xmlns dentro de un HTML sin formato (text/html) documento en el futuro. Pero esto es sólo un analizador de hack(**), el contenido SVG todavía será SVGElements en el SVG espacio de nombres, y no HTMLElements, así que usted no será capaz de utilizar innerHTML aunque mirada como parte de un documento HTML.

    Sin embargo, para los navegadores actuales debe utilizar XHTML (correctamente sirvió como application/xhtml+xml; guardar con el .xhtml extensión de archivo para pruebas locales) para obtener SVG a trabajar. (Tiene algo de sentido, de todos modos; SVG es una correctamente basado en XML estándar.) Esto significa que usted tendría que escapar de la < símbolos en el interior de su bloque de secuencia de comandos (o encerrar en una sección CDATA), e incluyen el XHTML xmlns declaración. ejemplo:

    <!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>

    *: bueno, hay de DOM Nivel 3 LS la parseWithContext, pero el soporte de los navegadores es muy pobre. Editar para agregar: sin embargo, mientras que usted no puede inyectar marcado en una SVGElement, usted podría inyectar un nuevo SVGElement en un HTMLElement utilizando innerHTML, para luego transferirlo a la meta deseada. Es probable que ser un poco más lento, aunque:

    <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>

    **: No me gusta la forma en que los autores de HTML5 parecen tener miedo de XML y decididos a calzador XML-funciones basadas en la crufty lío que es HTML. XHTML resuelto estos problemas de años atrás.

    Esta respuesta es todavía relevante! Yo sólo tenía un extraño error en el que agrega elementos a mostrar en el elemento Cromo inspector, pero no iba a representar. Si me RMB>edit as html en la etiqueta html y pulsa enter de todo lo que se muestra (pero todos los detectores de eventos desaparecer). Después de leer esta respuesta he cambiado mi createElement llamadas a createElementNS y ahora todo funciona bien!
    Puede manipular el SVG elementos con jquery una vez que se crean utilizando el método DOM createElementNS. Usted puede cambiar el makeSVG función ‘return $(el)’, y ahora usted tiene un svg elemento que puede utilizar métodos jquery.
    Ah! Así que ¿por qué no funciona. He intentado lo mismo con dos bibliotecas, una en jQuery y una en D3.js. Tengo exactamente de la misma fuente de salida en HTML utilizando tanto, pero el jQuery elementos generados no pronuncia mientras que el D3-generadas hizo! Recomiendo el uso de D3: d3.select('body').append('svg').attr('width','100%');
    DOM Nivel 3 LS nunca se ha hecho en los navegadores. El original-Mozilla-sólo DOMParser es ahora más ampliamente apoyado, sin embargo, y jQuery ha $.parseXML.
    Todavía es relevante. bobince odia el desorden de HTML5, odio el desorden de toda la web, ya que en ninguna parte se puede encontrar un buen código sin hacks porque de ese lío. WWW debería cambiar el nombre a WWM World Wide Lío.

    OriginalEl autor bobince

  2. 130

    La aceptado respuesta muestra demasiado complicada. Como Forresto reclamaciones en su respuesta, «parece a añadir en la DOM explorer, pero no en la pantalla» y la razón de esto es espacios de nombres diferentes para html y svg.

    La solución más sencilla es «actualizar» todo svg. Después de anexar círculo (u otros elementos), el uso de este:

    $("body").html($("body").html());

    Esto hace el truco. El círculo está en la pantalla.

    O si quieres, usar un div contenedor:

    $("#cont").html($("#cont").html());

    Y envolver su svg dentro de div de contenedor:

    <div id="cont">
        <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px">
        </svg>
    </div>

    El ejemplo funcional:

    http://jsbin.com/ejifab/1/edit

    Las ventajas de esta técnica:

    • puede editar los existentes svg (que ya está en DOM), por ejemplo. creado usando Raphael o como en tu ejemplo «codificados» sin secuencias de comandos.
    • puede agregar elementos complejos de las estructuras de las cadenas, por ejemplo. $('svg').prepend('<defs><marker></marker><mask></mask></defs>'); como en jQuery.
    • después de que los elementos se anexa y hace visible en la pantalla usando $("#cont").html($("#cont").html()); sus atributos pueden ser editadas usando jQuery.

    EDICIÓN:

    La técnica anterior funciona con «codificado» o DOM manipulados ( = documento.createElementNS etc.) SVG sólo. Si Rafael es utilizado para la creación de elementos, (según mis pruebas) la vinculación entre Raphael y objetos SVG DOM se rompe si $("#cont").html($("#cont").html()); se utiliza. La solución a esto no es para uso $("#cont").html($("#cont").html()); en todo y en lugar de utilizar ficticio documento SVG.

    Este maniquí SVG es en primer lugar una representación textual del documento SVG y contiene sólo los elementos que son necesarios. Si queremos, por ejemplo. para agregar un elemento de filtro de Rafael documento, el maniquí podría ser algo como <svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>. La representación textual se convierte primero a DOM con jQuery $(«body»).método append (). Y cuando el (filtro) es el elemento en el DOM, se puede consultar utilizando el estándar métodos jQuery y anexa a la principal documento SVG que es creado por Raphael.

    Por qué este maniquí es necesario? Por qué no añadir un elemento de filtro estrictamente a Rafael documento creado? Si usted lo intente usando, por ejemplo. $("svg").append("<circle ... />"), se crea como elemento de html y no hay nada en la pantalla, como se describe en las respuestas. Pero si todo el documento SVG se adjunta a continuación, el navegador se encarga automáticamente el espacio de nombres de la conversión de todos los elementos en el documento SVG.

    Un ejemplo ilumine la técnica:

    //Add Raphael SVG document to container element
    var p = Raphael("cont", 200, 200);
    //Add id for easy access
    $(p.canvas).attr("id","p");
    //Textual representation of element(s) to be added
    var f = '<filter id="myfilter"><!-- filter definitions --></filter>';
    
    //Create dummy svg with filter definition 
    $("body").append('<svg id="dummy" style="display:none"><defs>' + f + '</defs></svg>');
    //Append filter definition to Raphael created svg
    $("#p defs").append($("#dummy filter"));
    //Remove dummy
    $("#dummy").remove();
    
    //Now we can create Raphael objects and add filters to them:
    var r = p.rect(10,10,100,100);
    $(r.node).attr("filter","url(#myfilter)");

    Demo de esta técnica está aquí: http://jsbin.com/ilinan/1/edit.

    ( Tengo (aún) no hay idea, por qué $("#cont").html($("#cont").html()); no funciona cuando se usa Raphael. Sería muy corto hack. )

    Gracias, tu manera de acercarse demasiado trabajado.
    Estoy usando mi (hecho en Casa) solución para el manejo de SVG y tengo el mismo Problema como Raphael, cuando se utiliza el «reparsing truco» $(#imagen).html … pero mi solución fue volver a init algunos caché SVG elementos (marcado rectángulo, transformataion y así sucesivamente)
    Eres un asistente. Yo estaba mirando el aceptado contestar y me fue como el hombre, esto va a ser un dolor de cabeza. Entonces, vi esto y hace todo lo que se necesita en una línea corta. Gracias!
    ESTO que ME ESTABA CAUSANDO A PERDER MI CANICAS… pensé que podía por arte de magia el uso de js DOM olmos en el SVG espacio de nombres como uno podría pensar… tengo el inspector de etiquetas para reconocer las inserciones… pero no dados hasta ahora!
    Trabajó mucho para mí cuando anexar mi polígono existente y la ruta de acceso etiquetas a un recién creado padre svg etiqueta. Gracias!

    OriginalEl autor Timo Kähkönen

  3. 35

    El cada vez más popular D3 biblioteca se encarga de las rarezas de anexar/manipulación de svg muy bien. Puede que desee considerar la posibilidad de su uso en lugar de la de jQuery hacks que se mencionan aquí.

    HTML

    <svg xmlns="http://www.w3.org/2000/svg"></svg>

    Javascript

    var circle = d3.select("svg").append("circle")
        .attr("r", "10")
        .attr("style", "fill:white;stroke:black;stroke-width:5");
    bonita respuesta. me ayudó para algunos la cuestión aquí.
    jQuery también se ahoga en configuración/recibiendo clases de SVG así. Sólo de un lado.
    Gracias! Bonita respuesta!

    OriginalEl autor nategood

  4. 23

    JQuery no puede anexar elementos para <svg> (se parece a añadir en la DOM explorer, pero no en la pantalla).

    Una solución es añadir un <svg> con todos los elementos que usted necesita a la página y, a continuación, modificar los atributos de los elementos mediante .attr().

    $('body')
      .append($('<svg><circle id="c" cx="10" cy="10" r="10" fill="green" /></svg>'))
      .mousemove( function (e) {
          $("#c").attr({
              cx: e.pageX,
              cy: e.pageY
          });
      });

    http://jsfiddle.net/8FBjb/1/

    Gracias, me ayudó mucho! Este es un muy buen enfoque. En lugar de anexar <circle> ni de otros elementos en forma individual utilizando complejos y lentos DOM-métodos (por ejemplo. createDocumentFragment() o createElementNS()), anexar todo el documento svg al contenedor. En lugar de $(‘body’) puede ser, por supuesto, unos $(‘div’). Y después de que el documento svg es en DOM y pueden ser consultados en forma familiar utilizando, por ejemplo. $(‘c’).attr(‘relleno’,’rojo’).
    He hecho un ejemplo adicional de este: jsbin.com/inevaz/1 . Se pone de tigre.svg fuente de código de internet para iframe y se pueden Copiar y Pegar a textarea. El contenido del textarea se utiliza como una fuente de línea svg que es accesible a través de DOM (para cambiar el estilo de trazo).
    Esto es genial, no sé por qué todo el mundo está de votación para aquellas otras respuestas que simplemente no funcionan.
    Esta fue la mejor respuesta para mí también. Necesitaba un svg con un <usar xlink:href=»#icono de»> y esta fue la más corta de trabajo de respuesta.

    OriginalEl autor forresto

  5. 11

    No he visto a alguien hablar de este método, pero document.createElementNS() es útil en este caso.

    Puede crear los elementos mediante Javascript como normal nodos DOM con el espacio de nombres correcto y, a continuación, jQuery-a ellos desde allí. Así:

    var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
        circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
    
    var $circle = $(circle).attr({ //All your attributes });
    
    $(svg).append($circle);

    El único inconveniente es que tienes que crear cada elemento SVG con el derecho del espacio de nombres de forma individual o no funcionará.

    Timo de la respuesta (la parte superior votado) trabajó en Chrome, pero no IE. Esta respuesta resuelto el problema tanto para los navegadores!
    Bueno! Es bueno saberlo

    OriginalEl autor Chris Dolphin

  6. 7

    Puedo ver círculo en firefox, haciendo 2 cosas:

    1) cambiar el nombre de archivo de html a xhtml

    2) Cambio de la secuencia de comandos para

    <script type="text/javascript">
    $(document).ready(function(){
        var obj = document.createElementNS("http://www.w3.org/2000/svg", "circle");
        obj.setAttributeNS(null, "cx", 100);
        obj.setAttributeNS(null, "cy", 50);
        obj.setAttributeNS(null, "r",  40);
        obj.setAttributeNS(null, "stroke", "black");
        obj.setAttributeNS(null, "stroke-width", 2);
        obj.setAttributeNS(null, "fill", "red");
        $("svg")[0].appendChild(obj);
    });
    </script>

    OriginalEl autor Topera

  7. 5

    Basa en @chris-delfín ‘s respuesta pero el uso de la función auxiliar:

    //Creates svg element, returned as jQuery object
    function $s(elem) {
      return $(document.createElementNS('http://www.w3.org/2000/svg', elem));
    }
    
    var $svg = $s("svg");
    var $circle = $s("circle").attr({...});
    $svg.append($circle);
    Por supuesto, usted puede también hacer: $svg.append($s('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'));

    OriginalEl autor Jonas Berlin

  8. 4

    Si la cadena que necesita para anexar SVG y agregar el adecuado espacio de nombres, se puede analizar la cadena con formato XML y anexar a los padres.

    var xml = jQuery.parseXML('<circle xmlns="http://www.w3.org/2000/svg" cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>');
    $("svg").append(xml.documentElement))

    OriginalEl autor jdesjean

  9. 3

    La aceptó responder por Bobince es un corto, la solución portátil. Si usted necesita, no sólo para anexar SVG, sino también manipular, usted podría tratar de la Biblioteca de JavaScript «Pablo» (lo escribí). Se sentirá familiarizado a jQuery los usuarios.

    Su ejemplo de código podría ser algo como:

    $(document).ready(function(){
        Pablo("svg").append('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>');
    });

    También puede crear SVG elementos sobre la marcha, sin especificar marcado:

    var circle = Pablo.circle({
        cx:100,
        cy:50,
        r:40
    }).appendTo('svg');

    OriginalEl autor Premasagar

  10. 1

    Yo sugeriría que podría ser mejor usar ajax y cargar el elemento svg desde otra página.

    $('.container').load(href + ' .svg_element');

    Donde href es la ubicación de la página con el formato svg. De esta manera usted puede evitar cualquier trémulo efectos que podrían producirse a partir de la sustitución del contenido html. También, no olvides desenvuelva el svg después de que se haya cargado:

    $('.svg_element').unwrap();

    OriginalEl autor Dan185

  11. 0
     var svg; //if you have variable declared and not assigned value.
     //then you make a mistake by appending elements to that before creating element    
     svg.appendChild(document.createElement("g"));
     //at some point you assign to svg
     svg = document.createElementNS('http://www.w3.org/2000/svg', "svg")
     //then you put it in DOM
     document.getElementById("myDiv").appendChild(svg)
     //it wont render unless you manually change myDiv DOM with DevTools
    
    //to fix assign before you append
    var svg = createElement("svg", [
        ["version", "1.2"],
        ["xmlns:xlink", "http://www.w3.org/1999/xlink"],
        ["aria-labelledby", "title"],
        ["role", "img"],
        ["class", "graph"]
    ]);
    function createElement(tag, attributeArr) {
          //.createElementNS  NS is must! Does not draw without
          let elem = document.createElementNS('http://www.w3.org/2000/svg', tag);             
          attributeArr.forEach(element => elem.setAttribute(element[0], element[1]));
          return elem;
    }
    //extra: <circle> for example requires attributes to render. Check if missing.

    OriginalEl autor 4baad4

  12. -1

    Esto me está funcionando hoy en día con FF 57:

    function () {
        //JQuery, today, doesn't play well with adding SVG elements - tricks required
        $(selector_to_node_in_svg_doc).parent().prepend($(this).clone().text("Your"));
        $(selector_to_node_in_svg_doc).text("New").attr("x", "340").text("New")
            .attr('stroke', 'blue').attr("style", "text-decoration: line-through");
    }

    Hace:

    jquery append no funciona con svg elemento?

    Que no SVG elementos que estamos añadiendo, que el contenido del texto.
    Que puede ser, pero prestados después de carga de la página inicial de estáticamente en línea SVG.
    Entonces, ¿qué, no es la pregunta, que es sobre svg elementos y no el contenido del texto.
    $(this).clone() es la clonación de un elemento SVG (y a sus hijos si es que había alguno). Mirar más allá de la utilización de text(). Me estoy tomando un solo tspan que tenía «el Nuevo», y terminando con dos tspans, uno con «Su» (negro) y uno con el «Nuevo» (azul w/ line-through). Por dios, hacia abajo a partir de la 0 votos a -1 🙁

    OriginalEl autor paul_h

  13. -1

    Una manera mucho más sencilla es simplemente generar el archivo SVG en una cadena de texto, crear un contenedor elemento HTML e insertar el svg cadena en el elemento HTML utilizando $("#wrapperElement").html(svgString). Esto funciona bien en Chrome y Firefox.

    no trabajo para mí, traté de este par de veces

    OriginalEl autor Jakob Jenkov

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea