2010-07-27 19 views
10

Standard SVG umożliwia używanie zewnętrznych plików SVG i odnoszenie się do nich.Uzyskiwanie dostępu do obiektu DOM zdefiniowanego w zewnętrznym pliku SVG

Mam plik circle.svg, który definiuje obiekt okręgu o identyfikatorze "the_circle". Z głównego pliku SVG mogę dołączyć ten okrąg i ożywić go, używając SVG linking.

Chciałbym również uzyskać dostęp do tego samego obiektu okręgu za pośrednictwem javascript, w jaki sposób mogę to zrobić? Jaki jest odpowiednik javascript na xlink:href="url(#the_image)#the_circle"?

Korzystanie z document.getElementById('the_image') Mogę uzyskać dostęp tylko do SVGImageElement, ale nie obiektów zdefiniowanych w załączonym SVG.

<?xml version="1.0" standalone="no"?> 
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg width="100%" height="100%" version="1.1" 
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" > 

    <image 
    id="the_image" 
    x="0" y="0" width="100%" height="100%" 
    xlink:href="circle.svg" /> 

    <animateTransform  
    xlink:href="url(#the_image)#the_circle" 

    attributeName="transform" attributeType="XML" 
    type="translate" 
    from="0" to="25" 
    dur="1s" repeatCount="indefinite" 
    additive="replace" fill="freeze" /> 
</svg> 
+0

Wysłany samo pytanie w SVG programistów http://tech.groups.yahoo.com/group/svg-developers/message/63940 – rodrigob

Odpowiedz

13

Wygląda na to, że "właściwym" sposobem byłoby użycie elementu SVG "use", a nie obrazu. Powodem tego jest to, że interfejs DOM elementu używanego do SVG określa właściwość "instanceRoot", która pozwala uzyskać katalog główny "drzewa instancji" odpowiadającego temu elementowi użycia: http://www.w3.org/TR/SVG/struct.html#InterfaceSVGUseElement

Więc, skończyłbyś z roztworu, który wygląda mniej więcej tak: circle.svg:

<?xml version="1.0" standalone="no"?> 
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg width="4in" height="4in" id="the_svg" 
    viewBox="0 0 4 4" version="1.1" 
    xmlns="http://www.w3.org/2000/svg"> 
    <circle r="1" fill="blue" stroke="none" id="the_circle"/> 
</svg> 

dokument, który korzysta z węzła głównego SVG z circle.svg:

<?xml version="1.0" standalone="no"?> 
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg width="100%" height="100%" id="foo" 
    version="1.1" 
    xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"> 

    <use xlink:href="circle.svg#the_svg"/> 
</svg> 

Niestety, chociaż, podczas gdy Firefox obsługuje u se elementu użycia z zewnętrznymi dokumentami, obecnie występuje błąd w pakiecie Webkit, który na to nie pozwala: https://bugs.webkit.org/show_bug.cgi?id=12499

Ponadto, wydaje się, że Firefox nie implementuje właściwości instanceRoot dla elementów użytkujących.

Wygląda na to, że konieczne może być obejście ograniczeń bieżących implementacji SVG. Sposób, w jaki zaleciłbym to, to użycie XMLHttpRequest, aby pobrać dokument, do którego chciałbyś się połączyć, i zaimportować DOM pobranego dokumentu do DOM twojego dokumentu hosta. Poniższy kod realizuje to i działa w Firefox, Opera i chrom:

<?xml version="1.0" standalone="no"?> 
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg width="100%" height="100%" id="foo" 
    version="1.1" 
    xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"> 

    <script> 
    function fetchXML (url, callback) { 
     var xhr = new XMLHttpRequest(); 
     xhr.open('GET', url, true); 
     xhr.onreadystatechange = function (evt) { 
     //Do not explicitly handle errors, those should be 
     //visible via console output in the browser. 
     if (xhr.readyState === 4) { 
      callback(xhr.responseXML); 
     } 
     }; 
     xhr.send(null); 
    }; 

    //fetch the document 
    fetchXML("http://localhost:8082/tmp/circle.svg",function(newSVGDoc){ 
     //import it into the current DOM 
     var n = document.importNode(newSVGDoc.documentElement,true); 
     document.documentElement.appendChild(n); 

     var circle = document.getElementById("the_circle"); //now you have the circle 
    }) 
    </script> 
</svg> 
+0

Dzięki za odpowiedź! – rodrigob

+0

XHR ... genialny. – Duke

+0

To jest dokładnie to, czego szukałem!Inne próby pobrania SVG przez XHR i dołączenia go do DOM nie powiodły się. Dzięki! –

1

celu uzupełnienia @ Echo-Flow doskonałe rozwiązanie z kodem w jQuery/coffeescript:

$.get '/assets/hexagon.svg', (svgFileData)-> 
    svgTag = svgFileData.documentElement 
    $('body').append(svgTag) 
    circle = $('#the_circle') 
+0

Nie zapomnij zaimportować węzła za pomocą document.importNode. Może narzekać, jeśli tego nie zrobisz. – jbeard4

11

można uzyskać dostęp do konieczności Element nieco łatwiejsze:

document.getElementById('the_image').contentDocument.getElementById('the_circle') 

Zobacz this image odsyłające (podjęte na dev.opera.com) enter image description here

+0

Fajnie, ale jaki jest haczyk? Zakładam, że działa to tylko w przypadku SVG zawartych w tej samej domenie? – joeytwiddle

+0

I co z tego? Zasadniczo chcesz manipulować plikiem, a nie plikiem z innej strony. –

+0

Przyjmę to jako "tak"; po prostu dobrze, aby było jasne. Zgadzam się, że często jest tak samo w tej samej dziedzinie, co sprawia, że ​​inne odpowiedzi są raczej przesadne, chyba że potrzebne jest ogólne rozwiązanie. – joeytwiddle

Powiązane problemy