Простий шаблон заповнення в svg: діагональне штрихування


77

Як би я заповнив форму SVG не одним кольором, зображенням чи градієнтом, а малюнком штрихування, діагональним, якщо це можливо.

Минуло 2 години, а я нічого не знайшов (принаймні після 2005 року).

Я вважаю, що можливим злому буде штрихований PNG, який буде служити заповненням, але це не ідеально.


Люди по- як і раніше шукають рішення діагональної штрихуванням могли б хотіти , щоб почати тут замість: stackoverflow.com/a/22401717/1717535
Фаб'єн Snauwaert

Ось чудова скрипка, яку я знайшов, роблячи це jsfiddle.net/h5NMP
Джон Ктеджік

Відповіді:


126

Я також не знайшов нічого для діагонального штрихування в Інтернеті, тому поділюсь своїм рішенням тут:

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

4
Мені довелося додати стиль до шляху у шаблоні, щоб він став видимим: наприклад (наприклад, akarve): style = "stroke: black; stroke-width: 1"
lode

1
Коли я спробував збільшити цей шаблон до 20 х 20 пікселів (з обведенням 8 пікселів) і протестував результат із більшим масштабуванням, з’явився ефект кутового відсікання «рядок ковбас». Я зміг це виправити, зробивши кутові лінії довшими, наприклад M 0 0 L 20 20 M 10 -10 L 30 10 M -10 10 L 10 30.
hon2a

3
Ефект "нитки ковбас" може бути викликаний згладжуванням. Спробуйте додати shape-rendering="cripsEdges".
Девід Р.

2
@Ingo Kegel Пробачте мене за запитання, але я не можу знайти пояснення в Інтернеті, як я зміню параметри, щоб мати відстань 10, а не 4?
Тім Чарівник

3
Дякую! Це було таке просте рішення. Я також можу легко перейти stroke:blackна stroke:#386cb0. Але як мені змінити фон?
Liggliluff

67

Використовуйте атрибут patternTransform, щоб повернути вертикальний (або горизонтальний) відрізок лінії. Цей метод безперешкодно викладає плитки та використовує найпростіший можливий шлях. Атрибут pattern 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>

5
На сьогоднішній день найкраще рішення: просте (відсутність складної геометрії) та гнучке (можна встановити будь-який кут повороту, а widthатрибут візерунка встановлює зазор між смугами). Щоб зробити це ще простішим, я б використав <line x1="0" y1="0" x2="0" y2="2" style="stroke:black; stroke-width:1" />замість <g>...</g>.
Девід Боннет

1
Мені подобається це рішення, але наразі в FF є помилка (v 31.0, OSX). Коли ви обертаєте шаблон, з’являються маленькі білі лінії.
jasongonzales

1
Привіт, чи можна встановити колір тла прямокутника, який використовує цей шаблон?
Yannic Klem

3
@YannicKlem, щоб встановити колір фону, додати <rect x="0" y="0" width="10" height="10" style="fill:skyblue"/>перед <line/>.
medmunds

1
Ще простіше: використовуйте <rect>замість <line>і зробіть розмір візерунка 10х1 замість 10х10.
donquixote

15

Можливо, ви зможете створити те, що хочете, за допомогою <pattern>тегу.

Як вихідну точку ви можете взяти цей приклад відповідного документа MDN :

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


1
Дякую. Мені не вистачало patternUnits = "userSpaceOnUse". Без цього мій зразок взагалі не з'являвся.
Пол Черноч,

14

Цей код з 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>


7

Однією з проблем малювання діагональної лінії у візерунку є те, що коли візерунок викладений плиткою, лінії не завжди вишикуються - особливо при великому масштабуванні. (Це залежить від механізму візуалізації SVG, яким ви випадково користуєтесь). Відповідь @ Інго вище намагається вирішити це, намалювавши трикутники у верхньому лівому та нижньому правому кутах - але знову ж таки, використовуючи деякі механізми візуалізації та велике масштабування, це не завжди виглядає найкраще - і іноді рядок закінчується виглядом трохи схожа на нитку ковбас.

Інший підхід полягає у проведенні горизонтальної лінії на малюнку та обертанні малюнка, наприклад

  <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
+1 від мене, я виявив, що не використовував префікс простору імен svg, який мені потрібен, щоб переконатись, що використовую <patter>, а не <svg: pattern>
Alex KeySmith


4

Це рішення для діагональних ліній з використанням кола в шаблоні. Ви можете змінити кут нахилу відповідно до ваших вимог.

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

це працювало дуже добре і було просто для редагування. Чи є спосіб зробити двоколірне штрихування? Напр. з основним кольором смужки та фоном?
Едвард

3

Я спробував із цим зразком. Сподіваємось, це може вам дуже допомогти.

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

З повагою, Ву Фан


1

SVG 2 має hatchсутність для цієї мети. З прикладу розділу цієї сторінки:

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

Це дуже легко налаштовуваний спосіб створення люків:

Ілюстрація тегу штрихування з w3c

Крім того, шлях штрихування також можна налаштувати:

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

Ну так, але насправді це ніхто не реалізував, чи не так?
Роберт Лонгсон,

@RobertLongson Ну, я переважно використовую svg як проміжний формат і компілюю його у pdf (наприклад, я використовую inkscape як компілятор). І inkscape, безумовно, реалізує це, хоча може не видавати такий код самостійно. Ви маєте рацію, що firefox не вдається правильно застосувати люки. Я не знаю про інші браузери.
bitmask

0

Для React Native можна використовувати цей компонент для створення шаблону фонових ліній. Ви повинні додати до свого проекту response-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, будь ласка?
amit pandya

0

Я адаптував відповідь Інго тут .

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

Шлях до фону навмисне надто широкий, так що жодна частина візерунка не принаймні покрита фоном. Тим часом ширина люків може бути налаштована, щоб змінити товщину ліній.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.