Определить, когда встроенный SVG загружен с Angular - PullRequest
0 голосов
/ 21 ноября 2018

Я долго боролся с этим, многие старые посты решают эту проблему, но неполными, косвенными или устаревшими способами.Это такая общая проблема, общее решение было бы идеальным.Я не могу / не должен изменять SVG.У svg есть идентификатор, и у всех различных групп есть идентификаторы, с которыми мне нужно взаимодействовать.

Проблема в том, что я не могу назначить событие загрузки для самого элемента svg, потому что он еще не загружен, когда мой контроллер работает;И если я назначу событие on load родительскому тегу embed, то я не смогу получить доступ к элементам через getElementByID, потому что они еще не загружены.

View:

<div style="width:1000px" ng-controller="Controller">
    <embed id="svgObject" width="100%" height="100%" ng-src="{{modelSVG}}" type="image/svg+xml"></embed>
</div>

Контроллер:

   .controller('HomeController',['BaseController','$scope','$location',function (BaseController,scope,location) {
            scope.modelSVG = location.protocol() + '://' + location.host() + '/svg/pic.svg';
            var svgObject = document.getElementById("svgObject");

            svgObject.addEventListener('load', function(){
                var svgDocument = svgObject.contentDocument;
                **Do lots of stuff to EACH and every shape loadeded (e.g. show/hide, set hover/click events, etc
            })
   }])

Еще одна попытка получить настоящий документ svg

var svgDocument = svgObject.contentDocument ? svgObject.contentDocument : svgObject.contentWindow.document;

Не могу поверить, что это так сложно.

1 Ответ

0 голосов
/ 22 ноября 2018

Это, безусловно, самое красивое и лучшее решение, которое я нашел, которое не требует большого количества кода.По сути, мы получаем файл svg и анализируем его как фрагмент документа, чтобы все добавлялось в DOM (очевидно и магически), затем присваиваем результат обратно исходному div и затем можем получить доступ к директиве svg по id.

Вид:

<div style="width:1000px" ng-controller="Controller">
    <div id="svgObject" style="width: 600px; height: 600px;"></div>
</div>

Контроллер:

.controller('HomeController',['BaseController','$scope','$location',function (BaseController,scope,location) {
            scope.modelSVG = location.protocol() + '://' + location.host() + '/svg/pic.svg';
            http({
               method : "GET",
               url : scope.svgPath
            }).then(function mySuccess(response) {
               var svgObject = document.getElementById('svgObject');
               svgObject.appendChild(parseSVG(response.data));

               var svgDocument = document.getElementById("svgDocument");//the id of the actual svg tag.
               //do anything to fully loaded svg
            }, function myError(response) {
                alert(response.statusText);
            });

Магическая функция:

function parseSVG(svg) {
    var div= document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
    div.innerHTML= '<svg xmlns="http://www.w3.org/2000/svg">'+svg+'</svg>';
    var frag= document.createDocumentFragment();
    while (div.firstChild.firstChild)
        frag.appendChild(div.firstChild.firstChild);
    return frag;
}

Подход был обнаружен здесь: jquery's append notработа с svg элементом?

...