Warum wird <feDropShadow> nicht angezeigt?

Sep 30 2020

Bearbeiten : Beim Versuch, ein mcve zu erstellen, konnte ich das Problem nicht wiederholen . Jetzt bin ich völlig verblüfft. Funktioniert mit Codesandbox, nicht in meinem Projekt.


Erste Frage
Ich möchte ein dynamisches Inline-SVG-Element erstellen und seine Drehung einem zuordnen [(ngModel)]. Nichts Besonderes.

Der schicke Teil ist, dass ich ein <filter>mit einem verwenden möchte <feDropShadow>. Und ich möchte, dass der Schatten dynamisch ist (immer nach oben zeigen, unabhängig von der Drehung der Nadel). Das habe ich vor der Verwendung von Vue getan.

Hier ist eine Geige, die den Effekt demonstriert: https://jsfiddle.net/websiter/y4ghan0k/

Aber für mein Leben kann ich das nicht <feDropShadow>in Angular zum <svg>Laufen bringen, wenn das in der Vorlage eingefügt ist. Es wird einfach nicht angezeigt. Kein Fehler oder Warnung. Wenn ich es wie <img src="path/to/svg">erwartet einfüge (der Schatten wird angezeigt), kann ich den Pfad aber nicht mehr drehen, da das transformierte Element ein untergeordnetes Element des Elements sein muss, das den Filter trägt.

Beachten Sie, dass dies nicht an diesem Problem mit dem URL () -Filter liegt. Ich stelle dem Filter das Präfix vor this.location.path().

Hier ist der Kern meines Angular-Codes:

component.ts:

import { Location } from '@angular/common';

export class SomeComponent {
  constructor(private location: Location) {}
  dsLink = `url(${this.location.path()}#drop-shadow)`;
}

component.html:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="180" y="100"
     viewBox="0 0 180 100" xml:space="preserve">
  <defs>
    <filter xmlns="http://www.w3.org/2000/svg" id="drop-shadow" height="130%">
      <feDropShadow dx="0" dy="-4" flood-color="rgba(0,0,0,.65)"/>
    </filter>
  </defs>
  <g [attr.filter]="dsLink">
    <path fill="#fff" d="M102.2,89.5c0-0.1,0-0.1,0-0.2c0-0.2,0-0.4-0.1-0.6L92.9,6.8c-0.1-0.8-3.2-0.9-3.3,0
      L78.7,88.5c-0.1,0.2-0.1,0.4-0.1,0.6c0,0.1,0,0.1,0,0.2l0,0.1c0,0,0,0.1,0.1,0.1c0.5,2.4,5.6,4.4,11.7,4.4
      c6.2,0.1,11.2-1.8,11.8-4.2c0,0,0.1-0.1,0.1-0.1L102.2,89.5z">
    </path>
  </g>
</svg>

Der Einfachheit halber habe ich den [(ngModel)]Pfad entfernt, der die Nadel drehen soll.

Der Filter url()scheint korrekt zu sein, es liegt kein Fehler vor. Der Schatten wird jedoch nicht angezeigt.

Gibt es etwas Besonderes, das ich tun / wissen muss, um Winkelgriffelemente <svg>inline zu machen ?

Was vermisse ich?

Antworten

1 tao Sep 30 2020 at 05:27

Ich habe es endlich geknackt, also poste ich es hier und hoffe, dass es anderen hilft.

Kurz gesagt: Verwenden Sie eindeutige IDs für Filter in jeder Ihrer Komponenteninstanzen. Andernfalls verwendet jede Instanz den ersten in DOM gefundenen Filter (mit dieser ID). Wenn sich dieser Filter zufällig in einem übergeordneten Filter befindet display: none, visibility:hiddenoder wenn Sie den Filter opacity: 0anwenden, wird alles, was Sie anwenden, auch unsichtbar.


Das Problem hatte damit zu tun, dass ich dieselbe Komponente in verschiedenen Registerkarten verwendete. Dadurch wurden separate Instanzen der Komponente erstellt, die jeweils dieselbe ID ( #drop-shadow) verwenden. Während doppelte IDs offensichtlich ungültiges HTML sind, wäre dies kein Problem gewesen, wenn wir uns nicht mit Filtern befasst hätten. Da die <defs>identisch sind, spielt es keine Rolle, ob die Komponente auf der 4. Registerkarte die <defs>von der Komponente auf der ersten Registerkarte definierte verwendet.

Außer wenn es sich um <filter>s handelt, weil sie tatsächlich Pixel für Pixel das Rendering-Ergebnis dynamisch berechnen. Das heißt, wenn das <svg>Definieren von <filter>nicht gerendert wird, berechnet der Browser mithilfe des Filters (Pixel für Pixel) das Ergebnis, das den Filter anwendet, und führt immer dazu, dass alle Pixel unsichtbar sind.

So die Lösung ist eine eindeutige Kennung in jedem separaten Instanz der Komponente zuzuweisen.