SVG, polygon mit linear-gradient
J o
- css
- javascript
- svg
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
Hallo Jo,
was ich vermisse, du aber vielleicht nur nicht gepostet hast, ist
Bei clientseitigen Fehlschlägen aller Art sollte man die Entwicklerwerkzeuge des Browsers öffnen und
Rolf
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
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
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