> [Site index](https://perfectvector.com/llms.txt) — available pages and descriptions.

# Kreskowanie SVG: rzeczywiste ścieżki dla plotera pisakowego

> Generuj otwarte ścieżki kreskowania z zamkniętego SVG. Odtwórz kontrole otworów, odstępów, kąta i zapisanego pliku na autorskim przykładzie Paper.js.

Source: https://perfectvector.com/pl/blog/hatch-fill-svg-pen-paths

Language: pl
Author: Irene Kim
Published: 2026-10-11T08:00:00+09:00
Updated: 2026-10-11T08:00:00+09:00

Aby wypełnić SVG kreskowaniem dla plotera pisakowego, wygeneruj otwarte linie wewnątrz zamierzonego zamkniętego obszaru, podziel je na granicach i wyeksportuj pozostałe odcinki jako geometrię. Przed przygotowaniem zadania maszyny sprawdź w zapisanym pliku trasy przechodzące przez otwory lub poza kształtem.

Kolorowe wypełnienie lub pasiasty podgląd same w sobie nie dostarczają tras rysowania. Ten samouczek tworzy autorski pięcioboczny emblemat z prostokątnym otworem, używa Paper.js do przecięcia otwartych linii z tym obszarem i ponownie otwiera zapisane SVG do kontroli. Kontrole potwierdzają cyfrową geometrię linii środkowych, a nie udane fizyczne rysowanie.

## 1. Wybierz obszar do wypełnienia, a nie linię do odzyskania

Potrzebujesz zamkniętego obszaru, którego otwory należą do geometrii. Biały prostokąt nad pełnym kształtem może wyglądać jak otwór, pozostawiając obszar pod spodem nietknięty. [Dokumentacja kreskowania GRBL-Plotter](https://grbl-plotter.de/index.php?id=hatch-fill) pokazuje różnicę między nakładającymi się obiektami a otworem wewnątrz jednej ścieżki. Nie uruchamialiśmy tutaj GRBL-Plotter.

Jeśli chcesz odzyskać pojedynczą kreskę przez środek grubej linii rastrowej, użyj [poradnika jednoliniowego SVG](https://perfectvector.com/pl/blog/drawing-to-single-line-svg). Kreskowanie tworzy wiele pociągnięć przez obszar; nie odzyskuje pierwotnej linii środkowej pisaka.

Zachowaj kopię wypełnionej grafiki. Przykład celowo tworzy trasy kreskowania bez dodawania przejścia po konturze. Jeśli chcesz też rysować zewnętrzną granicę lub granicę otworu, przygotuj je jako oddzielne, zamierzone trasy.

## 2. Odróżnij przycięty wygląd od przyciętych ścieżek

[Wzór SVG](https://www.w3.org/TR/SVG2/pservers.html#Patterns) maluje powtarzany kafelek. [Ścieżka przycinania](https://www.w3.org/TR/css-masking-1/#ClippingPaths) ogranicza renderowany obszar bez zmiany leżącej pod nim geometrii. Oba rozwiązania mogą dać użyteczny obraz ekranowy, ale aplikacja nadal potrzebuje sposobu zamiany tego wyglądu na trasy pisaka.

Wariant kontrolny z samym przycinaniem przechowuje dziesięć poziomych linii, każda długości 200 jednostek użytkownika. Przycięcie ukrywa zewnętrzne części i prostokątny otwór. Zapisane długości nadal sumują się do 2000 jednostek.

Przycięty eksport z większym odstępem zawiera 14 oddzielnych otwartych ścieżek o łącznej długości 1320 jednostek. Nie ma ścieżki przycinania, wzoru, maski, osadzonego obrazu ani ponownie użytego symbolu. Cztery wiersze kreskowania dzielą się na dwie ścieżki wokół otworu. Różnicę można sprawdzić w zapisanym SVG nawet przy podobnym wyglądzie podglądów.

![Rzeczywiście ponownie otwarte SVG porównujące podgląd kreskowania z samym przycinaniem i jawne otwarte ścieżki przy dwóch odstępach oraz kącie 30 stopni](https://perfectvector.com/blog/hatch-fill-svg-pen-paths/hatch-routes.webp)

*Autorski cyfrowy zestaw testowy i rzeczywiste eksporty Paper.js. Otwór pozostaje otwarty we wszystkich trzech plikach tras. Kontrole dotyczą linii środkowych; nie wykonano testu plotera ani fizycznego pisaka.*

[Poradnik jednostek wzoru SVG](https://perfectvector.com/pl/blog/svg-pattern-units) opisuje powtarzane malowanie, gdy to jest celem. Tutaj wymaganym wynikiem jest jawna otwarta geometria.

## 3. Uruchom kompletny przykład Paper.js

Użyj przeglądarki, edytora tekstu i pełnego wydania Paper.js 0.12.18 z [oficjalnej publikacji](https://github.com/paperjs/paper.js/releases/tag/v0.12.18). Umieść `paper-full.min.js` w folderze `library`. Zapisz ten HTML jako `generate.html`, a następujący JavaScript jako `hatch.js` obok tego folderu. Oryginalny emblemat jest w kodzie.

```html
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Generate original hatch routes</title>
<canvas id="work" width="200" height="140" hidden></canvas>
<p id="status">Running</p>
<pre id="export-receipt"></pre>
<h2>0 degrees, 10-unit spacing</h2>
<img id="preview-coarse" width="400" alt="Coarse hatch">
<pre id="svg-coarse"></pre>
<h2>0 degrees, 5-unit spacing</h2>
<img id="preview-dense" width="400" alt="Dense hatch">
<pre id="svg-dense"></pre>
<h2>30 degrees, 10-unit spacing</h2>
<img id="preview-angled" width="400" alt="Angled hatch">
<pre id="svg-angled"></pre>
<script src="library/paper-full.min.js"></script>
<script src="hatch.js"></script>
</html>
```

```javascript
paper.setup(document.getElementById('work'));

// Original area: a five-sided boundary with a rectangular hole.
const areaData = 'M20 20 L140 20 L180 60 L180 120 L20 120 Z ' +
  'M60 50 L60 90 L110 90 L110 50 Z';
const configurations = [
  { id: 'coarse', angle: 0, spacing: 10 },
  { id: 'dense', angle: 0, spacing: 5 },
  { id: 'angled', angle: 30, spacing: 10 }
];

function makeHatch(angle, spacing) {
  const area = new paper.CompoundPath({
    pathData: areaData,
    fillRule: 'nonzero',
    insert: false
  });
  const radians = angle * Math.PI / 180;
  const direction = new paper.Point(Math.cos(radians), Math.sin(radians));
  const normal = new paper.Point(-direction.y, direction.x);
  const center = new paper.Point(100, 70);
  const delivery = new paper.Group({ insert: false });

  for (let offset = -200 + spacing / 2; offset < 200; offset += spacing) {
    const origin = center.add(normal.multiply(offset));
    const line = new paper.Path.Line({
      from: origin.subtract(direction.multiply(300)),
      to: origin.add(direction.multiply(300)),
      insert: false
    });
    const kept = line.intersect(area, { trace: false, insert: false });
    const parts = kept instanceof paper.CompoundPath ? [...kept.children] : [kept];
    const routes = parts.filter(path => path.length > 1e-7);
    for (const path of routes) {
      if (path.closed || path.segments.length !== 2) {
        throw new Error('Expected one open straight segment');
      }
      if (path.firstSegment.point.dot(direction) > path.lastSegment.point.dot(direction)) {
        path.reverse();
      }
    }
    routes.sort((a, b) => a.firstSegment.point.dot(direction) - b.firstSegment.point.dot(direction));
    for (const path of routes) {
      path.fillColor = null;
      path.strokeColor = '#2f6977';
      path.strokeWidth = 1;
      path.strokeCap = 'butt';
      delivery.addChild(path);
    }
    if (kept instanceof paper.CompoundPath || routes.length === 0) {
      kept.remove();
    }
    line.remove();
  }
  area.remove();
  const geometry = delivery.exportSVG({ asString: true, precision: 6 });
  const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="100mm" height="70mm" ' +
    'viewBox="0 0 200 140">' + geometry + '</svg>';
  const routeCount = delivery.children.length;
  const drawnLength = delivery.children.reduce((sum, path) => sum + path.length, 0);
  let transitionLength = 0;
  for (let index = 1; index < routeCount; index += 1) {
    transitionLength += delivery.children[index - 1].lastSegment.point
      .getDistance(delivery.children[index].firstSegment.point);
  }
  delivery.remove();
  return { svg, routeCount, drawnLength, transitionLength };
}

const receipt = { paper: paper.version, units: 'viewBox user units; 0.5 mm per unit', rows: [] };
for (const configuration of configurations) {
  const result = makeHatch(configuration.angle, configuration.spacing);
  document.getElementById('svg-' + configuration.id).textContent = result.svg;
  const preview = document.getElementById('preview-' + configuration.id);
  preview.src = URL.createObjectURL(new Blob([result.svg], { type: 'image/svg+xml' }));
  receipt.rows.push({ ...configuration, route_count: result.routeCount,
    drawn_length: result.drawnLength, transition_length: result.transitionLength });
}
document.getElementById('export-receipt').textContent = JSON.stringify(receipt, null, 2);
document.getElementById('status').textContent = 'Generated. Save each exact SVG shown below, then reopen those saved files for independent checks.';
```

Otwórz `generate.html` w przeglądarce. Uruchomiliśmy go z Paper.js 0.12.18 w Chromium 155. Każdy wynik pokazuje podgląd i dokładne znaczniki SVG. Skopiuj trzy kompletne ciągi SVG do `hatch-coarse.svg`, `hatch-dense.svg` i `hatch-angled.svg`, a następnie otwórz zapisane pliki niezależnie.

Kluczowe wywołanie to `line.intersect(area, { trace: false, insert: false })`. Paper.js opisuje [`trace: false`](https://paperjs.org/reference/pathitem/#intersect-path) jako dzielenie pierwszej ścieżki na przecięciach i zachowanie jej krzywych wewnątrz obszaru drugiej. Zachowuje to otwarte odcinki kreskowania. Domyślny tryb trasowania obszaru odpowiada na inne pytanie logiczne; ten proces opisuje [poradnik wypełnionych kształtów Paper.js](https://perfectvector.com/pl/blog/paperjs-svg-booleans).

Funkcja ustawia `fillColor` na null i nadaje każdej trasie obrys. Sprawdza też dwupunktowe otwarte wyniki przed eksportem. Zamknięty obszar pozostaje pomocą konstrukcyjną i nie trafia do grupy przekazania.

## 4. Sprawdzaj razem odstęp, kąt i fizyczną skalę

Wszystkie trzy eksporty deklarują `width="100mm"`, `height="70mm"` i `viewBox="0 0 200 140"`. Mapuje to jedną jednostkę użytkownika na 0.5 mm w SVG. Odstęp 10 jednostek oznacza więc 5 mm; 5 jednostek oznacza 2.5 mm.

Celowo szerokie odstępy przykładowe ułatwiają kontrolę pojedynczych tras. Nie są zaleceniem pełnego pokrycia tuszem. Obrys ekranowy ma jedną jednostkę szerokości, lecz jego wygląd nie mierzy rzeczywistego śladu pisaka na materiale.

Pętla przesunięć ustala fazę kreskowania na połowie odstępu. Zmiana fazy może zmienić elementy granicy, które spotka linia. Przy dodatnich 30° kierunek biegnie w dół i w prawo w tym układzie SVG. Odstęp jest mierzony prostopadle do równoległych linii, a nie jako ich pionowe oddalenie na ekranie.

| Zapisany plik      | Kąt | Odstęp               | Otwarte trasy | Długość rysowanych linii środkowych   |
| ------------------ | --- | -------------------- | ------------- | ------------------------------------- |
| `hatch-coarse.svg` | 0°  | 10 jednostek / 5 mm  | 14            | 1320 jednostek / 660 mm               |
| `hatch-dense.svg`  | 0°  | 5 jednostek / 2.5 mm | 28            | 2640 jednostek / 1320 mm              |
| `hatch-angled.svg` | 30° | 10 jednostek / 5 mm  | 20            | Około 1318.564 jednostek / 659.282 mm |

Niezależnie obliczyliśmy oczekiwane przecięcia linii z wielokątem, a potem porównaliśmy zapisane współrzędne z tolerancją 0.000002 jednostki użytkownika. Każda eksportowana trasa odpowiadała oczekiwanym końcom. Wszystkie były otwarte i żaden próbkowany punkt linii środkowej nie przechodził przez otwór lub poza obszar ponad tę tolerancję. Trzy zapisane SVG zachowały zadeklarowane mapowanie rozmiaru fizycznego.

Dla innego kształtu sprawdź rzeczywiste eksportowane trasy zamiast zakładać takie same liczby jak w przykładzie. Krzywe, bardzo małe przerwy, samoprzecięcia, transformowane grupy i dowolne importowane dokumenty SVG nie należą do zakresu tego testu.

## 5. Oddziel przerwy między trasami od optymalizacji przejazdów

Plik z większym odstępem ma 14 otwartych tras i 13 przerw między kolejnymi trasami w kolejności serializacji. Połączenie ich z opuszczonym pisakiem dodałoby niechciane ślady. Proces plotowania musi przed rysowaniem odpowiednio obsługiwać przejścia.

Skrypt zachowuje prostą kolejność jednokierunkową: odwiedza przesunięcia po kolei i prowadzi każdy odcinek w tym samym kierunku. Suma prostych odległości od końca każdej trasy do początku następnej wynosi około 1562.997 jednostek użytkownika dla pliku rzadszego. Gęstszy plik ma 27 przerw i sumę łączników około 3281.578 jednostek.

Sumy nie obejmują początkowego dojazdu i końcowego powrotu. To geometryczne skutki tej kolejności, a nie zmierzony ruch maszyny, szacunek czasu lub zoptymalizowany plan. Aplikacja plotująca może odwracać lub zmieniać kolejność tras. Zmniejszenie odstępu o połowę podwoiło długość rysowania i liczbę tras tego przykładu; nie ustanawia uniwersalnego podwojenia czasu pracy.

Otwórz plik ponownie w aplikacji sterującej ploterem, potwierdź rozmiar i sprawdź podgląd tras oraz podnoszenie pisaka. Przetestuj pisak, materiał, odstępy, odsunięcie od granic i ustawienia ruchu na własnym sprzęcie. Nie wykonaliśmy zadania plotera, nie generowaliśmy kodu maszynowego ani nie testowaliśmy Cricut Draw/Attach.

## Napraw typowe błędy geometrii

| Objaw                                                | Co sprawdzić i zmienić                                                                                                                                         |
| ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Kreskowanie przechodzi przez zamierzony otwór        | Sprawdź wypełniony obszar. Zastąp białą nakładkę rzeczywistym otworem geometrii złożonej przed przecięciem.                                                    |
| Podgląd jest poprawny, lecz pozostają pełne linie    | Szukaj zależności od przycięcia lub wzoru. Sprawdź zapisane współrzędne tras zamiast polegać na renderowanej sylwetce.                                         |
| Linie stają się zamkniętymi kształtami               | Potwierdź otwartą linię jako pierwszy argument i obecność `trace: false`. Przykład odrzuca zamknięte lub wieloodcinkowe wyniki.                                |
| Tusz wychodzi poza granicę                           | Odróżnij linię środkową od obszaru obrysu. Przykład nie pomniejsza obszaru o promień końcówki; przygotuj odstęp i przetestuj rzeczywiste narzędzie.            |
| Wypełnienie jest rzadkie lub powierzchnia zbyt mokra | Reguluj na kontrolowanej próbce pisaka i materiału. Sam odstęp cyfrowy nie określa krycia ani schnięcia.                                                       |
| Plik wykonuje nieoczekiwane skoki                    | Sprawdź kolejność i przejścia z uniesionym pisakiem w oprogramowaniu docelowym. Zachowaj trasy przed optymalizatorem, potem ponownie sprawdź otwory i granice. |

Jeśli źródłem jest tylko płaska rastrowa sylwetka, [proces clipartu do SVG PerfectVector](https://perfectvector.com/pl/clipart-to-svg) może najpierw odzyskać zamkniętą grafikę. Sprawdź kontur i każdy otwór, a potem wygeneruj trasy kreskowania z zaakceptowanej geometrii. Istniejąca czysta grafika wektorowa może trafić bezpośrednio do przygotowania kreskowania.

Wektoryzacja sylwetki i generowanie tras kreskowania są oddzielnymi etapami. Oryginalny emblemat artykułu utworzono jako geometrię wektorową; nie jest przykładem konwersji PerfectVector.

## FAQ

**Czy wypełnienie SVG automatycznie staje się kreskowaniem pisaka?**
Nie. Wypełnienie opisuje malowany wygląd. Proces plotowania potrzebuje tras kreskowania lub innego obsługiwanego sposobu tworzenia pociągnięć z tego obszaru.

**Dlaczego podgląd kreskowania nadal zawiera linie przez otwór?**
Przycięcie może ukryć części pełnych linii bez skracania zapisanej geometrii. Sprawdź współrzędne i włącz otwór do rzeczywistego obszaru przed tworzeniem jawnych tras.

**Jakiego odstępu kreskowania użyć?**
Wybierz go w teście pisaka i materiału przy docelowej skali. Cyfrowy przykład używa 5 mm i 2.5 mm, aby uwidocznić trasy; nie określa pełnego krycia ani uniwersalnego ustawienia pisaka.

**Czy to jedna ciągła ścieżka?**
Nie. Rzadszy wynik zawiera 14 oddzielnych otwartych tras. Otwór dzieli cztery wiersze, a proces rysowania musi obsługiwać przerwy bez dodawania niechcianych śladów.

## Źródła

1. [Paper.js PathItem intersection](https://paperjs.org/reference/pathitem/#intersect-path) — opisuje dzielenie otwartych ścieżek przy trace false.
2. [Wzory SVG](https://www.w3.org/TR/SVG2/pservers.html#Patterns) — definiuje powtarzane malowanie oddzielnie od jawnej geometrii tras.
3. [Maskowanie i ścieżki przycinania CSS](https://www.w3.org/TR/css-masking-1/#ClippingPaths) — wyjaśnia zmianę renderowania przez przycięcie bez skracania pierwotnego kształtu.
4. [Kreskowanie GRBL-Plotter](https://grbl-plotter.de/index.php?id=hatch-fill) — pokazuje różnicę nałożonych obiektów i otworu w jednej ścieżce.
5. [Wydanie Paper.js 0.12.18](https://github.com/paperjs/paper.js/releases/tag/v0.12.18) — wskazuje wersję biblioteki uruchamialnego przykładu.

Jeśli rastrowa sylwetka potrzebuje edytowalnych granic, [przygotuj kandydata clipart SVG](https://perfectvector.com/pl/clipart-to-svg), sprawdź otwory i oddzielnie wygeneruj oraz zweryfikuj kreskowanie przed fizycznym testem zadania.

## Explore

- [Read the HTML article](https://perfectvector.com/pl/blog/hatch-fill-svg-pen-paths)
- [Linie bigowania i cięcia SVG: odczytaj geometrię](https://perfectvector.com/pl/blog/svg-score-lines-vs-cut-lines.md)
- [Szablony do trawienia szkła: wybierz, co usunąć](https://perfectvector.com/pl/blog/glass-etching-stencil-polarity.md)
- [Product facts](https://perfectvector.com/product-facts.md)
- [FAQ](https://perfectvector.com/faq.md)
- [Pricing and credits](https://perfectvector.com/pricing.md)
