Ist es möglich, einen gruppierten Pfad in SVG mit linearem Farbverlauf zu füllen (durch CSS oder Attr bei jQuery-Ereignis)?

Lesezeit: 7 Minuten

Benutzeravatar von Répás
Repás

Wie kann ich einen Farbverlauf für a füllen? <g> in einem SVG-Bild, anstatt alles auszufüllen <g>s in der ausgewählten <g>?

In diesem Fall möchte ich Afrika zeigen, gefüllt mit nur einem Farbverlauf von Gelb nach Rot, aber aufgrund der Untergruppen erzeugt die Füllung viele Farbverläufe.

Das Javascript:

<script type="text/javascript">
function svgOver() { 
    var what = $(this).attr("id");
    $("#world #"+what, svg.root()).attr("fill", "url(#red_black)"); 
} 
function svgOut() { 
    $(this).attr("fill", "");
}

...

$("#map").svg({ 
    loadURL: 'http://teszt.privilegetours.hu/skins/privilege/svg/worldmap.svg',
        onLoad: function(svg) { 
        $("#world > g", svg.root()).bind('mouseover', svgOver).bind('mouseout', svgOut).bind('click', svgZoom);
        },
    settings: {}
});

Das SVG:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" mlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="570px" height="300px" viewBox="146.605 71.42 570 300" enable-background="new 146.605 71.42 570 300" xml:space="preserve">

<defs>
    <linearGradient id="red_black" x1="0%" y1="0%" x2="0%" y2="100%">
        <stop offset="0%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
        <stop offset="100%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
    </linearGradient>
</defs>

<g id="world" transform="scale(1)" fill="#AAAAAA" stroke="#FFFFFF" stroke-width="0.1">
    <g id="africa" name="africa"> // < i want to fill this
        <g id="er" transform="translate(-29.9017, -45.0745)"> // < instead of theese
            <path d="..."/>
        </g>
        <g id="yt"> // < instead of theese
            <path d="..."/>
        </g> 
        ...

Das ist Afrika

Wie kann ich dieses Problem beheben?
Wie kann ich dieses Problem beheben, ohne ein weiteres hinzuzufügen? <g> Tag zum Originalbild hinzufügen?

  • Können Sie auf ein Online-Beispiel verlinken? Ich denke, das Problem liegt möglicherweise eher in Ihrem CSS als in Ihrer SVG-Datei. Ich möchte mir nur das Ganze ansehen.

    – Robertc

    29. März 2011 um 14:09

  • Sie können das Beispiel also nicht online verlinken? Wo ist der Code, auf den Sie den Stil anwenden? #africa?

    – Robertc

    30. März 2011 um 10:04

  • $("#world #"+what, svg.root()).attr("fill", "url(#red_black)"); 1. Box Zeile 4

    – Répás

    30. März 2011 um 11:33

  • Aber das machen Sie nur beim Mouseover: $("#world > g", svg.root()).bind('mouseover', svgOver). Kann man das ganze online wirklich nicht verlinken?

    – Robertc

    30. März 2011 um 13:37 Uhr

  • Nun, wie Sie sehen können, wann $("#world > g", svg.root()).bind('mouseover', svgOver) bindet die mouseover event übergibt die ID des Elements an die svgOver() Funktion. Also die svgOver wird gleich sein mit $("#world #africa", svg.root()).attr("fill", "url(#red_black)");. Der url(#red_black) wird aus dem SVG ausgewählt, (<defs>). Eigentlich habe ich keine Berechtigung, die gesamte Website zu teilen. Ich werde später eine Kopie davon erstellen und sie teilen.

    – Répás

    30. März 2011 um 13:46 Uhr


Benutzeravatar von collapsar
zusammenbrechen

Ihr Problem kann gelöst werden, indem Sie das Farbverlaufskoordinatensystem auf den Benutzerbereich einstellen (anstelle des standardmäßigen Objektbegrenzungsrahmens).

Du könntest es versuchen

<defs>
    <linearGradient id="red_black" x1="0%" y1="0%" x2="0%" y2="100%" gradientUnits="userSpaceOnUse">
        <stop offset="0%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
        <stop offset="100%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
    </linearGradient>
</defs>

Die Lösung widerspricht nicht dem Kommentar von e.nelson – was hier passiert, ist, dass auf jede Untergruppe, die die Nationen repräsentiert, immer noch ihre individuelle Gradienteninstanz angewendet wird, während alle diese Instanzen denselben Koordinatenursprung und dieselben Transformationen in Bezug auf den Benutzerraum haben – also überhaupt Punkt im endgültigen Rendering spielt es keine Rolle, welche Verlaufsinstanz sichtbar ist.

Es sind zwei Anpassungen erforderlich:

  1. [ minor]

    Sie müssen die Y1/Y2-Offsets (oder die Stopp-Offsets) der Gradientendefinition anpassen – da sie sich auf den Benutzerkoordinatenraum der gesamten Karte beziehen, deckt Afrika nur einen Teil des Gradienten zwischen den definierten Stopps ab. versuchen y1="50%" Und y2="100%".

  2. [medium]

    Wenn Sie sich die SVG-G-Elemente ansehen, die die Länderformen definieren, werden Sie feststellen, dass einige davon einer zusätzlichen Übersetzung unterliegen. Sie verschieben effektiv das Benutzerkoordinatensystem und wirken sich daher auch auf den Farbverlauf aus, wodurch die betroffenen Länderformen auf der Karte wie Flecken erscheinen. Diese Spurios-Transformation ist wahrscheinlich ein Artefakt der Aktionen im Generator, der zum Erstellen der Karte verwendet wurde. Dies kann durch Hinzufügen der Übersetzungsoffsets zu jedem behoben werden absolut Koordinate in den Pfadelementen innerhalb der jeweiligen g-Elemente. Da diese Pfade mithilfe relativer Koordinaten für die zusammengenähten Teile definiert werden, reduziert sich dies auf die Änderung der Koordinaten der anfänglichen „M“- und letzten „C“-Befehle im d-Attribut des Pfads.

Ich habe ein Ad-hoc-Perl-Skript erstellt, um die Struktur des SVG-Codes zu normalisieren, der die Landesgrenzen darstellt und die oben genannten Änderungen implementiert. Beachten Sie, dass diese Änderungen auch recht bequem in js durchgeführt werden können. Das ist das Ergebnis.

Ich hoffe, das hilft und schreiben Sie mir eine Nachricht, wenn Sie zusätzliche Informationen zur Durchführung der genannten Anpassungen benötigen.

PS: Mir ist gerade aufgefallen, dass Mosambik in der generierten Ausgabe immer noch fehlt – für die Form dieses einzelnen Landes wurde noch eine andere Übersetzung angegeben. Dieses kleine Detail soll jedoch später noch hinzugefügt werden …

Ergebnis

  • Nun ja, ich bin total erstaunt. arbeiten daran. Haben Sie irgendwelche Programme, mit denen ich eine M-lose und übersetzte Version meiner Karte erstellen kann? Danke, Répás

    – Répás

    4. April 2011 um 8:22

  • Ich habe ein Perl-Skript. PS: Heute habe ich einen vollen Terminkalender, daher werde ich wahrscheinlich erst morgen bei Stackoverflow sein. cu, Carsten

    – zusammenklappen

    4. April 2011 um 10:02


  • Ein großes Lob und +1, tolle Lösung.

    – Elliot Nelson

    6. April 2011 um 1:01

  • @repas: Entschuldigung für die lange Latenz – ich war letzte Woche viel beschäftigter als erwartet … die Skript-URL lautet collapsar.co.ohost.de/data/astcko.03.cleanse.pl; In den Zeilen 64ff müssen Sie die Pfade zu Ihrem lokalen Dateisystem anpassen. $fclone ist das Original, $fres der Zieldateiname, $workdir … nun ja … 😉 (aus historischen Gründen seltsame ID-Namen …). Beste Grüße, Carsten

    – zusammenklappen

    12. April 2011 um 22:16 Uhr

  • @collapsar ohai. Links sind tot.

    – GottZ

    8. Dezember 2015 um 13:21

„Das Malen erfolgt jedoch immer für jedes Grafikelement einzeln, niemals auf der Ebene des Containerelements (z. B. ein ‚g‘). Daher gilt für das folgende SVG, auch wenn die Farbverlaufsfüllung auf dem ‚g‘ angegeben ist Der Farbverlauf wird einfach durch das „g“-Element in jedes Rechteck vererbt, wobei jedes Rechteck so gerendert wird, dass sein Inneres mit dem Farbverlauf bemalt wird.“

http://www.w3.org/TR/SVGTiny12/painting.html#InheritanceOfPaintingProperties

Was Sie verlangen, ist laut Spezifikation nicht möglich. Wenn dies erforderlich ist, können Sie Folgendes ausprobieren: Lassen Sie den SVG-Ersteller Mouseover-Pfade für Sie hinzufügen. Kombinieren Sie die Pfade im Code auf dem Server (möglicherweise schwierig); Wählen Sie eine Volltonfarbe anstelle eines Farbverlaufs, damit das Problem nicht so offensichtlich ist.

Wenn Sie ganz Afrika mit einem Farbverlauf füllen möchten, dann möchten Sie, dass die Union die Wege dafür füllt. Vielleicht solltest du eine andere Karte verwenden? Eines mit nur den Kontinenten?

Wie auch immer, eine Möglichkeit, das Problem zu beheben, wäre:

  1. Öffnen Sie es in Inkscape
  2. Wählen Sie alle Pfade aus, die Sie füllen möchten
  3. Wählen Sie „Vereinigung“ aus dem Menü „Pfad“.
  4. Speichern Sie die Datei (oder kopieren Sie den vereinigten Pfad und fügen Sie ihn ein).

Ein anderer Weg:

  1. Suchen Sie nach einer anderen Karte, siehe http://d-maps.com/ oder http://commons.wikimedia.org. Hier ist einer mit dem Nur Kontinente, Afrika markiert.

Anschließend können Sie den Farbverlauf auf diesen neuen Pfad anwenden.

Sie könnten es auch auf andere Weise tun, diese sind jedoch aus Leistungsgründen wahrscheinlich nicht so gut. Eine dieser (nicht empfohlenen) Möglichkeiten wäre, ein Rechteck mit dem Farbverlauf zu füllen, wo Sie einen Clip-Pfad erstellt haben, der aus den Pfaden in der Gruppe besteht. Etwas in dieser Richtung:

<clipPath id="clip">
  <use xlink:href="#africa"/>
</clipPath>
<rect width="100" height="100" fill="url(#grad)" clip-path="url(#clip)"/>
<g id="africa">...</g>

  • Diese Karte hat einige andere Javascripte … 😀 Verschieben, Auswählen usw. Ich kann also nicht den anderen Weg wählen, 1. auch nicht, weil. Jetzt hatte ich eine Idee mit einem unsichtbaren Gewerkschaftspfad. 🙂 Du wirst mich später sehen.

    – Répás

    30. März 2011 um 20:02 Uhr

  • Beachten Sie, dass SVG-Gruppen in clip-paths haben keine Wirkung. clip-paths dürfen nur enthalten Grundformen, text oder path Elemente bzw use-Referenzen, die direkt darauf verweisen.

    – Simon

    5. Juli 2021 um 14:11 Uhr

Ich denke, Ihr Problem könnte darin liegen fill wird vererbt entsprechend der Standardregeln von CSS in SVG. Sie müssten also ein explizites festlegen fill von transparent auf das Kind g Elemente. Wenn nicht, komme ich zurück und schaue mir das noch einmal an, nachdem Sie ein Online-Beispiel haben.

1452180cookie-checkIst es möglich, einen gruppierten Pfad in SVG mit linearem Farbverlauf zu füllen (durch CSS oder Attr bei jQuery-Ereignis)?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy