56

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

我在下面有一些示例代码可以重现该问题。定义了一个线元素和一个标记元素。标记元素通过标记的 uri 和 id 由其“标记结束”属性中的行引用。没有基本标签,箭头显示正常。对于基本标签,它不显示。原因是因为 base 标签改变了浏览器解析 url 的方式。即使对于在行的 marker-end 属性中指定的简单的基于 id 的 url。

有什么办法可以解决这个问题而不必删除基本标签?

我无法真正删除它,因为它的使用在我正在开发的产品中已经根深蒂固。我的 webapp 需要支持 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>
4

8 回答 8

57

HTML<base>元素用于表示“将所有相对 URL 解析为不与此页面相关,而是与新位置相关”。在您的情况下,您已经告诉它相对于带有 HTML 页面的目录进行解析。

SVGmarker-mid="url(…)"属性是FuncIRI 参考。当您使用像url(#foo)相对 IRI 这样的值时,通常相对于当前页面解析,找到具有fooid 的元素。但是,当你使用 时<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)" />
于 2013-08-16T03:26:00.897 回答
5

尝试使用 javascript:

<line id="something" />

与原生:

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

使用 jQuery:

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

它只是工作。

于 2015-05-01T09:30:57.583 回答
5

In the context of a rich web app like one built on Angular, where you need to set the <base> tag to make HTML5-style navigation work, it can get messy to try to fix that in a permanent way.

In my case, the app I was working on was showing a SVG-based interactive diagram builder that would change the app url as I selected elements therein.

What I did was to add a global event handler that would fix all url(#...) inline styles in any <path> element found in the page:

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

Then trigger this handler in key places, like when the app state changes (I'm using ui-router)

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

As well as anywhere where I know there'd be new/updated paths like these. Here, the $timeout thing is to account for the fact that the DOM nodes really are changed asynchronously sometime after the $stateChangeSuccess event is triggered.

于 2015-11-03T14:06:45.353 回答
5

在 Angular 2+ 中,您可以在应用程序模块中注入基本路径,而不是使用 <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

于 2017-04-26T16:03:54.967 回答
1

在 Windows 当前(04-2017)上,所有浏览器的行为都符合预期(mask=url("#svgmask"))。Chrome、Firefox,甚至 IE 11!- 但 Edge 出现错误。

因此,对于 Microsoft Edge,当您在文档中使用基本标记时,您仍然需要为您的掩码 ID提供绝对路径( 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>
于 2017-04-28T06:21:41.220 回答
1

Ember 2.7 将替换应该解决此问题的<base>标签。rootURL

与此同时,在我的 d3 渐变中,我正在使用以下内容:

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

如果您不这样做,您所定位的项目似乎是透明的。

于 2016-06-17T18:28:04.017 回答
0

如果您不想修改/动画 svg,有一个比更改url()参数更简单的解决方案。

将 svg 包含为图像:

<img src="yourpath/image.svg">
于 2015-04-01T10:03:04.123 回答
0

您可以将其存档:

$("[marker-mid]").attr("marker-mid", function () {
    return $(this).attr("marker-mid").replace("url(", "url(" + location.href); 
});
于 2018-11-15T15:23:32.197 回答