在包含SVG标记元素的页面上使用基本标记无法呈现标记

尝试在基于SVG的可视化中使用SVG标记元素时遇到问题。 我将我的更改添加到每个页面上都包含基本标记的Web应用程序,以便任何对CSS文件,JavaScript文件等的引用都可以是相对的。

我有一些示例代码重现了这个问题。 有一个线元素和一个标记元素定义。 标记元素通过标记的uri和id在其“marker-end”属性中被引用。 没有基地标签,箭头显示正常。 用基本标签,它没有被显示。 原因是因为base标签改变了浏览器parsingurls的方式。即使对于line的marker-end属性中指定的简单的基于id的URL也是如此。

有什么办法可以避免这个问题,而不必删除基地标签?

我真的不能删除它,因为它的使用是相当根深蒂固的产品即时通讯工作。 我需要为我的web应用程序支持Firefox,Chrome和IE9 +。 Firefox和Chrome都会产生这个问题。 IE工作正常(即箭头标记显示)。

任何帮助是极大的赞赏。 感谢名单。

<html> <head> <base href="."> <style> .link { stroke: #999; stroke-opacity: .6; } marker#arrow { fill: black; } </style> </head> <body> <svg width="100%" height="100%"> <defs> <marker id="arrow" viewBox="0 -5 10 10" refX="0" refY="0" markerWidth="20" markerHeight="20" orient="auto"> <path d="M0,-5L10,0L0,5"></path> </marker> </defs> <line x1="100" y1="100" x2="333" y2="333" marker-start="url(#arrow)" class="link"></line> </svg> </body> </html> 

HTML <base>元素用于说“parsing所有相对的URL而不是相对于这个页面,而是到一个新的位置”。 在你的情况,你已经告诉它相对于HTML页面的目录。

SVG marker-mid="url(…)"属性是一个FuncIRI参考 。 当你使用像url(#foo)这样的值时,相对IRI通常是相对于当前页面被parsing的,find具有foo id的元素。 但是,当你使用<base> ,你改变它的外观。

要解决这个问题,请使用更好的值。 由于您的基础引用是当前目录,因此您可以简单地使用当前文件的名称:

 <line … marker-mid="url(this_page_name.html#arrow)" /> 

如果你有一个不同的<base> href,比你所显示的,如:

 <base href="http://other.site.com/whee/" /> 

那么你将需要使用绝对的href,例如

 <line … marker-mid="url(http://my.site.com/this_page_name.html#arrow)" /> 

尝试使用javascript:

 <line id="something" /> 

与本地:

 document.getElementById('something').setAttribute('marker-mid', 'url(' + location.href + '#arrow)'); 

使用jQuery:

 $('#something').attr('marker-mid', 'url(' + location.href + '#arrow)'); 

它只是工作。

在丰富的Web应用程序(如Angular构build的应用程序)的上下文中,需要设置<base>标记以使HTML5风格的导航工作,可能会变得麻烦,试图以永久方式解决这个问题。

就我而言,我正在开发的应用程序展示了一个基于SVG的交互式图表构build器 ,它将改变应用程序的URL,因为我select了其中的元素。

我所做的是添加一个全局事件处理程序,它将修复页面中find的任何<path>元素中的所有url(#...)内联样式:

 $rootScope.$on 'fixSVGReference', -> $('path').each -> $path = $ this if (style = $path.attr 'style')? $path.attr 'style', style.replace /url\([^)#]*#/g, "url(#{location.href}\#" 

然后在关键的地方触发这个处理程序,比如当应用程序状态发生变化时(我正在使用ui-router )

 $rootScope.$on '$stateChangeSuccess', -> $timeout (-> $rootScope.$emit 'fixSVGReference'), 5 

以及我知道的任何地方都会有新的/更新的path。 在这里, $timeout事件是为了说明在触发$stateChangeSuccess事件之后的某个时刻,DOM节点实际上是asynchronous更改的。

在Angular 2+中,可以在应用程序模块中注入基本path,而不是使用<base>标记。 这为我解决了Edge和Firefox的问题。

 import { APP_BASE_HREF } from '@angular/common'; @NgModule({ providers: [{ provide: APP_BASE_HREF, useValue: '/' }] }) export class AppModule { } 

https://angular.io/docs/ts/latest/api/common/index/APP_BASE_HREF-let.html

如果你不想修改/animationsvg,比改变url()参数更简单。

包括svg为图像:

 <img src="yourpath/image.svg"> 

Ember 2.7将用rootURLreplace<base>标签, rootURL解决这个问题。

同时在我的d3渐变我使用以下内容:

.attr('fill', `url(${Ember.$(location).attr('href')}#my-gradient)`);

如果你不这样做,你的目标项目将是透明的。

在当前(04-2017)的Windows上,所有浏览器的行为与预期相同( mask = url(“#svgmask”) )。 Chrome,火狐,甚至IE 11! – 但边缘出现了一个错误。

因此,对于Microsoft Edge,当您在文档中使用基本标记时,仍然需要为掩码ID提供绝对path( mask =“url(path / to / this-document.htm#svgmask)”

 <svg viewBox="0 0 600 600" > <defs> <mask id="svgmask"> <image width="100%" height="100%" xlink:href="path/to/mask.svg" ></image> </mask> </defs> <image mask="url(path/to/this-document.htm#svgmask)" width="600" height="600" xlink:href="path/to/image.jpg"></image> </svg>