it-swarm.com.de

Bei Verwendung des Basis-Tags auf einer Seite, die SVG-Markierungselemente enthält, wird die Markierung nicht gerendert

Beim Versuch, SVG-Markierungselemente in einer SVG-basierten Visualisierung zu verwenden, ist ein Problem aufgetreten. Ich füge meine Änderungen einer Webanwendung hinzu, die auf jeder Seite ein Basis-Tag enthält, sodass alle Verweise auf CSS-Dateien, Javascript-Dateien usw. relativ sein können. 

Ich habe unten einen Beispielcode, der das Problem reproduziert. Es gibt ein Linienelement und ein Markierungselement. Das Markerelement wird von der Zeile in seinem 'marker-end'-Attribut über uri und id des Markers referenziert. Ohne das Basis-Tag wird der Pfeil in Ordnung angezeigt. Mit dem Basis-Tag wird es nicht angezeigt. Der Grund liegt darin, dass das Basis-Tag die Art und Weise ändert, in der der Browser URLs auflöst. Dies gilt auch für die einfache, auf IDs basierende URL, die im marker-end-Attribut der Zeile angegeben ist. 

Gibt es eine Möglichkeit, dieses Problem zu umgehen, ohne das Basis-Tag entfernen zu müssen? 

Ich kann es nicht wirklich entfernen, weil die Verwendung in dem Produkt, an dem ich arbeite, ziemlich tief verwurzelt ist. Ich muss Firefox, Chrome und IE9 + für meine Webapp unterstützen. Firefox und Chrome verursachen dieses Problem. IE funktioniert einwandfrei (dh Pfeilmarkierungen werden angezeigt).

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

Das HTML <base>-Element wird verwendet, um zu sagen "alle relativen URLs relativ zu dieser Seite, aber zu einem neuen Ort auflösen". In Ihrem Fall haben Sie ihm mitgeteilt, dass er relativ zu dem Verzeichnis mit der HTML-Seite aufgelöst werden soll.

Das SVG marker-mid="url(…)"-Attribut ist eine FuncIRI-Referenz . Wenn Sie einen Wert wie url(#foo) verwenden, wird das relative IRI normalerweise relativ zur aktuellen Seite aufgelöst. Suchen Sie das Element mit der foo-ID. Wenn Sie jedoch <base> verwenden, ändern Sie, wo es aussieht.

Um dieses Problem zu lösen, verwenden Sie einen besseren Wert. Da Ihre Basisreferenz das aktuelle Verzeichnis ist, können Sie einfach den Namen der aktuellen Datei verwenden:

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

Wenn Sie einen anderen <base> href haben, als Sie gezeigt haben, z.

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

dann müssen Sie eine absolute href verwenden, z.

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

Im Kontext einer Rich-Web-App wie Angular, bei der Sie das <base>-Tag festlegen müssen, damit die Navigation im HTML5-Stil funktioniert, kann es unangenehm werden, das Problem dauerhaft zu beheben.

In meinem Fall zeigte die App, an der ich arbeitete, einen SVG-basierten interaktiven Diagramm-Generator , der die App-URL ändert, wenn ich Elemente darin auswähle.

Was ich tat, war das Hinzufügen eines globalen Ereignishandlers, der alle url(#...) Inline-Stile in jedem <path>-Element auf der Seite korrigiert:

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

Dann lösen Sie diesen Handler an wichtigen Stellen aus, beispielsweise wenn sich der App-Status ändert (ich verwende ui-router ).

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

Sowie überall, wo ich weiß, würde es neue/aktualisierte Pfade wie diese geben. Die Sache $timeout ist hier zu berücksichtigen, dass die DOM-Knoten tatsächlich einmal asynchron geändert werden, nachdem das Ereignis $stateChangeSuccess ausgelöst wurde.

5
matehat

Versuchen Sie es mit Javascript:

<line id="something" />

Mit einheimischen:

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

Mit jQuery:

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

Es funktioniert einfach.

4
nikoloza

In Angular 2+ können Sie den Basispfad in Ihr App-Modul einfügen, anstatt den Tag <base> zu verwenden. Dadurch wurde das Problem in Edge und Firefox für mich behoben.

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

3
CTarczon

Ember 2.7 ersetzt das <base> - Tag durch rootURL, wodurch dieses Problem behoben werden sollte.

In der Zwischenzeit benutze ich in meinem d3 für Farbverläufe Folgendes:

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

Wenn Sie dies nicht tun, wird das Objekt, auf das Sie zielen, transparent angezeigt.

1
averydev

Wenn Sie das svg nicht ändern/animieren möchten, gibt es eine einfachere Lösung als das Ändern des Parameters url().

Fügen Sie die svg als Bild hinzu:

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

Unter Windows verhalten sich derzeit (04-2017) alle Browser wie erwartet (mask = url ("# svgmask")). Chrome, Firefox, sogar IE 11 !! - aber Edge hat einen Fehler.

Für Microsoft Edge müssen Sie also weiterhin den absoluten Pfad ( mask = "url (Pfad/zu/this/document.htm # svgmask)" ) für Ihre Masken-IDs angeben, wenn Sie ein Basis-Tag in verwenden Ihr Dokument:

<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>
1
f.eberharter

Sie können es archivieren mit:

$("[marker-mid]").attr("marker-mid", function () {
    return $(this).attr("marker-mid").replace("url(", "url(" + location.href); 
});
0
Paolo Rampino