【问题标题】:Making a responsive angled svg shape with pattern制作带有图案的响应式倾斜 svg 形状
【发布时间】:2017-04-19 22:11:28
【问题描述】:

我正在尝试创建一个 SVG 形状,它是一种可图案化的路径。我面临的问题是末端需要有角度,并且元素需要响应(角度保持不变,但元素的长度会发生变化)。

我最初只使用 HTML 和 CSS,但必须使用前后元素创建角度,这意味着无法让图案对齐。因此,我为什么要寻找 SVG 解决方案。

以下是元素的外观:

我最接近的尝试是一个 rect 元素,它有一个使用路径的 clip-path 引用。问题是元素必须是响应式的,但路径不能定位在“最右边”。

我确实有 d3 可供我使用,但我不确定这是否能减轻复杂性。如何创建这种响应式图案形状?

【问题讨论】:

    标签: html css d3.js svg


    【解决方案1】:

    可以在 SVG 中使用 <use> 元素的技巧来做到这一点。

    <svg width="100%" height="50px">
      <defs>
        <pattern id="stripes" patternUnits="userSpaceOnUse" width="50" height="50">
          <path d="M-10,20 L20,-10
                   M-10,45 L45,-10
                   M0,60 L60,0
                   M25,60 L60,25" fill="none" stroke="lightgrey" stroke-width="10"/>
        </pattern>
        <clipPath id="leftarrow">
          <path d="M15,0 L0,25,15,50,5000,50,5000,0 Z"/>
        </clipPath>
        <path id="rightarrowpath" d="M-15,0 L0,25,-15,50,-5000,50,-5000,0 Z"/>
        <clipPath id="rightarrow">
          <use xlink:href="#rightarrowpath" x="100%"/>
        </clipPath>
      </defs>
    
      <g clip-path="url(#leftarrow)">
        <rect width="100%" height="50" fill="url(#stripes)"
              clip-path="url(#rightarrow)"/>
      </g>
    </svg>

    这是如何工作的

    首先,我们将 SVG 定义为 100% 宽度,以便填充容器。我们添加一个相同大小(100% x 50px)的矩形。 SVG 没有viewBox,因为我们不希望进行任何拉伸。

    现在我们需要将矩形裁剪成左右箭头形状。左箭头很简单,因为我们可以定义一个真正宽的剪切路径,箭头部分位于x=0。只要够宽,应该没问题。

    <svg width="100%" height="50px">
      <defs>
        <pattern id="stripes" patternUnits="userSpaceOnUse" width="50" height="50">
          <path d="M-10,20 L20,-10
                   M-10,45 L45,-10
                   M0,60 L60,0
                   M25,60 L60,25" fill="none" stroke="lightgrey" stroke-width="10"/>
        </pattern>
        <clipPath id="leftarrow">
          <path d="M15,0 L0,25,15,50,5000,50,5000,0 Z"/>
        </clipPath>
      </defs>
    
      <rect width="100%" height="50" fill="url(#stripes)"
            clip-path="url(#leftarrow)"/>
    </svg>

    不幸的是,右手箭头并不那么直。原因是我们希望箭头自动定位在 SVG 的右侧(即 100% 宽度)。但是&lt;path&gt; 定义不允许百分比。而且我们也不能使用transform 来获取它,因为您也不能在转换中使用百分比。

    幸运的是,有一种“漏洞”技术。 &lt;use&gt; 元素允许我们提供一个偏移量(xy)来定位它所引用的元素。而那些属性确实允许百分比。

    所以我们要做的是定义右箭头剪辑路径,使其右侧边缘位于 x=0,然后我们使用 &lt;use&gt; 元素将其定位为 100%。

    <svg width="100%" height="50px">
      <defs>
        <pattern id="stripes" patternUnits="userSpaceOnUse" width="50" height="50">
          <path d="M-10,20 L20,-10
                   M-10,45 L45,-10
                   M0,60 L60,0
                   M25,60 L60,25" fill="none" stroke="lightgrey" stroke-width="10"/>
        </pattern>
        <path id="rightarrowpath" d="M-15,0 L0,25,-15,50,-5000,50,-5000,0 Z"/>
        <clipPath id="rightarrow">
          <use xlink:href="#rightarrowpath" x="100%"/>
        </clipPath>
      </defs>
    
      <rect width="100%" height="50" fill="url(#stripes)"
            clip-path="url(#rightarrow)"/>
    </svg>

    我们需要做的就是结合这两种技术来获得我们的双端(和响应式)图案箭头。但是,由于矩形不能有两个剪切路径,我们必须将它包装在一个组中,并将其中一个剪切路径应用到该组中。

    最终结果是这个答案顶部的例子。

    【讨论】:

    • 谢谢!我被困在无法正确定位路径的地方(变换或百分比)。我从未想过使用use 元素。感谢您为此付出的所有时间。
    • 优秀的答案!你已经包含了完美的细节。
    【解决方案2】:

    这是一个 HTML/CSS 解决方案。

    我们所做的是transform(support) 两个元素和skew() 来创建尖端。您可以在下面看到红色的父 DIV 创建点的一侧,子元素通过向相反方向倾斜创建另一侧。在最终解决方案中,我们从父元素中移除背景。

    div {
      height: 25px;
      transform: skew( 25deg );
      overflow: hidden;
      position: relative;
      background-color: indianred;
    }
    div:before {
      content: '';
      display: block;
      height: 100%;
      background-color: rebeccapurple;
      transform: skew( -42deg );
    }
    &lt;div&gt;&lt;/div&gt;

    然后我们使用repeating lindear gradient (support) 来创建有角度的细条纹。

    div {
      height: 25px;
      transform: skew( 25deg );
      overflow: hidden;
      position: relative;
    }
    
    div:before {
      content: '';
      display: block;
      height: 100%;
      background: repeating-linear-gradient(
        35deg,
        transparent,
        transparent 3px,
        lightgray 3px,
        lightgray 6px
      );;
      transform: skew( -42deg );
    }
    &lt;div&gt;&lt;/div&gt;

    【讨论】:

      猜你喜欢
      • 2020-09-25
      • 2022-01-19
      • 2020-04-12
      • 1970-01-01
      • 2019-03-06
      • 2020-03-06
      相关资源
      最近更新 更多