AngularJS ng-href 和 svg xlink

Posted

技术标签:

【中文标题】AngularJS ng-href 和 svg xlink【英文标题】:AngularJS ng-href and svg xlink 【发布时间】:2013-03-31 12:02:51 【问题描述】:

我想要一些关于使用带有 angular 的 xml 命名空间属性的意见。

问题是,当 Angular 解析表达式时,Angular 附带了几个指令来处理诸如 href 和 src 之类的写入属性(否则浏览器将尝试将 mymodel.myimage 作为 url 加载)

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

我面临的问题是我正在使用 angular 与 D3 一起输出 svg,并且由于 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 的建议将不胜感激。

【问题讨论】:

我没有找到您问题的答案,但感谢您发布 Plunker。我将它用于我自己的角度 SVG 绑定。 【参考方案1】:

你可以使用ng-attr-<some attribute>

ng-attr-xlink:href="xxx" 为我工作。


请注意,您还需要一个空的xlink:href="" 作为初始值。 ——德里克·许

【讨论】:

这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post。 @Siddharth,实际上确实如此。问题不仅仅是关于自定义指令。事实上,@Leon 想要一些关于使用带有 angular 的 xml 命名空间属性的输入,以及关于如何最好地处理 xml 命名空间 / svg 和 angular 的建议。为了解决他的问题,他甚至编写了自定义指令。我指出不需要自定义指令。 Angularjs 已经有 ng-attr 为他完成这项工作。 @sheriffderek,给你angularjs ng-attr example。请注意,您还需要一个空的xlink:href="" 作为初始值。 我希望将它与 一起使用——这样我就可以定位精灵的片段。我真的没有任何理由将图像放入 svg。 +1,这对我有用,但它非常挑剔。您在动态 ng-attr-xlink:href 之后使用了空的 xlink:href=""。另外,我认为这不适用于早期版本的 Angular。【参考方案2】:

如果您像我一样正在寻找一种将图像添加到 svg 的方法,您可以添加:

xlink:href="" ng-href=" foo "

例子:

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

我在哪里找到了解决方案:

https://github.com/angular/angular.js/issues/7697

【讨论】:

这太棒了。谢谢!【参考方案3】:

我在尝试输出与模型相关的 xlink:href 值时遇到了类似的问题。基于用户在<select> 控件中选择的<option>,我试图通过<use> 元素的xlink:href 属性显示动态SVG 图标。

我在 AngularJS 的 GitHub 问题中找到了 a thread about this。根据那里的讨论,似乎因为存在可行的解决方法,他们通过将其移至积压里程碑有效地提出了修复。

最终对我有用的是这个 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>

例如,给定icon-music 中的category.iconName,Angular 会将xlink:href 动态设置为#icon-music,这会在同一页面上进一步引用&lt;svg id="icon-music"&gt; 元素。

正如其他人所指出的,关键是在调用ngHref 指令的元素上设置一个空白xlink:href="" 属性。属性顺序似乎无关紧要。使用 ng-attr-xlink:href="xxx"(如 Derek Hsu 的回答中所述)对我不起作用。

所有这些都假设 Angular 1.3.36。

【讨论】:

非常感谢它对我有用...ng-attr-xlink:href="model" 对我不起作用..... coffeescript: 【参考方案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"  
    ng-xlink-href="item.imageSrc"
    ng- ng-
    ng-cloak
    />

【讨论】:

当 xlink:href 对我不起作用时,我不得不重新阅读这篇文章。这里的关键是您需要一个假值才能开始。没有它,即使具有正确的属性,图像也不会呈现。留下此评论以帮助像我这样的其他 TL;DR 傻瓜。谢谢丹尼! @fractalspawn 欢迎您。我打算将此评论添加到答案中,然后我看到我已经将它放在 HTML 上方的评论中:-)【参考方案5】:

对于由于 HTML5 模式下的 Angular/Angular UI 路由器而遇到此问题的任何其他人,我想出了一个简单的修复方法,使 svg sprite 图标能够与它们的 xlink:href 属性和标签一起使用。

要点在这里: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 加载到页面上时遇到了这个问题。如果在加载 spritesheet 之前我在页面上有一个,它将失败并且一旦 spritesheet 可用就不会解决。加载 spritesheet 后添加到 dom 的任何内容都可以。我不得不推迟将项目放入 dom 直到 spritesheet 完成加载。

这只影响了 ios。所有其他浏览器都不关心顺序。

【讨论】:

【参考方案7】:

这花费了我比我想要的更多的时间。大约 20-30 分钟。

如果我理解正确,图像元素上的任何失败加载都会使该元素在未来变得无用。我相信这与@GeekyMonkey 所说的类似。如果角度绑定系统最初将 xlink:href 设置为 null,则 Image 元素将不再起作用,即使我们将来有有效值也是如此。

这是解决方案,请注意我是如何使用 ng-if 指令将图像元素包裹在 g 元素中的。这确保我们仅在正确的值可用时才绑定图像。

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

        xlink:href=""

        
        
        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);
        ;
    ;
());

【讨论】:

以上是关于AngularJS ng-href 和 svg xlink的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS进阶(三十二)书海拾贝之特殊的ng-src和ng-href

AngularJS:如何通过 ng-href 将多个参数传递给控制器​​?

使用 CSS 或 AngularJS 的 SVG 路径元素悬停缩放

angularjs ng重复svg跳过空值的索引

使用 AngularJs 和 D3.js 从 svg 元素调用自定义函数

基于容器元素在 AngularJS 指令中自动调整 SVG 大小