Svg 中的简单填充模式: 对角线孵化

如何填充一个 SVG 形状,不是用单一的颜色,图像或渐变,而是用孵化模式,如果可能的话,对角线。

已经两个小时了,我什么也没找到(至少在2005年以后)。

我认为一个可能的黑客将是一个孵化的巴布亚新几内亚将作为填充,但这并不理想。

85197 次浏览

You may be able to create, what you want using a <pattern> tag.

As a starting point you might take this example of the respective MDN docu:

    <?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>

I did not find anything for diagonal hatching on the internet either, so I'll share my solution here:

<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>

(note the lower case "l" in the path expression)

The above creates a hatch with diagonal lines from the lower left to the upper right that are 4 pixels apart. Besides the diagonal line (M0,4 l4,-4) you also have to stroke the upper left and the lower right edges of the pattern area, since the line will otherwise be "constricted" due to clipping where it intersects the edges of the square.

Example of a pattern after applying the above steps, it shows how the pattern it titled to make the end product

To fill a rectangle with this pattern, do:

<rect x="0" y="0" width="100%" height="100%" fill="url(#diagonalHatch)"/>

One problem with drawing a diagonal line within a pattern is that when the pattern is tiled the lines won't always line up - especially at high zooms. (It depends on the SVG rendering engine you happen to be using). @Ingo's answer above attempts to resolve this by drawing in the triangles at the top-left and bottom-right corners - but again, using some rendering engines and high zooms, it doesn't always look best - and sometimes the line ends up looking a bit like a string of sausages.

Another approach is to draw a horizontal line in the pattern and rotate the pattern, e.g.

  <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)"/>

Use the patternTransform attribute to rotate a vertical (or horizontal) line segment. This method tiles seamlessly and uses the simplest possible path. The pattern width attribute controls how close parallel hatches are.

<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>

This code from http://bl.ocks.org/jfsiii/7772281 seems very clean and reusable:

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>

These two resources are very helpful: https://bocoup.com/weblog/using-svg-patterns-as-fills https://github.com/iros/patternfills/blob/master/public/patterns.css

For example:

<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'>
<rect width='10' height='10' fill='red'/>
<path d='M-1,1 l2,-2
M0,10 l10,-10
M9,11 l2,-2' stroke='orange' stroke-width='2'/>
</svg>

This is a solution for diagonal lines using circle in pattern. You can change angle as per your requirements.

<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>

I tried with this sample. Hopefully, It can help you much.

<!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> 

Regards, Vu Phan

For React Native use can use this component, for making background lines pattern. You should add to your project react-native-svg

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>
}
}

SVG 2 has a hatch entity for specifically this purpose. From that page's example section:

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

This is a very easily configurable way to create hatches:

Illustration of hatch tag from the w3c

Furthermore the hatch path can also be customised:

<hatchpath stroke-width="1" d="C 0,4 8,6 8,10 8,14 0,16 0,20"/>

I've adapted Ingo's answer here.

<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>

This pattern includes two paths, one for the background, and other for the hatches. The background color is addressable vs JS such as:

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

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

The background path is overly-wide on purpose, so that there's no part of the pattern not at least covered by the background. Meanwhile, the hatches can have their width tuned to change how thick the lines are.

Some great points got lost in the comments, so I wanted to aggregate that knowledge with some simpler inline examples. As far as I can tell, what method you choose to use is entirely up to preference since the heavy lifting is being done by patternTransform + rotate either way, but personally I think the <rect> method is easier to digest at-a-glance even if it might make more semantic sense to use <line>.


SVG Non-Scaling Pattern with <rect>

Define the spacing between your lines with the <pattern>'s width, and the width of the lines themselves via the nested <rect>'s width.

Codepen example as full-size background.

<svg height="100%" width="100%" xmlns="http://www.w3.org/2000/svg">
<pattern id="diaHatch" width="9" height="1" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<rect x="0" y="0" width="3" height="1" fill="red" />
</pattern>
<rect x="0" y="0" width="100%" height="100%" fill="url(#diaHatch)" />
</svg>


SVG Non-Scaling Pattern with <line>

Define the spacing between the <line>s with the pattern height, and use stroke-width for the <line> itself.

Codepen example as full-size background.

<svg height="100%" width="100%" xmlns="http://www.w3.org/2000/svg">
<pattern id="diaHatch" width="1" height="9" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<line x1="0" x2="100%" y1="0" y2="0" stroke-width="9" stroke="black" />
</pattern>
<rect x="0" y="0" width="100%" height="100%" fill="url(#diaHatch)" />
</svg>


On SVG 2 & Hatches [as of October 2022]

While the above examples solve the issue, SVG 2's Hatches (Candidate Recommendation 2016) are a documented method of tackling this exact issue. Inkscape happens to implement them because one of its developers, Tavmjong Bah, was an Invited Expert at the time, but browsers are still tackling them. To note, the latest Editor's Draft (2018) doesn't include hatch, which doesn't necessarily mean anything, but might be why it hasn't yet been prioritized by browser vendors.


Tracking SVG 2 Features for the Browser

Each major engine has an ongoing thread for feature implementations: