Як отримати доступ до елементів SVG за допомогою Javascript


83

Я возиться з SVG, і я сподівався, що зможу створити файли SVG в Illustrator і отримати доступ до елементів за допомогою Javascript.

Ось файл SVG Illustrator запускається (здається, це також додає навантаження сміття на початок файлу, який я видалив)

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

Як ви, мабуть, бачите, кожен елемент має ідентифікатор, і я сподівався мати можливість отримати доступ до окремих елементів за допомогою 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, вам потрібен хост-файл HTML на веб-сервері, як IIS, Tomcat


4
примітка щодо примітки @ jbeard4: у деяких браузерах ця політика того самого походження спричиняє необхідність використовувати сервер (навіть якщо ви використовуєте лише HTML та js [серверні сторони]), політика доступу заборонить доступ до svg.
Майкл

1
Важливо, щоб запустити цей HTML, вам потрібен хост-файл HTML для веб-сервера, як IIS, Tomcat
Hien Nguyen

Як згадував @HienNguyen, перед запуском на веб-сервері він не працював. Повернуте значення document.getElementById("alphasvg").contentDocumentбуло null.
am.rez

TL; DR: contentDocumentмости від контексту HTML до контексту SVG
Абдулл

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 Брукерт

у випадку jQuery вам краще використовувати $('#alphasvg').loadзамість $(window).load. Це дозволить вам змінювати атрибут dataна льоту
vkabachenko

Зауважте, що хоча ви можете використовувати jQuery для доступу до елементів у svg, ви не можете використовувати його для додавання елементів до svg. Дивіться stackoverflow.com/questions/3642035/…, чому.
hrabinowitz

4

Якщо ви використовуєте <img>тег для SVG, тоді ви не можете маніпулювати його вмістом (наскільки мені відомо).

Як показує прийнята відповідь, використання <object>- це варіант.

Мені це знадобилося нещодавно, і я використовував gulp-injectпід час моєї збірки ковтка, щоб вводити вміст файлу SVG безпосередньо в документ HTML як <svg>елемент, з яким потім дуже легко працювати за допомогою селекторів CSS та querySelector/ getElementBy*.


imgтег корисний для великого завантаження SVG ... Щоб використовувати складний (та інтерактивний!) SVG, краще використовувати D3js , тобто як простий jQuery, що спеціалізується на маніпулюванні даними SVG + DOM +.
Пітер Краус
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.