Einfaches Füllmuster in SVG: diagonale Schraffur

76

Wie würde ich eine SVG-Form füllen, nicht mit einer einzelnen Farbe, einem Bild oder einem Farbverlauf, sondern mit einem Schraffurmuster, wenn möglich diagonal.

Es ist 2 Stunden her und ich habe nichts gefunden (zumindest nach 2005).

Ich denke, ein möglicher Hack wäre ein schraffiertes PNG, das als Füllung dienen würde, aber das ist nicht ideal.

Cystack
quelle
Leute, die immer noch nach einer Lösung für diagonale Schraffuren suchen, möchten vielleicht stattdessen hier beginnen: stackoverflow.com/a/22401717/1717535
Fabien Snauwaert
Hier ist eine großartige Geige, die ich dabei gefunden habe jsfiddle.net/h5NMP
john ktejik

Antworten:

123

Ich habe auch im Internet nichts für diagonale Schraffuren gefunden, daher werde ich meine Lösung hier teilen:

<pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4">
  <path d="M-1,1 l2,-2
           M0,4 l4,-4
           M3,5 l2,-2" 
        style="stroke:black; stroke-width:1" />
</pattern>

(Beachten Sie den Kleinbuchstaben "l" im Pfadausdruck)

Das Obige erzeugt eine Schraffur mit diagonalen Linien von links unten nach rechts oben, die 4 Pixel voneinander entfernt sind. Neben der diagonalen Linie ( M0,4 l4,-4) müssen Sie auch den oberen linken und den unteren rechten Rand des Musterbereichs streichen, da die Linie sonst aufgrund von Übersteuerungen, die die Kanten des Quadrats schneiden, "eingeengt" wird.

Ein Beispiel für ein Muster nach dem Anwenden der obigen Schritte zeigt, wie das Muster, mit dem es betitelt wurde, das Endprodukt ergibt

Um ein Rechteck mit diesem Muster zu füllen, gehen Sie wie folgt vor:

<rect x="0" y="0" width="100%" height="100%" fill="url(#diagonalHatch)"/>
Ingo Kegel
quelle
4
Ich musste dem Pfad im Muster einen Stil hinzufügen, damit er sichtbar wurde: zum Beispiel (wie akarve): style = "Strich: schwarz; Strichbreite: 1"
Lode
1
Als ich versuchte, dieses Muster auf 20 x 20 px (mit 8 px Strich) zu vergrößern und das Ergebnis bei höherem Zoom zu testen, erschien der Effekt "Wurstkette". Ich konnte es beheben, indem ich die Ecklinien verlängerte, z M 0 0 L 20 20 M 10 -10 L 30 10 M -10 10 L 10 30.
Hon2a
3
Der Effekt "Würstchen" kann durch Anti-Aliasing verursacht werden. Versuchen Sie es hinzuzufügen shape-rendering="cripsEdges".
David R.
1
@Ingo Kegel Verzeihen Sie mir, dass ich gefragt habe, aber ich kann online keine Erklärung finden. Wie würde ich die Parameter ändern, um einen Abstand von 10 statt 4 zu haben?
Tim der Verzauberer
1
Ändern Sie den Pfad zuM-1,1 l2,-2 M0,10 l10,-10 M9,11 l2,-2
Ingo Kegel
64

Verwenden Sie das Attribut patternTransform, um ein vertikales (oder horizontales) Liniensegment zu drehen. Diese Methode kachelt nahtlos und verwendet den einfachsten Pfad. Das Musterattribut widthsteuert, wie eng parallele Schraffuren sind.

<pattern id="diagonalHatch" width="10" height="10" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
  <line x1="0" y1="0" x2="0" y2="10" style="stroke:black; stroke-width:1" />
</pattern>
akarve
quelle
4
Bisher beste Lösung: einfach (keine komplexe Geometrie) und flexibel (jeder Drehwinkel kann eingestellt werden und das widthMusterattribut legt den Abstand zwischen den Streifen fest). Um es noch einfacher zu machen, würde ich <line x1="0" y1="0" x2="0" y2="2" style="stroke:black; stroke-width:1" />anstelle von verwenden <g>...</g>.
David Bonnet
1
Ich liebe diese Lösung, aber es gibt derzeit einen Fehler in FF (v 31.0, OSX). Wenn Sie das Muster drehen, erscheinen kleine weiße Linien.
Jasongonzales
1
Hallo, ist es möglich, die Hintergrundfarbe des Rechtecks ​​festzulegen, das dieses Muster verwendet?
Yannic Klem
3
@YannicKlem, um eine Hintergrundfarbe festzulegen, fügen Sie <rect x="0" y="0" width="10" height="10" style="fill:skyblue"/>vor dem <line/>.
Medmunds
1
Noch einfacher: Verwenden Sie <rect>statt <line>und machen Sie Ihre Mustergröße 10x1 statt 10x10.
Donquijote
15

Möglicherweise können Sie mithilfe eines <pattern>Tags erstellen, was Sie möchten .

Als Ausgangspunkt können Sie dieses Beispiel des jeweiligen MDN-Dokuments nehmen :

    <?xml version="1.0"?>
    <svg width="120" height="120" viewBox="0 0 120 120"
         xmlns="http://www.w3.org/2000/svg" version="1.1"
         xmlns:xlink="http://www.w3.org/1999/xlink">
     
        <defs>
            <pattern id="Triangle"
                     width="10" height="10"
                     patternUnits="userSpaceOnUse">
                <polygon points="5,0 10,10 0,10"/>
            </pattern>
        </defs>
     
        <circle cx="60" cy="60" r="50"
                fill="url(#Triangle)"/>
    </svg>

Sirko
quelle
1
Vielen Dank. Mir fehlte patternUnits = "userSpaceOnUse". Ohne sie erschien mein Muster überhaupt nicht.
Paul Chernoch
14

Dieser Code von http://bl.ocks.org/jfsiii/7772281 scheint sehr sauber und wiederverwendbar zu sein:

svg {
  width: 500px;
  height: 500px;
}

rect.hbar {
  mask: url(#mask-stripe)
}

.thing-1 {
  fill: blue;
}


.thing-2 {
  fill: green;
}
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset=utf-8 />
        <title>SVG colored patterns via mask</title>
      </head>
      <body>
        <svg>
          <defs>
            <pattern id="pattern-stripe" 
              width="4" height="4" 
              patternUnits="userSpaceOnUse"
              patternTransform="rotate(45)">
              <rect width="2" height="4" transform="translate(0,0)" fill="white"></rect>
            </pattern>
            <mask id="mask-stripe">
              <rect x="0" y="0" width="100%" height="100%" fill="url(#pattern-stripe)" />
            </mask>      
          </defs>
    
          <!-- bar chart -->
          <rect class="hbar thing-2" x="0" y="0" width="50" height="100"></rect>
          <rect class="hbar thing-2" x="51" y="50" width="50" height="50"></rect>
          <rect class="hbar thing-2" x="102" y="25" width="50" height="75"></rect>
          
          <!-- horizontal bar chart -->
          <rect class="hbar thing-1" x="0" y="200" width="10" height="50"></rect>
          <rect class="hbar thing-1" x="0" y="251" width="123" height="50"></rect>
          <rect class="hbar thing-1" x="0" y="302" width="41" height="50"></rect>
          
        </svg>
      </body>
    </html>

Nobu
quelle
7

Ein Problem beim Zeichnen einer diagonalen Linie innerhalb eines Musters besteht darin, dass beim Kacheln des Musters die Linien nicht immer ausgerichtet sind - insbesondere bei hohen Zooms. (Dies hängt von der SVG-Rendering-Engine ab, die Sie gerade verwenden.) Die obige Antwort von @ Ingo versucht, dieses Problem zu lösen, indem die Dreiecke oben links und unten rechts gezeichnet werden. Bei Verwendung einiger Rendering-Engines und hoher Zooms sieht es jedoch nicht immer am besten aus. Manchmal sieht die Linie auch so aus ein bisschen wie eine Reihe von Würstchen.

Ein anderer Ansatz besteht darin, eine horizontale Linie in das Muster zu zeichnen und das Muster zu drehen, z

  <svg:svg viewBox="0 0 100 100" version="1.1"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<svg:defs>
  <svg:pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4" patternTransform="rotate(45 2 2)">
    <svg:path d="M -1,2 l 6,0" stroke="#000000" stroke-width="1"/>
  </svg:pattern>
</svg:defs>
<svg:rect x="0" y="0" height="100" width="100" fill="url(#diagonalHatch)"/>

Mark 父
quelle
1
+1 von mir, ich fand, wenn ich nicht das svg-Namespace-Präfix verwendete, das ich brauchte, um sicherzustellen, dass ich <patter> anstelle von <svg: pattern> verwendete
Alex KeySmith
4

Dies ist eine Lösung für diagonale Linien mit Kreis im Muster. Sie können den Winkel gemäß Ihren Anforderungen ändern.

<svg width="500" height="500">
    <defs>
        <pattern id="transformedPattern"
            x="0" y="0" width="2" height="20"
            patternUnits="userSpaceOnUse"
            patternTransform="rotate(45)">

            <circle cx="1" cy="1" r="2" style="stroke: none; fill: #0000ff" />
        </pattern>
    </defs>

    <rect x="10" y="10" width="100" height="100"
        style="stroke: #000000; fill: url(#transformedPattern);" />
</svg>
Muhammad Qasim
quelle
Das hat sehr gut funktioniert und war einfach zu bearbeiten. Gibt es eine Möglichkeit, eine zweifarbige Schraffur durchzuführen? Z.B. mit einer Primärstreifenfarbe und einer Hintergrundfarbe?
Edward
3

Ich habe es mit diesem Beispiel versucht. Hoffentlich kann es Ihnen viel helfen.

<!DOCTYPE html>
<html>
  <head>
    <meta charset=utf-8 />
    <title>SVG colored patterns via mask</title>
  </head>
  <body>
    <svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <pattern id="stripes" viewBox="0,0,8,8" width="16" height="16" patternUnits="userSpaceOnUse">
          <polygon points="0,0 4,0 0,4" fill="yellow"></polygon>
          <polygon points="0,8 8,0 8,4 4,8" fill="yellow"></polygon>
          <polygon points="0,4 0,8 8,0 4,0" fill="green"></polygon>
          <polygon points="4,8 8,8 8,4" fill="green"></polygon>
        </pattern>
      </defs>
	  <rect fill="url(#stripes)" x="150" y="20" width="100" height="50" />
      <circle cx="50"  cy="50" r="50" fill="url(#stripes)"/>
    </svg>
  </body>
</html> 

Grüße, Vu Phan

Vu Phan
quelle
1

SVG 2 hat speziell für diesen Zweck eine hatchEntität . Aus dem Beispielabschnitt dieser Seite:

<hatch hatchUnits="userSpaceOnUse" pitch="5" rotate="135">
  <hatchpath stroke="#a080ff" stroke-width="2"/>
</hatch>

Dies ist eine sehr einfach zu konfigurierende Methode zum Erstellen von Luken:

Illustration des Schraffuretiketts vom w3c

Darüber hinaus kann der Schraffurpfad auch angepasst werden:

<hatchpath stroke-width="1" d="C 0,4 8,6 8,10 8,14 0,16 0,20"/>
Bitmaske
quelle
Nun, aber niemand hat es tatsächlich implementiert, oder?
Robert Longson
@RobertLongson Nun, ich benutze meistens svg als Zwischenformat und kompiliere es als PDF (ich benutze zum Beispiel inkscape als Compiler). Und inkscape implementiert es sicherlich, obwohl es solchen Code möglicherweise nicht alleine ausgibt. Sie haben Recht, dass Firefox Schraffuren nicht korrekt implementiert. Ich weiß nichts über andere Browser.
Bitmaske
0

Für React Native kann diese Komponente verwendet werden, um Hintergrundlinienmuster zu erstellen. Sie sollten Ihrem Projekt react-native-svg hinzufügen

import PropTypes from 'prop-types';
import React, { PureComponent } from "react";
import { View } from "react-native";
import Svg, { Defs, Line, Pattern, Rect } from 'react-native-svg';

export default class PatternLineView extends PureComponent {

  static propTypes = {
    pattern: PropTypes.func.isRequired,
    space: PropTypes.number,
    backgroundColor: PropTypes.string,
    lineColor: PropTypes.string,
    lineWidth: PropTypes.number,
    rotation: PropTypes.number
  }

  static defaultProps = {
    pattern: () => { },
    space: 8,
    lineColor: "#D2D9E5",
    lineWidth: 3,
    rotation: 45
  }

  render() {
    const transform = `rotate(${this.props.rotation})`
    return <View style={{
      flex: 1,
      flexDirection: "row",
      height: "100%",
      width: "100%",
      position: "absolute",
      top: 0,
      start: 0,
      backgroundColor: this.props.backgroundColor
    }}>
      <Svg width="100%" height="100%">
        <Defs>
          <Pattern
            id="linePattern"
            patternUnits="userSpaceOnUse"
            patternTransform={transform}
            width={this.props.space}
            height={this.props.space}>
            <Line
              x1="0"
              y1="0"
              x2="0"
              y2="100%"
              stroke={this.props.lineColor}
              strokeWidth={this.props.lineWidth}
            />
          </Pattern>
        </Defs>

        <Rect
          fill="url(#linePattern)"
          x="0"
          y="0"
          width="100%"
          height="100%"
        />
      </Svg>
    </View>
  }
}
Walfang
quelle
0

Ich habe Ingos Antwort hier angepasst .

<defs>
    <pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4">
        <!-- background -->
        <path id="background"
            d="M-1,3 L3,-1
               M1,5 L5,1" style="stroke:pink; stroke-width:10" />
        <!-- hatches -->
        <path id="hatches"
            d="M-2,2 L2,-2
               M0,4 L4,0
               M2,6 L6,2" style="stroke:red; stroke-width:1" />
    </pattern>
</defs>

Dieses Muster enthält zwei Pfade, einen für den Hintergrund und einen für die Schraffuren. Die Hintergrundfarbe ist gegenüber JS adressierbar, z. B.:

const hatchPath = document.querySelector("path#hatches");

hatchPath.setAttribute('style', "stroke:blue; stroke-width:1")

Der Hintergrundpfad ist absichtlich zu breit, sodass kein Teil des Musters zumindest vom Hintergrund abgedeckt wird. In der Zwischenzeit kann die Breite der Luken angepasst werden, um die Dicke der Linien zu ändern.

Joe Irland
quelle