SVGベースの視覚化でSVGマーカー要素を使用しようとしているときに問題が発生しました。 CSSファイル、JavaScriptファイルなどへの参照を相対的にできるように、すべてのページにベースタグを含むWebアプリケーションに変更を追加しています。
以下に、問題を再現するコードの例をいくつか示します。 line要素と、marker要素が定義されています。マーカー要素は、マーカーのURIとIDを介して、「マーカー終了」属性の行によって参照されます。ベースタグがない場合、矢印は正常に表示されます。ベースタグでは表示されません。その理由は、ベースタグはブラウザがURLを解決する方法を変更するためです。行のmarker-end属性で指定された単純なIDベースのURLについても同様です。
ベースタグを削除せずにこの問題を回避する方法はありますか?
私が取り組んでいる製品には、その使用がかなり根付いているため、実際に削除することはできません。 Firefoxをサポートする必要があります。ChromeおよびIE9 + for mywebapp。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>
_ element は、「このページではなく新しい場所に関連するすべての相対URLを解決する」と言うために使用されます。あなたの場合、HTMLページのあるディレクトリを基準にして解決するように指示しました。
SVG marker-mid="url(…)"
属性は FuncIRIリファレンス です。 url(#foo)
のような値を使用する場合、相対IRIは通常、現在のページに対して解決され、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)" />
_
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
JavaScriptで試してください:
<line id="something" />
ネイティブ:
document.getElementById('something').setAttribute('marker-mid', 'url(' + location.href + '#arrow)');
JQueryの場合:
$('#something').attr('marker-mid', 'url(' + location.href + '#arrow)');
うまくいきます。
Angularに基づいて構築されたようなリッチWebアプリのコンテキストでは、HTML5スタイルのナビゲーションを機能させるために_<base>
_タグを設定する必要があるため、永続的な方法で修正しようとすると面倒になる可能性があります。
私の場合、私が取り組んでいたアプリは SVGベースのインタラクティブなダイアグラムビルダー を表示していました。その中で要素を選択すると、アプリのURLが変更されます。
私がしたことは、ページにある_<path>
_要素のすべてのurl(#...)
インラインスタイルを修正するグローバルイベントハンドラーを追加することでした。
_$rootScope.$on 'fixSVGReference', ->
$('path').each ->
$path = $ this
if (style = $path.attr 'style')?
$path.attr 'style', style.replace /url\([^)#]*#/g, "url(#{location.href}\#"
_
次に、アプリの状態が変化したときなど、主要な場所でこのハンドラーをトリガーします(私は i-router を使用しています)
_$rootScope.$on '$stateChangeSuccess', ->
$timeout (-> $rootScope.$emit 'fixSVGReference'), 5
_
同様に、これらのような新しい/更新されたパスがあることがわかっている場所はどこでも。ここで、_$timeout
_は、_$stateChangeSuccess
_イベントがトリガーされた後、DOMノードが実際に非同期で実際に変更されるという事実を説明するためのものです。
Ember 2.7は_<base>
_タグをrootURL
に置き換え、この問題を修正する予定です。
それまでの間、グラデーションのd3では、次を使用しています。
.attr('fill', `url(${Ember.$(location).attr('href')}#my-gradient)`);
これを行わないと、対象のアイテムは透明に見えます。
現在Windows(2017年4月)では、すべてのブラウザーが期待どおりに動作します(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>
Svgを変更またはアニメーション化したくない場合は、url()
パラメータを変更するよりも簡単な解決策があります。
画像としてsvgを含めます。
<img src="yourpath/image.svg">
あなたはそれをアーカイブすることができます:
$("[marker-mid]").attr("marker-mid", function () {
return $(this).attr("marker-mid").replace("url(", "url(" + location.href);
});