2016-12-23 76 views
8

Próbuję załadować zewnętrzny plik SVG, a następnie napisać na nim dodatkowe elementy SVG. Kiedy to zrobię, pojawia się błąd "Nie można wykonać" appendChild "w" węźle ": dozwolony jest tylko jeden element na dokumencie." kiedy sprawdzam w Chrome.Nie można wykonać "appendChild" w "węźle": dozwolony jest tylko jeden element na dokumencie

Oto HTML:

<html> 
    <head> 
    <link rel="stylesheet" type="text/css" href="css/index.css"> 
    <title>Hello World</title> 
    </head> 
    <body> 
     <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="mySvg"> 
     <circle cx="40" cy="30" r="15" fill="#FF00FF" 
      stroke="#000000" stroke-width="2" /> 
     </svg> 
     <object data="img/drawing.svg" type="image/svg+xml" 
     align="center" id="svgDrw" height="80vh"></object> 
    <script type="text/javascript" src="js/problem.js"></script> 
    </body> 
</html> 

Oto problem.js:

var svgXtraDoc; 
var d = document.getElementById("svgDrw"); 

d.addEventListener("load",function(){ 

    // get the inner DOM 
    svgXtraDoc = d.contentDocument; 
    // get the inner element by id 
    svgRect1 = svgXtraDoc.getElementById("MyRect1"); 
    svgRect2 = svgXtraDoc.getElementById("MyRect2"); 
}, false); 


function addRect() { 
    var svgRect = document.createElementNS("http://www.w3.org/2000/svg", 
    "rect"); 
    svgRect.setAttribute("x", 100); 
    svgRect.setAttribute("y", 100); 
    svgRect.setAttribute("width", 100); 
    svgRect.setAttribute("height", 100); 
    svgRect.style.fill = "red"; 
    // mySvg.appendChild(svgRect); 
    svgXtraDoc.appendChild(svgRect); 
} 

document.getElementById("mySvg").addEventListener("click", addRect); 

... i oto drawing.svg, pozbawiony niektórych cruft Inkscapy:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<!-- Created with Inkscape (http://www.inkscape.org/) --> 

<svg 
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:cc="http://creativecommons.org/ns#" 
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
    xmlns:svg="http://www.w3.org/2000/svg" 
    xmlns="http://www.w3.org/2000/svg" 
    width="29.02857mm" 
    height="37.092064mm" 
    viewBox="0 0 102.85714 131.42857" 
    id="svg2" 
    version="1.1"> 
    <g 
    id="layer1" 
    transform="translate(-205.71428,-218.07649)"> 
    <rect 
     style="stroke:none;fill-opacity:1;fill:#5eb056" 
     id="MyRect1" 
     width="102.85714" 
     height="131.42857" 
     x="205.71428" 
     y="218.07649" /> 
    <rect 
     style="fill:#000000;stroke:none;fill-opacity:1" 
     id="MyRect2" 
     width="42.857143" 
     height="65.714287" 
     x="231.42857" 
     y="252.3622" /> 
    </g> 
</svg> 

Błąd pojawia się po kliknięciu na kółko: prostokąt, który powinien pojawić się wewnątrz importowanego rysunku za pomocą dwóch prostokątów nie pojawia się, a komunikat o błędzie "Nie można wykonać" appendChild "w" węźle ": dozwolony jest tylko jeden element na dokumencie." jest wyświetlany w konsoli.

Jeśli zmienię to, aby prostokąt został dodany do svg zawierającego okrąg, tj. Przez odkomentowanie linii "// mySvg.appendChild (svgRect);", wówczas prostokąt pojawi się z powodzeniem.

Wiem również, że plik rysunku został pomyślnie załadowany, ponieważ w innym kodzie (nie uwzględnionym tutaj ze względu na zwięzłość) mogę zmienić kolory prostokątów w tym pliku. Wygląda więc na to, że mogę uzyskać dostęp do istniejących elementów w pliku, ale nie dodawać elementów.

Czy jest coś związanego z zewnętrznie ładowanymi plikami SVG w porównaniu z liniowymi SVG, których nie uwzględniam?

Ostatnia rzecz - to wchodzi do aplikacji Cordova, więc chciałbym, aby było małe, więc preferowane są czyste rozwiązania JavaScript. Jeśli chcę, użyję JQuery lub SnapSVG, ale wydaje mi się, że moje potrzeby są na tyle proste, że powinno to być możliwe bez zewnętrznych bibliotek.

+0

Właśnie opracowałem sposób obejścia mojego problemu - chcę dodać kręgi wskazujące lokalizacje zdarzeń, więc mogę po prostu umieścić je w oryginalnym pliku z obrysem i wypełnieniem ustawionym na brak, a następnie uczynić je widocznymi we właściwym czasie, zamiast faktycznie tworzyć i dodawać je kiedy wydarzenie się wydarzy. Nadal byłbym zainteresowany odpowiedzią na zadane pytanie. –

Odpowiedz

10

Istnieje różnica między węzłem głównym dokumentu a elementem dokumentu. To, czego potrzebujesz, to element dokumentu <svg>, ale .contentDocument dostaje ci węzeł główny.

Węzeł główny jest o jeden poziom wyżej hierarchii. Oznacza to, że element dokumentowy <svg> znajduje się wewnątrz węzła głównego, a węzeł główny może mieć tylko ten jeden element podrzędny: <svg>.

Aby uzyskać dokument element, to zrobić:

svgXtraDoc = d.contentDocument.documentElement; 
+0

Działa idealnie, bardzo dziękuję! –

+0

Bardzo dziękuję! – jojojohn

1

W moim przypadku, DOM narzekał, bo starałem się dodać dziecku w dokumencie samego:

document.appendChild(myElement); 

Rozwiązałem go, uzyskując odniesienie do znacznika body:

document.body.appendChild(logger);