Angular和SVGfilter

在AngularJS中使用SVG时,我遇到了一个奇怪的行为。 我正在使用$routeProvider服务来configuration我的路线。 当我把这个简单的SVG放在我的模板里时,一切都很好:

 <div id="my-template"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <rect fill="red" height="200" width="300" /> </svg> // ... </div> 

但是当我添加一个filter,例如这个代码:

 <div id="my-template"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <defs> <filter id="blurred"> <feGaussianBlur stdDeviation="5"/> </filter> </defs> <rect style="filter:url(#blurred)" fill="red" height="200" width="300" /> </svg> </div> 

然后:

  • 它在我的主页上工作
  • 使用Firefox时 ,SVG 在其他页面上不再可见,但它仍然留下原来的空间。 使用Chrome ,SVG是可见的,但根本不模糊。
  • 当我手动删除(使用Firebug) filter样式时,SVG再次可见。

这里是路由configuration:

 $routeProvider .when('/site/other-page/', { templateUrl : 'view/Site/OtherPage.html', controller : 'Site.OtherPage' }) .when('/', { templateUrl : 'view/Site/Home.html', controller : 'Site.Home' }) .otherwise({ redirectTo : '/' }) ; 

小提琴

请注意,我没有重现与铬在一个小提琴的问题,虽然它与Firefox“工作”。

我试图用document.createElementNS()创build我的整个SVG无济于事。

有人知道发生了什么吗?

问题

问题是我的HTML页面中有一个<base>标签。 因此,用于识别filter的IRI不再与当前页面相关,而是与<base>标记中指示的URL相关。

这个URL也是我主页的URL,例如http://example.com/my-folder/

对于主页以外的页面,例如http://example.com/my-folder/site/other-page/计算为绝对URL http://example.com/my-folder/#blurred 。 但对于一个简单的GET请求,没有JavaScript,因此没有AngularJS,这只是我的基本页面,没有模板加载。 因此, #blurred 不存在 #blurredfilter。

在这种情况下, Firefox不会呈现<rect> (这是正常行为 ,请参阅W3C推荐 )。 Chrome只是不适用filter。

对于主页, #blurred也计算为绝对URL http://example.com/my-folder/#blurred 。 但是这一次,这也是当前的URL。 不需要发送GET请求,因此存在 #blurredfilter。

我应该看到http://example.com/my-folder/的额外请求,但是在我的辩护中,它在JavaScript文件的其他许多请求中丢失了。

解决scheme

如果<base>标记是强制​​性的,解决方法是使用绝对IRI来标识filter。 在AngularJS的帮助下,这非常简单。 在控制器或链接到SVG的指令中,注入$location服务并使用absUrl() getter:

 $scope.absUrl = $location.absUrl(); 

现在,在SVG中,只需使用这个属性:

 <svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <defs> <filter id="blurred"> <feGaussianBlur stdDeviation="5"/> </filter> </defs> <rect style="filter:url({{absUrl}}#blurred)" fill="red" height="200" width="300" /> </svg> 

相关: 当HTML页面中有BASE标签时,SVG渐变变黑了吗?

这看起来像我之前观察到的行为。 根本原因是你最终有多个元素(filter)具有相同的ID(模糊)。 不同的浏览器处理它不同…

下面是我重做你的情况: http : //jsfiddle.net/z5cwZ/它有两个SVG,一个是隐藏的,Firefox显示没有。

有两种可能性来避免冲突ID。 首先,你可以从你的模板生成独特的ID(我忍不住用尖锐的方式来做)。 这里是一个例子: http : //jsfiddle.net/KbCLB/1/

第二种可能性,使用angularjs可能会更容易,就是把filter放在个别svgs之外( http://jsfiddle.net/zAbgr/1/ ):

 <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="0" height="0"> <defs> <filter id="blurred"> <feGaussianBlur stdDeviation="10" /> </filter> </defs> </svg> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="display:none"> <rect style="filter:url(#blurred)" fill="red" height="200" width="300" /> </svg> <br/> <svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <rect style="filter:url(#blurred)" fill="red" height="200" width="300" /> </svg> 

刚碰到这个问题。 从@Blackhole的答案扩展,我的解决scheme是添加一个指令,改变每个填充属性的值。

 angular.module('myApp').directive('fill', function( $location ) { 'use strict'; var absUrl = 'url(' + $location.absUrl() + '#'; return { restrict: 'A', link: function($scope, $element, $attrs) { $attrs.$set('fill', $attrs.fill.replace(/url\(#/g, absUrl)); } }; }); 

我最近自己碰到这个问题,如果svg在不同的路由上使用,你将不得不把$ location添加到每个path。 实现这一点的更好方法是使用window.location.href而不是$ location服务。

也有问题与svg链接:hrefs,是的,问题是因为<base> – 由于严格的上下文转义限制,当连接绝对url时,我有错误。

我的解决scheme是编写一个filter,添加绝对url,也信任连接。

 angular.module('myApp').filter('absUrl', ['$location', '$sce', function ($location, $sce) { return function (id) { return $sce.trustAsResourceUrl($location.absUrl() + id); }; }]); 

然后像这样使用它: {{'#SVGID_67_' | absUrl} {{'#SVGID_67_' | absUrl}

结果: http://www.example.com/deep/url/to/page#SVGID_67_http://www.example.com/deep/url/to/page#SVGID_67_ ,没有$ sce错误