角度和 SVG 过滤器 [英] Angular and SVG filters

查看:33
本文介绍了角度和 SVG 过滤器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

但是当我添加过滤器时,例如使用以下代码:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1"><定义><filter id="模糊"><feGaussianBlur stdDeviation="5"/></过滤器></defs><rect style="filter:url(#blurred)" fill="red" height="200" width="300"/></svg>

那么:

  • 它适用于我的主页.
  • 使用 Firefox,SVG 在 其他页面 上不再可见,但它仍然在原处留下空间.使用 Chrome,SVG 可见,但完全不模糊.
  • 当我手动(使用 Firebug)删除 filter 样式时,SVG 再次可见.

这里是路由配置:

$routeProvider.when('/site/other-page/', {templateUrl : 'view/Site/OtherPage.html',控制器:'Site.OtherPage'}).什么时候('/', {templateUrl : 'view/Site/Home.html',控制器:'Site.Home'}).除此以外({重定向到:'/'});

小提琴

请注意,我未能在 Fiddle 中重现 Chrome 的问题,尽管它在 Firefox 中有效".

我尝试使用 document.createElementNS() 创建整个 SVG 无济于事.

有人知道发生了什么吗?

解决方案

问题

问题是有一个<我的 HTML 页面中的 base> 标记.因此,用于识别过滤器的 IRI 不再与当前页面,但指向 标记中指示的 URL.

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

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

在这种情况下,Firefox 不会呈现 (这是正常行为,请参阅 W3C 推荐).Chrome 根本不应用过滤器.

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

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

解决办法

如果 标签是强制性的,解决方案是使用绝对 IRI 来标识过滤器.在 AngularJS 的帮助下,这非常简单.在控制器或链接到 SVG 的指令中,注入 $location 服务并使用 absUrl() 获取器:

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

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

<定义><filter id="模糊"><feGaussianBlur stdDeviation="5"/></过滤器></defs><rect style="filter:url({{absUrl}}#blurred)" fill="red" height="200" width="300"/></svg>

<小时>

相关: HTML 页面中有 BASE 标签时 SVG Gradient 变黑?

I came accross a strange behaviour when using SVG with AngularJS. I'm using the $routeProvider service to configure my routes. When I put this simple SVG in my templates, everything is fine:

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

But when I add a filter, with this code for instance:

<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>

Then:

  • It works on my homepage.
  • With Firefox, the SVG isn't visible anymore on the other pages, but it still leaves space where it would have been. With Chrome, the SVG is visible, but not blurred at all.
  • The SVG is visible again when I remove manually (with Firebug) the filter style.

Here is the routes 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 : '/'
    })
;

Fiddle

Please notice that I've failed to reproduce the problem with Chrome in a Fiddle, although it "works" with Firefox.

I've tried to no avail to create my whole SVG with document.createElementNS().

Does someone has an idea of what is happening?

解决方案

The problem

The problem is that there is a <base> tag in my HTML page. Therefore, the IRI used to identify the filter is not anymore relative to the current page, but to the URL indicated in the <base> tag.

This URL was also the URL of my home page, http://example.com/my-folder/ for instance.

For the pages other than the home page, http://example.com/my-folder/site/other-page/ for example, #blurred was computed to the absolute URL http://example.com/my-folder/#blurred. But for a simple GET request, without JavaScript, and therefore without AngularJS, this is simply my base page, with no template loaded. Thus, the #blurred filter doesn't exist on this pages.

In such cases, Firefox doesn't render the <rect> (which is the normal behaviour, see the W3C recommandation). Chrome simply doesn't apply the filter.

For the home page, #blurred is also computed to the absolute URL http://example.com/my-folder/#blurred. But this time, this is also the current URL. There is no need to send a GET request, and thus the #blurred filter exists.

I should have seen the additional request to http://example.com/my-folder/, but in my defense, it was lost in a plethora of other requests to JavaScript files.

The solution

If the <base> tag is mandatory, the solution is to use an absolute IRI to identify the filter. With the help of AngularJS, this is pretty simple. In the controller or in the directive that is linked to the SVG, inject the $location service and use the absUrl() getter:

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

Now, in the SVG, just use this property:

<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>


Related: SVG Gradient turns black when there is a BASE tag in HTML page?

这篇关于角度和 SVG 过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆