【问题标题】:Simple fill pattern in svg : diagonal hatchingsvg中的简单填充图案:对角线阴影
【发布时间】:2012-10-15 16:29:42
【问题描述】:

我将如何填充 SVG 形状,而不是使用单一颜色、图像或渐变,而是使用阴影图案,如果可能的话,对角线。

2 小时过去了,我什么也没找到(至少在 2005 年之后)。

我认为可能的 hack 将是一个带阴影的 PNG 作为填充,但这并不理想。

【问题讨论】:

标签: svg


【解决方案1】:

我也没有在互联网上找到任何关于对角线孵化的东西,所以我将在这里分享我的解决方案:

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

(注意路径表达式中的小写“l”)

上面创建了一个从左下角到右上角相距 4 像素的对角线的阴影。除了对角线 (M0,4 l4,-4) 之外,您还必须描边图案区域的左上角和右下角边缘,否则该线会因为与正方形边缘相交的位置被剪裁而“收缩”。

要用这种图案填充矩形,请执行以下操作:

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

【讨论】:

  • 我必须在模式中的路径中添加一个样式,让它变得可见:例如(如 akarve):style="stroke:black; stroke-width:1"
  • 当我尝试将这个图案放大到 20 x 20 px(8px 笔画)并在更高的缩放下测试结果时,出现了剪角“香肠串”效果。我可以通过延长角线来修复它,例如M 0 0 L 20 20 M 10 -10 L 30 10 M -10 10 L 10 30.
  • “香肠串”效果可能是由抗锯齿引起的。尝试添加shape-rendering="cripsEdges"
  • @Ingo Kegel 请原谅我的提问,但我在网上找不到解释,如何将参数更改为距离为 10 而不是 4?
  • 谢谢!这是一个非常简单的解决方案。我也可以轻松地将stroke:black 更改为stroke:#386cb0。但是如何改变背景呢?
【解决方案2】:

使用 patternTransform 属性旋转垂直(或水平)线段。此方法无缝拼接并使用最简单的路径。图案width 属性控制平行影线的接近程度。

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

【讨论】:

  • 目前最好的解决方案:简单(没有复杂的几何形状)和灵活(可以设置任何旋转角度,width 图案属性设置条纹之间的间隙)。为了更简单,我会使用&lt;line x1="0" y1="0" x2="0" y2="2" style="stroke:black; stroke-width:1" /&gt; 代替&lt;g&gt;...&lt;/g&gt;
  • 我喜欢这个解决方案,但目前 FF (v 31.0, OSX) 中存在一个错误。旋转图案时,会出现小白线。
  • 你好,可以设置使用这种图案的矩形的背景颜色吗?
  • @YannicKlem 设置背景颜色,在&lt;line/&gt; 之前添加&lt;rect x="0" y="0" width="10" height="10" style="fill:skyblue"/&gt;
  • 更简单:使用&lt;rect&gt; 代替&lt;line&gt;,并使您的图案尺寸为10x1 而不是10x10。
【解决方案3】:

您可以使用&lt;pattern&gt; 标签创建您想要的内容。

作为起点,您可以以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>

【讨论】:

  • 谢谢。我错过了 patternUnits="userSpaceOnUse"。没有它,我的模式根本不会出现。
【解决方案4】:

http://bl.ocks.org/jfsiii/7772281 的这段代码看起来非常干净且可重复使用:

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>

【讨论】:

    【解决方案5】:

    在图案中绘制对角线的一个问题是,当图案平铺时,线条并不总是对齐 - 特别是在高缩放时。 (这取决于您碰巧使用的 SVG 渲染引擎)。 @Ingo 上面的答案试图通过在左上角和右下角绘制三角形来解决这个问题 - 但同样,使用一些渲染引擎和高缩放,它并不总是看起来最好 - 有时这条线最终看起来有点像一串香肠。

    另一种方法是在图案中画一条水平线并旋转图案,例如

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

    【讨论】:

    • +1 来自我,我发现如果我没有使用 svg 命名空间前缀,我需要确保我使用的是 而不是
    【解决方案6】:

    这两个资源非常有用: https://bocoup.com/weblog/using-svg-patterns-as-fills https://github.com/iros/patternfills/blob/master/public/patterns.css

    例如:

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

    【讨论】:

      【解决方案7】:

      这是使用圆形图案的对角线的解决方案。您可以根据需要更改角度。

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

      【讨论】:

      • 这非常好用并且易于编辑。有没有办法进行两种颜色的孵化?例如。具有主条纹颜色和背景颜色?
      【解决方案8】:

      我尝试使用此示例。希望对您有很大帮助。

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

      问候, 武潘

      【讨论】:

        【解决方案9】:

        SVG 2 有一个 hatch entity 专门用于此目的。从该页面的示例部分:

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

        这是一种非常容易配置的方式来创建影线:

        另外hatch path也可以自定义:

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

        【讨论】:

        • 确实有,但实际上没有人实现它吗?
        • @RobertLongson 好吧,我主要使用 svg 作为中间格式并将其编译为 pdf(例如,我使用 inkscape 作为编译器)。而inkscape当然实现了它,尽管它可能不会自己发出这样的代码。您是正确的,Firefox 未能正确实现影线。其他浏览器我不知道。
        【解决方案10】:

        React Native 使用可以使用该组件,用于制作背景线条图案。 你应该添加到你的项目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>
          }
        }
        

        【讨论】:

        • 非常感谢。这对我帮助很大。你能帮我在 Android 启动画面中做同样的事情吗?
        【解决方案11】:

        我已经适应了Ingo'sanswer 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>
        

        此图案包括两条路径,一条用于背景,另一条用于影线。背景颜色与 JS 相比是可寻址的,例如:

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

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

        背景路径故意过宽,因此图案的任何部分都至少被背景覆盖。同时,可以调整影线的宽度以改变线条的粗细。

        【讨论】:

          猜你喜欢
          • 2018-01-01
          • 2012-06-14
          • 2015-06-03
          • 2018-10-14
          • 2021-09-01
          • 2022-01-03
          • 1970-01-01
          • 2013-09-06
          • 2015-12-08
          相关资源
          最近更新 更多