Подтвердить что ты не робот

AngularJS ng-href и svg xlink

Мне нужен вход для использования атрибутов с именами xml с именами angular.

Проблема заключается в том, что angular содержит пару директив для обработки атрибутов записи, таких как href и src, когда angular проанализировал выражения (иначе браузер попытается загрузить {{mymodel.myimage}} в качестве URL-адреса)

https://github.com/angular/angular.js/blob/master/src/ng/directive/booleanAttrs.js#L329

Проблема, с которой я сталкиваюсь, заключается в том, что я использую angular для вывода svg вместе с D3, и поскольку angular не имеет способа вывода xlink:href, я застрял.

Я создал настраиваемую директиву, которая выводит xlink: href

app.directive('ngXlinkHref', function () {
  return {
    priority: 99,
    restrict: 'A',
    link: function (scope, element, attr) {
      var attrName = 'xlink:href';
      attr.$observe('ngXlinkHref', function (value) {
        if (!value)
          return;

        attr.$set(attrName, value);
      });
    }
  };
});

Полная демонстрация: http://plnkr.co/edit/cMhGRh

Но кажется, что если я не добавлю вручную xlink: href к элементу, изображение svg не будет отображаться.

Приветствуются любые предложения о том, как наилучшим образом обрабатывать пространства имен xml/svg вместе с angular.

4b9b3361

Ответ 1

Вы можете использовать ng-attr-<some attribute>

ng-attr-xlink:href="{{xxx}}" работает для меня.


Обратите внимание, что вам также нужно пустое xlink:href="" как начальное значение. - Дерек Хсу

Ответ 3

У меня возникла аналогичная проблема при попытке вывода значения для xlink:href, привязанного к модели. Исходя из выбранного пользователем элемента <option> в элементе управления <select>, я пытался показать динамический значок SVG с помощью атрибута xlink:href элемента <use>.

Я нашел поток об этом в вопросах GitHub для AngularJS. Основываясь на обсуждении там, похоже, что, поскольку существует жизнеспособное обходное решение, они эффективно внесли исправление, переместив его на веху в Backlog.

То, что в конечном итоге сработало для меня, было вдохновлено этим JSBin:

http://jsbin.com/sigoleya/1/edit?html,js,output

Вот код, который я использовал в моем шаблоне:

<svg class="icon" data-ng-class="category.iconName">
  <use xlink:href="" data-ng-href="{{'#' + category.iconName}}">
</svg>

Учитывая category.iconName of icon-music, например, Angular динамически устанавливает xlink:href на #icon-music, который ссылается на элемент <svg id="icon-music"> далее на той же странице.

Как отмечали другие, какой ключ устанавливает пустой атрибут xlink:href="" в элементе, где вы вызываете директиву ngHref. Порядок атрибутов не имеет значения. Использование ng-attr-xlink:href="{{xxx}}" (как упоминалось в ответе Дерека Хсу) не сработало для меня.

Все это предполагает Angular 1.3.36.

Ответ 4

Я решил ту же проблему со следующими модулями:

Модуль для SVG:

var app = angular.module('Svgs', []);

angular.forEach([
    { ngAttrName: 'ngXlinkHref', attrName: 'xlink:href' },
    { ngAttrName: 'ngWidth', attrName: 'width' },
    { ngAttrName: 'ngHeight', attrName: 'height' }
], function (pair) {

    var ngAttrName = pair.ngAttrName;
    var attrName = pair.attrName;

    app.directive(ngAttrName, function (IeHelperSrv) {

        return {

            priority: 99,

            link: function (scope, element, attrs) {

                attrs.$observe(ngAttrName, function (value) {

                    if (!value) return;

                    attrs.$set(attrName, value);
                    if (IeHelperSrv.isIE) element.prop(attrName, value);
                });
            }
        };
    });
});

Модуль для обнаружения IE:

angular.module('IeHelper', []).factory('IeHelperSrv', function () {

    return {
        isIE: checkForIE.isIE,
    }
});

var checkForIE = {
    init: function () {
        this.isIE = (navigator.userAgent.indexOf('MSIE') != -1);
    }
};

checkForIE.init();

HTML:

<!-- image has initial fake source, width and height to force it to render -->
<image xlink:href="~/Content/Empty.png" width="1" height="1"
    ng-xlink-href="{{item.imageSrc}}"
    ng-width="{{item.width}}" ng-height="{{item.height}}"
    ng-cloak
    />

Ответ 5

Для всех, у кого есть эта проблема из-за Angular/Angular UI Router в режиме HTML5, я придумал прямое исправление, позволяющее значкам svg sprite работать со своим атрибутом xlink: href и тегом.

Gist здесь: https://gist.github.com/planetflash/4d9d66e924aae95f7618c03f2aabd4a3

app.run(['$rootScope', '$window', function($rootScope, $window){
 $rootScope.$on('$locationChangeSuccess', function(event){
    $rootScope.absurl = $window.location.href;
});

<svg><use xlink:href="{{absurl+'#svgvID'}}"></use></svg>

Ответ 6

Я столкнулся с этой проблемой, когда я использовал Ajax для загрузки svg spritesheet на страницу. Если бы у меня была страница на странице до того, как был загружен спрайт, она потерпит неудачу и не будет разрешаться после того, как спрайт будет доступен. Любое добавление в дом после загрузки спрайта было прекрасным. Мне пришлось откладывать предметы в доме до тех пор, пока после того, как спрайт закончил загрузку.

Это повлияло только на IOS. Все остальные браузеры не заботились о заказе.

Ответ 7

Мне потребовалось больше времени, чем хотелось бы. Около 20-30 минут.

Если я правильно понимаю, любая неудачная загрузка элемента изображения будет сделать этот элемент бесполезным в будущем. Я верю, что это что-то похожее @GeekyMonkey говорит. Если система привязки angular установила xlink: href изначально имеет значение null, элемент изображения больше не будет работать, даже если у нас есть действительное значение в будущем.

Вот решение, обратите внимание, как я обернул элемент изображения внутри элемента g, используя директиву ng-if. Это гарантирует, что мы будем привязываться к изображению только тогда, когда доступно правильное значение.

<g ng-if="vm.svgMap.background != null">
    <image
        ng-attr-xlink:href="{{vm.svgMap.background.image | trusted}}"
        ng-attr-width="{{vm.svgMap.background.width}}"
        ng-attr-height="{{vm.svgMap.background.width}}"

        xlink:href=""

        width="1"
        height="1"
        x="0"
        y="0"></image>
</g>

Как говорят другие, порядок атрибутов также важен. Чтобы гарантировать, что angularJS позволяет нам связывать элемент изображения, мы также должны будем доверять этому ресурсу, я сделал это через фильтр (это тот, который указан в атрибуте xlink: href):

(function() {
    'use strict';

    angular.module('myTool').filter('trusted', TrustedFilter);

    function TrustedFilter($sce) {
        return function(url) {
            return $sce.trustAsResourceUrl(url);
        };
    };
}());