2014-04-26 14 views
6

Jestem zainteresowany budowaniem kompozytowego SVG przez komponowanie wielorazowych elementów graficznych zapakowanych wewnątrz dyrektyw Angular.js. Na przykład może mam:AngularJS: Transcluding elementy SVG w dyrektywach

<div ng-app="svgApp"> 
    <canvas> 
    <drawing ng-repeat="i in [1,2,3]" cy="{{i * 40}}"></drawing> 
    </canvas> 
</div> 

gdzie jestem określającą następujących dyrektyw:

.directive('canvas', function() { 
    return { 
     template: '<svg height=200 width=100 ng-transclude></svg>', 
     restrict: 'E', 
     replace: true, 
     transclude: true 
    }; 
    }) 

    .directive('drawing', function() { 
    return { 
     template: '<circle cx=50 r=15></circle>', 
     restrict: 'E', 
     replace: true 
    }; 
    }) 

Problem polega na tym, że elementy SVG nie wydają się prawidłowo dołączona. Wskazówką wydaje się być here, in another StackOverflow question, ponieważ dzieje się tak głównie dlatego, że węzły SVG nie są poprawnie utworzone w Angular.js.

Po wywiercenie dalej, znalazłem this solution, which involves using a helper function zastąpić odpowiednich elementów DOM z prawidłowo utworzonych węzłów SVG, a la:

.value('createSVGNode', function(name, element, settings) { 
     var namespace = 'http://www.w3.org/2000/svg'; 
     var node = document.createElementNS(namespace, name); 
     for (var attribute in settings) { 
     var value = settings[attribute]; 
     if (value !== null && !attribute.match(/\$/) && (typeof value !== 'string' || value !== '')) { 
      node.setAttribute(attribute, value); 
     } 
     } 
     return node; 
    }); 

Jednak wydawało się niepożądana, że ​​muszę to wykorzystać wszędzie, a ja chciałem, aby obejście było jak najbliżej błędu, dopóki nie zostało naprawione.

Moje pytanie brzmi, czy następujące byłoby rozsądne obejście:

angular.forEach(['circle', ...], function (svgElem) { 

    svgModule 

    .directive(svgElem, function (createSVGNode) { 
     return { 
     restrict: 'E', 
     link: function(scope, element, attrs) { 
      var node = createSVGNode(svgElem, element, attrs); 
      angular.element(node).append(element[0].childNodes); 
      element.replaceWith(node); 
     } 
     }; 
    }); 

}); 

I to działa w Plunker!

Czy mogę w ten sposób przedefiniować istniejące dyrektywy dotyczące elementów SVG?

Odpowiedz

5

Powyższe podejście jest możliwe, jeśli nie można przenieść kodu do aktywnej końcówki programistycznej AngularJS 1.3, gdzie kwestia transkokowania elementów innej przestrzeni nazw (takich jak SVG lub MathML) to resolved.

prowadzi link Plunker pokazuje, jak zaktualizować swój kod z poprawką. Kluczem jest dodanie nowego klucza „templateNamespace” w obiekcie definicji dyrektywy:

.directive('svgInternal', function() { 
    return { 
     templateNamespace: 'svg', 
     template: '<g><rect height="25" width="25" /><text x="30" y="20">Hello, World</text></g>', 
     restrict: 'E', 
     replace: true 
    }; 
    }) 

gdzie następujących znaczników demonstruje dyrektywę SVG typu w użyciu:

<svg height="30"> 
    <svg-internal></svg-internal> 
    </svg> 

Edycja " type "zmieniono na" templateNamespace "od wersji 1.3.beta.19.

+1

Dzięki za odpowiedź. Mam problem z twoim plunkr, 'Fragment SVG osadzony w kontenerze svg (FIXED)' i 'SVG w transclusion (FIXED)' nie pokazują svg rect. – apairet

+1

OK, zmieniono 'type'' templateNamespace' patrz http://plnkr.co/edit/IgXMeZ6vNHPLxZOs0Sbu – apairet

+0

Pre 1.3, zawiń szablon w ''. Elementy SVG można zagnieżdżać. –

Powiązane problemy