Javascript로 SVG 요소에 액세스하는 방법


83

저는 SVG를 엉망으로 만들고 있으며 Illustrator에서 SVG 파일을 만들고 Javascript로 요소에 액세스 할 수 있기를 바랐습니다.

다음은 Illustrator에서 시작되는 SVG 파일입니다 (제거한 파일의 시작 부분에 정크 파일을 추가하는 것 같습니다).

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="276.843px" height="233.242px" viewBox="0 0 276.843 233.242" enable-background="new 0 0 276.843 233.242"
     xml:space="preserve">
<path id="delta" fill="#231F20" d="M34.074,86.094L0,185.354l44.444,38.519l80.741-0.74l29.63-25.186l-26.667-37.037
    c0,0-34.815-5.926-37.778-6.667s-13.333-28.889-13.333-28.889l7.407-18.519l31.111-2.963l5.926-21.481l-12.593-38.519l-43.704-5.185
    L34.074,86.094z"/>
<path id="cargo" fill="#DFB800" d="M68.148,32.761l43.704,4.445l14.815,42.963l-7.407,26.667l-33.333,2.963l-4.444,14.074
    l54.074-1.481l22.222,36.296l25.926-3.704l25.926-54.074c0,0-19.259-47.408-21.481-47.408s-31.852-0.741-31.852-0.741
    l-19.259-39.259L92.593,8.316L68.148,32.761z"/>
<polygon id="beta" fill="#35FF1F" points="86.722,128.316 134.593,124.613 158.296,163.872 190.889,155.724 214.593,100.909 
    194.593,52.02 227.186,49.057 246.444,92.02 238.297,140.909 216.074,172.761 197.556,188.316 179.778,169.798 164.963,174.983 
    163.481,197.946 156.815,197.946 134.593,159.428 94.593,151.279 "/>
<path class="monkey" id="alpha" fill="#FD00FF" d="M96.315,4.354l42.963,5.185l18.519,42.222l71.852-8.148l20.74,46.667l-5.926,52.593
    l-24.444,34.074l-25.185,15.555l-14.074-19.259l-8.889,2.964l-1.481,22.222l-14.074,2.963l-25.186,22.963l-74.074,4.444
    l101.481,4.444c0,0,96.297-17.777,109.63-71.852S282.24,53.983,250.389,20.65S96.315,4.354,96.315,4.354z"/>
</svg>

보시다시피 각 요소에는 ID가 있으며 Javascript로 개별 요소에 액세스하여 Fill 속성을 변경하고 클릭과 같은 이벤트에 응답 할 수 있기를 바랐습니다.

HTML은 기본입니다.

<!DOCTYPE html>
<html>
    <head>
        <title>SVG Illustrator Test</title> 
    </head>
    <body>

        <object data="alpha.svg" type="image/svg+xml" id="alphasvg" width="100%" height="100%"></object>

    </body>
</html>

나는 이것이 정말로 두 가지 질문이라고 생각합니다.

  1. Raphael 또는 jQuery SVG와 같은 것을 사용하는 것과는 반대로 이렇게 할 수 있습니까?

  2. 가능하다면 기술은 무엇입니까?


최신 정보

지금은 Illustrator를 사용하여 SVG 파일 을 만들고 Raphaël JS 를 사용하여 경로를 만들고 단순히 SVG 파일에서 포인트 데이터를 복사하여 path()함수에 붙여넣고 있습니다. 포인트 데이터를 수동으로 코딩하여지도에 필요할 수있는 복잡한 경로를 만드는 것은 (내가 아는 한) 엄청나게 복잡합니다.

답변:


113

Raphael 또는 jQuery SVG와 같은 것을 사용하는 것과는 반대로 이런 식으로 할 수 있습니까?

명확히.

가능하다면 기술은 무엇입니까?

이 주석 코드 조각은 다음과 같이 작동합니다.

<!DOCTYPE html>
<html>
    <head>
        <title>SVG Illustrator Test</title> 
    </head>
    <body>

        <object data="alpha.svg" type="image/svg+xml"
         id="alphasvg" width="100%" height="100%"></object>

        <script>
            var a = document.getElementById("alphasvg");

            // It's important to add an load event listener to the object,
            // as it will load the svg doc asynchronously
            a.addEventListener("load",function(){

                // get the inner DOM of alpha.svg
                var svgDoc = a.contentDocument;
                // get the inner element by id
                var delta = svgDoc.getElementById("delta");
                // add behaviour
                delta.addEventListener("mousedown",function(){
                        alert('hello world!')
                }, false);
            }, false);
        </script>
    </body>
</html>

이 기술의 한계는 동일 출처 정책에 의해 제한되므로 파일 alpha.svg과 동일한 도메인에서 호스팅되어야 .html합니다. 그렇지 않으면 객체의 내부 DOM에 액세스 할 수 없습니다.

이 HTML을 실행하기 위해 중요한 것은 IIS, Tomcat과 같은 웹 서버에 호스트 HTML 파일이 필요합니다.


4
@ jbeard4의 참고 사항 : 일부 브라우저에서이 동일 출처 정책은 서버를 사용해야하는 결과를 가져옵니다 (코드가 html 및 js [서버 측] 만 사용하는 경우에도) 액세스 정책은 svg에 대한 액세스를 차단합니다.
Michael

1
중요한 것은이 HTML을 실행하려면 IIS, 톰캣 등의 웹 서버에 호스트 HTML 파일이 필요합니다
히엔 응우 엔

@HienNguyen이 언급했듯이 웹 서버에서 실행하기 전에 작동하지 않았습니다. 에 대해 반환 된 값 document.getElementById("alphasvg").contentDocumentnull입니다.
am.rez


19

jQuery를 사용하는 경우 $(window).load에는 포함 된 SVG 문서가 아직로드되지 않았을 수 있으므로 기다려야합니다 .$(document).ready

$(window).load(function () {

    //alert("Document loaded, including graphics and embedded documents (like SVG)");
    var a = document.getElementById("alphasvg");

    //get the inner DOM of alpha.svg
    var svgDoc = a.contentDocument;

    //get the inner element by id
    var delta = svgDoc.getElementById("delta");
    delta.addEventListener("mousedown", function(){ alert('hello world!')}, false);
});

3
이 코드를 사용하는 동안이 다른 답변이 유용한 보완 도구가 될 수 있습니다. stackoverflow.com/a/5990945/1515819
Stéphane Bruckert 2013

jQuery를하는 경우에 당신은 더 나은 사용하십시오 $('#alphasvg').load대신을 $(window).load. 이것은 당신이 속성을 변경할 수 있습니다 data즉시
vkabachenko

jQuery를 사용하여 svg 내의 요소에 액세스 할 수 있지만이를 사용하여 svg에 요소를 추가 할 수는 없습니다. 그 이유는 stackoverflow.com/questions/3642035/… 를 참조하십시오 .
hrabinowitz

4

<img>SVG에 태그를 사용하는 경우 해당 내용을 조작 할 수 없습니다 (내가 아는 한).

수락 된 답변에서 알 수 있듯이 사용 <object>은 옵션입니다.

나는 최근에 이것을 필요 gulp-inject로했으며 SVG 파일의 내용을 HTML 문서에 <svg>요소 로 직접 삽입하기 위해 gulp 빌드 중에 사용 했습니다. 그러면 CSS 선택기 및 querySelector/ 를 사용하여 작업하기가 매우 쉽습니다 getElementBy*.


img태그는 큰 SVG로드에 유용합니다. 복잡한 (및 대화 형!) SVG를 사용하려면 SVG + DOM + 데이터 조작에 특화된 간단한 jQuery와 같은 D3js 를 사용하는 것이 좋습니다 .
Peter Krauss
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.