J o: SVG, polygon mit linear-gradient

Guten Morgen zusammen,

mittlerweile hab ich wieder etwas Zeit und bin auf ein kleines Problem gestoßen.

Meine Aufgabe: Ein SVG mit einem Farbverlauf von Links nach Rechts. Dazu findet sich eine Reihe an Referenzen mit Beispielen auch im SelfHTML-Wiki. Soweit also kein Problem.
Nun möchte ich den offset der Farben individuell mit Werten aus einer Datenbank variieren. Dies auch nicht nur für ein SVG sondern für Viele ( N > 25 - 250 ) welche sich dann auch noch ändern können.

Da für jeden Farbverlauf eine eigener <linearGradient> definiert werden müsste und ich den irgendwo zu meiner HTML Struktur hinzufügen müsste, war mein erster Ansatz im CSS eine Klasse zu erstellen welche fill: ein background-image zuweist. Dies schlug leider fehl.

Weiter gesucht und auf diesen Artikel gestoßen. Das sollte doch irgendwie funktionieren. Also ein SVG erstellt:

<svg height="20" width="20">
	<polygon id="svg" points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78"/>
</svg>

(ob das svg oder das polygon die id trägt ändert gerade nichts, bin dort gerade am experimentieren) und versucht dieses als Background Image zu nutzen:

.svg {
	height: 1.5em;
	width: 1.5em;
	-webkit-mask: url(#svg) no-repeat 50% 50%;
	mask: url(#svg) no-repeat 50% 50%;
	-webkit-mask-size: cover;
	mask-size: cover;
}

und den Gradient ebenfalls mit einer Klasse im CSS hinzuzufügen:

.svg--gradient-test {
	background: -webkit-linear-gradient(0deg, var(--color) 40%, var(--color-transparent) 60%);
	background: linear-gradient(0deg, var(--color) 40%, var(--color-transparent) 60%); 
}

Damit müsste es doch möglich sein, beliebig viele Polygone mit JS dem DOM hinzuzufügen:

let node = document.createElement("img");
node.classList.add("svg" , "svg--gradient-test");
document.getElementById("test").appendChild( node );

Dies schlägt jedoch auch Fehl. Irgendwo ist sicher ein kleiner Fehler aber ich komme gerade nicht dahinter.

Gruß
Jo

akzeptierte Antworten

  1. Hallo Jo,

    was ich vermisse, du aber vielleicht nur nicht gepostet hast, ist

    • dem img-Element einen Quelle geben (also ein src für das img, am besten eins das auf das svg verweist)
    • das Setzen der custom Properties (a.k.a. CSS-Variablen) --color und --color-transparent

    Bei clientseitigen Fehlschlägen aller Art sollte man die Entwicklerwerkzeuge des Browsers öffnen und

    • in der JS Konsole nach Fehlermeldungen schauen
    • im Netzwerk-Tab nach Ladefehlern schauen
    • im DOM Inspektor/Explorer schauen, ob das im DOM steht, was man erwartet.

    Rolf

    --
    sumpsi - posui - clusi
    1. Hallo Rolf,

      was ich vermisse, du aber vielleicht nur nicht gepostet hast, ist

      • dem img-Element einen Quelle geben (also ein src für das img, am besten eins das auf das svg verweist)

      Vielleicht ist das Element für den Moment schlecht gewählt da es kein Bild gibt eben nur das Background-image, also src="" wäre es dann wohl.

      • das Setzen der custom Properties (a.k.a. CSS-Variablen) --color und --color-transparent

      Ja das sind irgendwelche Farben spielt für die Aufgabe keine Rolle

      Bei clientseitigen Fehlschlägen aller Art sollte man die Entwicklerwerkzeuge des Browsers öffnen und

      • in der JS Konsole nach Fehlermeldungen schauen

      Kein Fehler.

      • im Netzwerk-Tab nach Ladefehlern schauen

      Es wird kein Bild geladen.

      • im DOM Inspektor/Explorer schauen, ob das im DOM steht, was man erwartet.

      Im DOM steht wie erwartet

      <image class="svg svg--gradient-test"/>
      

      Mittlerweile bin ich beim clipPath angekommen. Nur schaffe ich es so auch nicht eine Form auszuschneiden und nur innerhalb der Form den Gradienten der SVG darzustellen.

      Gruß
      Jo

  2. Hey,

    Ich habe mein Ziel fast erreicht.

    Dabei verstehe ich aber nicht warum das SVG unbedingt eine Größe haben muss (und auch nicht display: none; gesetzt werden darf) und warum der clipPath nicht zu der Größe des <div> skaliert.

    Gruß
    Jo

  3. Hey,

    ich habe es selber gelöst ohne SVG und rein mit CSS.

    Gruß
    Jo

    1. Hallo Jo,

      ich war schon drauf und dran, Dir die CSS-Varianten zu empfehlen, dachte mir aber, dass Du ggf. unbedingt SVG willst weil der clip-path mit CSS Mitteln nicht zu spezifizieren ist (Beispiel: ein clipPath mit mehreren Kreisen).

      Dass das SVG eine Größe von 0 haben muss, hat den Sinn, dass es nicht sichtbar ist. Du hast es ja im HTML drin. Würdest Du das SVG als externe URL laden, dann würde ich annehmen, dass das unötig ist.

      Der clipPath aus dem SVG skaliert nicht, weil die clipPathUnits falsch sind. Der Default ist userSpaceOnUse, was laut MDN angibt, dass „all coordinates inside the <clipPath> element refer to the user coordinate system as defined when the clipping path was created.“. Das habe ich nicht wirklich verstanden, denn dann müsste der clipPath mit der Größe des SVG skalieren. Tut er aber nicht.

      Der andere mögliche Wert für clipPathUnits ist objectBoundingBox. Dann skaliert der clipPath mit dem Container, in dem er sich befindet. Wichtig ist dann nur, dass die Größe des Containers in x- und y-Richtung mit 1 angenommen wird, d.h. Du gibst deine Maße als Werte zwischen 0 und 1 an.

      Fiddle: Clippath aus 4 Kreisen

      Rolf

      --
      sumpsi - posui - clusi