feat(markdown): Initial version for v3 tutorial
This commit is contained in:
parent
0acbe206c1
commit
e5bacbecb7
11 changed files with 499 additions and 239 deletions
|
@ -156,16 +156,8 @@ function draftBib({
|
||||||
while (points.tipRightBottomStart.x > -1) {
|
while (points.tipRightBottomStart.x > -1) {
|
||||||
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* While we're at it,
|
|
||||||
* let's add a point where
|
|
||||||
* the closure's snap should go.
|
|
||||||
*/
|
|
||||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
|
||||||
// highlight-end
|
// highlight-end
|
||||||
|
|
||||||
|
|
||||||
// highlight-start
|
// highlight-start
|
||||||
/*
|
/*
|
||||||
* This is not needed
|
* This is not needed
|
||||||
|
|
|
@ -92,60 +92,13 @@ snippet.
|
||||||
You can find all possible snippets in [our documentation](/reference/api/snippet/).
|
You can find all possible snippets in [our documentation](/reference/api/snippet/).
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
|
## The completed design
|
||||||
|
|
||||||
|
Let's put this and few other things together to complete our design:
|
||||||
|
|
||||||
|
|
||||||
We won't be adding seam allowance, but we will be doing something that is essentially the same.
|
|
||||||
Rather than draw an outline outside our bib to indicate the seam allowance, we'll draw one within
|
|
||||||
our bib to mark the bias tape:
|
|
||||||
|
|
||||||
```js
|
<Example tutorial caption="Almost done. But there's one more thing the user can ask for: a **paperless** pattern">
|
||||||
paths.bias = paths.seam
|
|
||||||
.offset(-5)
|
|
||||||
.attr("class", "various dashed")
|
|
||||||
.attr("data-text", "finishWithBiasTape")
|
|
||||||
.attr("data-text-class", "center fill-various")
|
|
||||||
```
|
|
||||||
|
|
||||||
The `path.offset()` method makes it trivial to add seam allowance, since it will contruct
|
|
||||||
a path parallel to the given path at the distance you pass it. 9 times out of 10, you'll be using it as `path.offset(sa)`.
|
|
||||||
|
|
||||||
Note that we're also using the attributes again, to change the look of the line, and add text to it,
|
|
||||||
as explained in [Adding text](/howtos/code/adding-text).
|
|
||||||
|
|
||||||
## Scalebox and title
|
|
||||||
|
|
||||||
Two more macros and we're done.
|
|
||||||
|
|
||||||
The `title` macro adds a title to our part.
|
|
||||||
It's not that big a deal here since we only have one part in our pattern.
|
|
||||||
But patterns typically have many different parts, some of them which might look rather similar.
|
|
||||||
That's why you should number your parts and give them a name.
|
|
||||||
|
|
||||||
The `title` macro can help you with that:
|
|
||||||
|
|
||||||
```js
|
|
||||||
points.title = points.bottom.shift(-90, 45)
|
|
||||||
macro("title", {
|
|
||||||
at: points.title,
|
|
||||||
nr: 1,
|
|
||||||
title: "bib"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
The `scalebox` macro prints a box of an exact size.
|
|
||||||
It is used by people who print the pattern to make sure their print is correctly scaled.
|
|
||||||
|
|
||||||
```js
|
|
||||||
points.scalebox = points.title.shift(-90, 55)
|
|
||||||
macro("scalebox", { at: points.scalebox })
|
|
||||||
```
|
|
||||||
|
|
||||||
And with that, our pattern is now _complete_:
|
|
||||||
|
|
||||||
We're not done yet though. There's one more thing the user can ask for: a _paperless_ pattern.
|
|
||||||
|
|
||||||
|
|
||||||
<Example tutorial caption="The shape our bib is now completed">
|
|
||||||
```js
|
```js
|
||||||
function draftBib({
|
function draftBib({
|
||||||
Path,
|
Path,
|
||||||
|
@ -275,7 +228,6 @@ function draftBib({
|
||||||
points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
|
points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
|
||||||
points.snapRight = points.snapLeft.flipX()
|
points.snapRight = points.snapLeft.flipX()
|
||||||
|
|
||||||
// highlight-start
|
|
||||||
// Round the bottom corners
|
// Round the bottom corners
|
||||||
macro("round", {
|
macro("round", {
|
||||||
from: points.topLeft,
|
from: points.topLeft,
|
||||||
|
@ -291,24 +243,14 @@ function draftBib({
|
||||||
radius: points.bottomRight.x / 4,
|
radius: points.bottomRight.x / 4,
|
||||||
prefix: "bottomRight"
|
prefix: "bottomRight"
|
||||||
})
|
})
|
||||||
// highlight-end
|
|
||||||
|
|
||||||
// Create one path for the bib outline
|
// Create one path for the bib outline
|
||||||
paths.seam = new Path()
|
paths.seam = new Path()
|
||||||
.move(points.edgeLeft)
|
.move(points.edgeLeft)
|
||||||
// strikeout-start
|
|
||||||
/* We only need to replace the start
|
|
||||||
* with the new lines below
|
|
||||||
.line(points.bottomLeft)
|
|
||||||
.line(points.bottomRight)
|
|
||||||
*/
|
|
||||||
// strikeout-end
|
|
||||||
// highlight-start
|
|
||||||
.line(points.bottomLeftStart)
|
.line(points.bottomLeftStart)
|
||||||
.curve(points.bottomLeftCp1, points.bottomLeftCp2, points.bottomLeftEnd)
|
.curve(points.bottomLeftCp1, points.bottomLeftCp2, points.bottomLeftEnd)
|
||||||
.line(points.bottomRightStart)
|
.line(points.bottomRightStart)
|
||||||
.curve(points.bottomRightCp1, points.bottomRightCp2, points.bottomRightEnd)
|
.curve(points.bottomRightCp1, points.bottomRightCp2, points.bottomRightEnd)
|
||||||
// highlight-end
|
|
||||||
.line(points.edgeRight)
|
.line(points.edgeRight)
|
||||||
.curve(
|
.curve(
|
||||||
points.edgeRightCp,
|
points.edgeRightCp,
|
||||||
|
@ -363,31 +305,95 @@ function draftBib({
|
||||||
.close()
|
.close()
|
||||||
.addClass("fabric")
|
.addClass("fabric")
|
||||||
|
|
||||||
|
// highlight-start
|
||||||
|
if (complete) {
|
||||||
|
/*
|
||||||
|
* Let's add the points where
|
||||||
|
* the closure's snaps should go.
|
||||||
|
*/
|
||||||
|
// Add snaps
|
||||||
|
points.snapLeft = points.top
|
||||||
|
.shiftFractionTowards(points.edgeTop, 0.5)
|
||||||
|
points.snapRight = points.snapLeft
|
||||||
|
.flipX()
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, let's use our newfound snippet powers
|
||||||
|
* to add the snaps to these points.
|
||||||
|
* First the left snap (the stud part)
|
||||||
|
*/
|
||||||
|
snippets.snapStud = new Snippet(
|
||||||
|
'snap-stud',
|
||||||
|
points.snapLeft
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The right snap (the socket part)
|
||||||
|
* should go on the back of the fabric.
|
||||||
|
* To try to make that more obvious to the user
|
||||||
|
* let's set its `opacity` attribute to 0.5
|
||||||
|
* this way it will be semi-transparent.
|
||||||
|
*/
|
||||||
|
snippets.snapSocket = new Snippet(
|
||||||
|
'snap-socket',
|
||||||
|
points.snapRight
|
||||||
|
).attr('opacity', 0.5)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Another snippet we should add is our logo.
|
||||||
|
* A logo is not required, but we love skully.
|
||||||
|
*/
|
||||||
|
// Add a logo
|
||||||
|
points.logo = new Point(0, 0)
|
||||||
|
snippets.logo = new Snippet(
|
||||||
|
"logo",
|
||||||
|
points.logo
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We already know how to use macros
|
||||||
|
* This one adds a title to our part
|
||||||
|
*/
|
||||||
|
// Add a title
|
||||||
|
points.title = points.bottom
|
||||||
|
.shift(-90, 45)
|
||||||
|
macro("title", {
|
||||||
|
at: points.title,
|
||||||
|
nr: 1,
|
||||||
|
title: "bib",
|
||||||
|
scale: 0.7
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This macro adds a scalebox to our part
|
||||||
|
*/
|
||||||
|
// Add a scalbox
|
||||||
|
points.scalebox = points.title
|
||||||
|
.shift(-90, 55)
|
||||||
|
macro(
|
||||||
|
"scalebox",
|
||||||
|
{ at: points.scalebox }
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Our bib should be finished with bias tape.
|
||||||
|
* To add it, we're using Path.offset()
|
||||||
|
* You will learn to LOVE this methid
|
||||||
|
* when designing pattern with seam allowance
|
||||||
|
* as it draws a path parallel to another one
|
||||||
|
*/
|
||||||
|
paths.bias = paths.seam
|
||||||
|
.offset(-5)
|
||||||
|
.addClass("various dashed")
|
||||||
|
.addText(
|
||||||
|
"finishWithBiasTape",
|
||||||
|
"center fill-various"
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
// highlight-end
|
||||||
|
|
||||||
return part
|
return part
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Example>
|
</Example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
We've added a `snap-stud` and `snap-socket` snippet to the points we had foreseen for that.
|
|
||||||
|
|
||||||
Because the socket snippet is at the back of the fabric, we've made it semi-transparent by
|
|
||||||
setting the `opacity` attribute to `0.5`. Yes, you can do that.
|
|
||||||
|
|
||||||
<Tip>
|
|
||||||
|
|
||||||
Any attributes you set will be added to the SVG output.
|
|
||||||
|
|
||||||
</Tip>
|
|
||||||
|
|
||||||
Since we're adding snippets, let's throw a logo on there too:
|
|
||||||
|
|
||||||
```js
|
|
||||||
points.logo = new Point(0, 0)
|
|
||||||
snippets.logo = new Snippet("logo", points.logo)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,44 +3,75 @@ title: Conclusion
|
||||||
order: 280
|
order: 280
|
||||||
---
|
---
|
||||||
|
|
||||||
Congratulations, you have created your first pattern. And while it's arguably rather simple,
|
Congratulations, you have created your first pattern. And while it's arguably
|
||||||
you have learned a bunch of things along the way. Let's list some of the things you've learned:
|
rather simple, we have learned a bunch of things along the way. Let's list
|
||||||
|
some of the things we've learned:
|
||||||
|
|
||||||
- You learned how to [setup your development environment](/tutorials/pattern-design/new-design) with `npx @freesewing/new-design`
|
- We learned how to [setup your development environment][new-design] with `npx
|
||||||
- You learned how to [add parts](/tutorials/pattern-design/your-first-part), [measurements](/tutorials/pattern-design/adding-measurements), and [options](/tutorials/pattern-design/adding-options) to your pattern's configuration file
|
@freesewing/new-design`
|
||||||
- You learned what [a good boilerplate is to start with a new part](/tutorials/pattern-design/part-structure)
|
- We learned about [the different files and folders][structure] in the
|
||||||
- You learned [how to add points and draw paths](/tutorials/pattern-design/constructing-the-neck-opening)
|
development environment and how `design/src` holds our source code.
|
||||||
- You learned how you can make changes in a loop to [adapt the neck opening](/tutorials/pattern-design/fitting-the-neck-opening) or [rotate the straps](/tutorials/pattern-design/avoiding-overlap) until they were just right
|
- We learned about [parts][our-first-part] and how they are structured.
|
||||||
- You learned about [macros and how to use them](/tutorials/pattern-design/creating-the-closure)
|
- We learned how to add [measurements][adding-measurements], and
|
||||||
- You learned different methods to manipulate [points](/reference/api/point/) and [paths](/reference/api/path/)
|
[options][adding-options] to our design.
|
||||||
- You learned about using [attributes](/reference/api/attributes/) to influence the appearance of points and paths
|
- We learned about [a part's draft method][draft-method] and how to destructure
|
||||||
- You learned about what it means to draft [a complete pattern](/tutorials/pattern-design/completing-your-pattern)
|
what we need to design our part.
|
||||||
- You learned about [snippets and how to add them](/tutorials/pattern-design/completing-your-pattern#adding-snippets)
|
- We learned [how to add points and draw paths][constructing-the-neck-opening]
|
||||||
- You learned [how to offset a path](/tutorials/pattern-design/completing-your-pattern#seam-allowance) to create seam allowance, or in our case, mark the bias tape line
|
- We learned how you can make changes in a loop to [adapt the neck
|
||||||
- You learned how to create a [paperless pattern](/tutorials/pattern-design/paperless-bib) by adding dimensions
|
opening][fitting-the-neck-opening] or [rotate the straps][avoiding-overlap]
|
||||||
|
until they were just right
|
||||||
|
- We learned about [macros and how to use them][creating-the-closure]
|
||||||
|
- We learned there are many methods that allow us to manipulate
|
||||||
|
[points](/reference/api/point/) and [paths](/reference/api/path/)
|
||||||
|
- We learned about what it means to draft [a complete
|
||||||
|
pattern][completing-our-pattern]
|
||||||
|
- We learned about [snippets and how to add them][completing-our-pattern]
|
||||||
|
- We learned [how to offset a path][completing-your-pattern] to create seam
|
||||||
|
allowance, or in our case, mark the bias tape line
|
||||||
|
- We learned how to support a [paperless pattern][paperless] by adding
|
||||||
|
dimensions
|
||||||
|
|
||||||
|
[new-design]: /tutorials/pattern-design/new-design
|
||||||
|
[structure]: /tutorials/pattern-design/new-design
|
||||||
|
[our-first-part]: /tutorials/pattern-design/our-first-part
|
||||||
|
[adding-measurements]: /tutorials/pattern-design/adding-measurments
|
||||||
|
[adding-options]: /tutorials/pattern-design/adding-options
|
||||||
|
[draft-method]: /tutorials/pattern-design/draft-method
|
||||||
|
[constructing-the-neck-opening]: /tutorials/pattern-design/constructing-the-neck-opening
|
||||||
|
[fitting-the-neck-opening]: /tutorials/pattern-design/fitting-the-neck-opening
|
||||||
|
[avoiding-overlap]: /tutorials/pattern-design/avoiding-overlap
|
||||||
|
[creating-the-closure]: /tutorials/pattern-design/creating-the-closure
|
||||||
|
[completing-our-pattern]: /tutorials/pattern-design/completing-our-pattern
|
||||||
|
[paperless]: /tutorials/pattern-design/paperless
|
||||||
|
|
||||||
You can find the complete code of the tutorial pattern [here on GitHub](https://github.com/freesewing/freesewing/blob/develop/designs/tutorial/src/bib.js).
|
|
||||||
|
|
||||||
## More reading material
|
## More reading material
|
||||||
|
|
||||||
- If you haven't done so already, read through [the pattern guide](/guides/patterns/) which provides a good overview of how patterns work under the hood
|
- If you haven't done so already, read through [the pattern
|
||||||
- Bookmark [the FreeSewing API docs](/reference/api/), they are your reference every time you're not entirely certain how something works
|
guide](/guides/patterns/) which provides a good overview of how patterns work
|
||||||
- Have a look at [the design guide](/guides/best-practices/) for best practices that will help you make the best possible patterns
|
under the hood
|
||||||
|
- Bookmark [the FreeSewing API docs](/reference/api/), they are your reference
|
||||||
|
every time you're not entirely certain how something works
|
||||||
|
- Have a look at [the design guide](/guides/best-practices/) for best practices
|
||||||
|
that will help you make the best possible patterns
|
||||||
|
|
||||||
## What to do next
|
## What to do next
|
||||||
|
|
||||||
Now that you have learned how to create a pattern, why don't you make one?
|
Now that you have learned how to create a pattern, why don't you make one?
|
||||||
|
|
||||||
Think about what it is you would like to create, and just do it. If you get stuck at any moment,
|
Think about what it is you would like to create, and just do it. If you get
|
||||||
or need some help or advice, you can [join our chat room](https://discord.freesewing.org/) and we'll help you out.
|
stuck at any moment, or need some help or advice, you can [join our chat
|
||||||
|
room](https://discord.freesewing.org/) and we'll help you out.
|
||||||
|
|
||||||
<Note>
|
<Comment by="joost">
|
||||||
|
##### How did I do?
|
||||||
|
|
||||||
###### Tell us how we can improve this tutorial
|
You could do me a real favor by letting me know what you loved or hated about
|
||||||
|
this tutorial.
|
||||||
|
|
||||||
You could do us a real favor by letting us know what you loved or hated about this tutorial.
|
Were there areas that were not clear? Did I dwell too long on one topic, or
|
||||||
|
rushed through another one too quickly? Your feedback helps improve things,
|
||||||
|
so don't be shy and [tell me what you think](https://discord.freesewing.org/).
|
||||||
|
|
||||||
Were there areas that were not clear? Did we dwell too long on one topic, or rushed through another one too quickly?
|
If you don't like Discord, you can reach me at joost@freesewing.org
|
||||||
You feedback helps us improve things, so don't be shy and [tell us what you think](https://discord.freesewing.org/).
|
</Comment>
|
||||||
|
|
||||||
</Note>
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ order: 210
|
||||||
---
|
---
|
||||||
|
|
||||||
Things are starting to look good, but we can't fit the bib over the baby's head like this.
|
Things are starting to look good, but we can't fit the bib over the baby's head like this.
|
||||||
So we must create a closure. We'll let the straps overlap at the end, and put in a snap.
|
So we must create a closure. We'll let the straps overlap at the end, and put in a snap
|
||||||
|
later.
|
||||||
|
|
||||||
## Using macros
|
## Using macros
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title: Structure of a draft method
|
title: A part's draft method
|
||||||
order: 150
|
order: 150
|
||||||
---
|
---
|
||||||
|
|
|
@ -163,12 +163,6 @@ function draftBib({
|
||||||
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||||
}
|
}
|
||||||
|
|
||||||
// highlight-start
|
|
||||||
// Snap anchor
|
|
||||||
// highlight-end
|
|
||||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
|
||||||
|
|
||||||
|
|
||||||
// strikeout-start
|
// strikeout-start
|
||||||
/* Remove this repetition
|
/* Remove this repetition
|
||||||
macro("round", {
|
macro("round", {
|
||||||
|
@ -211,7 +205,6 @@ function draftBib({
|
||||||
points.tipLeftBottomCp1 = points.tipRightBottomCp1.flipX()
|
points.tipLeftBottomCp1 = points.tipRightBottomCp1.flipX()
|
||||||
points.tipLeftBottomCp2 = points.tipRightBottomCp2.flipX()
|
points.tipLeftBottomCp2 = points.tipRightBottomCp2.flipX()
|
||||||
points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
|
points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
|
||||||
points.snapRight = points.snapLeft.flipX()
|
|
||||||
|
|
||||||
// Create one path for the bib outline
|
// Create one path for the bib outline
|
||||||
paths.seam = new Path()
|
paths.seam = new Path()
|
||||||
|
|
Before Width: | Height: | Size: 277 KiB After Width: | Height: | Size: 277 KiB |
|
@ -1,106 +0,0 @@
|
||||||
---
|
|
||||||
title: Making your pattern paperless
|
|
||||||
order: 270
|
|
||||||
---
|
|
||||||
|
|
||||||
Users can request paperless patterns by setting the `paperless` setting to `true`.
|
|
||||||
|
|
||||||
We can get that value of the setting from the `part.shorthand()` method.
|
|
||||||
It will be the last shorthand we will put to use:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const {
|
|
||||||
Point,
|
|
||||||
points,
|
|
||||||
Path,
|
|
||||||
paths,
|
|
||||||
complete,
|
|
||||||
sa,
|
|
||||||
paperless, // <- this one here
|
|
||||||
measurements,
|
|
||||||
options,
|
|
||||||
macro,
|
|
||||||
snippets,
|
|
||||||
Snippet
|
|
||||||
} = part.shorthand()
|
|
||||||
```
|
|
||||||
|
|
||||||
The idea behind _paperless patterns_ is that users don't need to print your
|
|
||||||
pattern in order to use it.
|
|
||||||
Instead, we include dimensions on the pattern that allows them to transfer
|
|
||||||
the pattern directly onto fabric, or onto an intermediate medium such as tracing paper.
|
|
||||||
|
|
||||||
In addition, FreeSewing will automatically render a grid for each pattern part with metric or imperial
|
|
||||||
markings, depending on the units requested by the user.
|
|
||||||
|
|
||||||
While the grid gets added automatically, the dimensions you have to add yourself.
|
|
||||||
Thankfully, there's macros that can help you with that, specifically:
|
|
||||||
|
|
||||||
- The `hd` macro adds a horizontal dimension
|
|
||||||
- The `vd` macro adds a vertical dimension
|
|
||||||
- The `ld` macro adds a linear dimension
|
|
||||||
- The `pd` macro adds a path dimension that follows a given path
|
|
||||||
|
|
||||||
<Note> The documentation, as always, holds [all the information about the macros](/reference/api/macros/). </Note>
|
|
||||||
|
|
||||||
Let's look at the code:
|
|
||||||
|
|
||||||
```js
|
|
||||||
if (paperless) {
|
|
||||||
// Add dimensions
|
|
||||||
macro("hd", {
|
|
||||||
from: points.bottomLeftStart,
|
|
||||||
to: points.bottomRightEnd,
|
|
||||||
y: points.bottomLeft.y + 15
|
|
||||||
})
|
|
||||||
macro("vd", {
|
|
||||||
from: points.bottomRightStart,
|
|
||||||
to: points.bottom,
|
|
||||||
x: points.bottomRight.x + 15
|
|
||||||
})
|
|
||||||
macro("vd", {
|
|
||||||
from: points.bottomRightStart,
|
|
||||||
to: points.right,
|
|
||||||
x: points.bottomRight.x + 30
|
|
||||||
})
|
|
||||||
macro("vd", {
|
|
||||||
from: points.bottomRightStart,
|
|
||||||
to: points.tipLeftTopStart,
|
|
||||||
x: points.bottomRight.x + 45
|
|
||||||
})
|
|
||||||
macro("hd", {
|
|
||||||
from: points.left,
|
|
||||||
to: points.right,
|
|
||||||
y: points.left.y + 25
|
|
||||||
})
|
|
||||||
macro("ld", {
|
|
||||||
from: points.tipLeftBottomEnd,
|
|
||||||
to: points.tipLeftTopStart,
|
|
||||||
d: 15
|
|
||||||
})
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
There's a lot going on, but it's mostly repetition. To see what that did to your pattern, you have to enable _paperless mode_ in your developing environment; you can find the option under _Pattern options_ on the right. Let's look at the end result, and discuss:
|
|
||||||
|
|
||||||
<Example pattern="tutorial" part="bib" settings_paperless="true">
|
|
||||||
Your paperless bib
|
|
||||||
</Example>
|
|
||||||
|
|
||||||
We used the `hd` macro to add two horizontal dimensions:
|
|
||||||
|
|
||||||
- One at the bottom for the width of our bib
|
|
||||||
- One for the width of the neck opening
|
|
||||||
|
|
||||||
The `hd` macro takes a `from` and `to` point as well as a `y` value that says at what Y-value to draw the dimension.
|
|
||||||
|
|
||||||
We've also added three `vd` macros for the vertical dimensions on the right.
|
|
||||||
|
|
||||||
They also takes a `from` and `to` point, but expect a `x` parameter to indicate at what X-value the dimension should be drawn.
|
|
||||||
|
|
||||||
Finally, we added a `ld` macro for the linear dimension at the top that marks the width of our strap.
|
|
||||||
While most dimensions are horizontal or vertical, sometimes you want a straight line from the `from` to the `to` points like in this case.
|
|
||||||
|
|
||||||
The `ld` macro takes a `d` argument (short for delta) that indicates how far the dimension should be offset from the line from the `from` to the `to` point, if at all.
|
|
||||||
|
|
||||||
Making your pattern paperless is the icing on the cake. Time to wrap up, go over what we've learned, and give some pointers on where to go from here.
|
|
347
markdown/dev/tutorials/pattern-design/paperless/en.md
Normal file
347
markdown/dev/tutorials/pattern-design/paperless/en.md
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
---
|
||||||
|
title: Supporting paperless patterns
|
||||||
|
order: 270
|
||||||
|
---
|
||||||
|
|
||||||
|
The goal of paperless patterns is to create a pattern that you don't need to
|
||||||
|
print to be able to use it. Saving paper is always a good thing, but it's
|
||||||
|
also a way to democratize access to patterns.
|
||||||
|
|
||||||
|
While more and more of humanity is on the internet, access to printers and
|
||||||
|
printing paper is often harder to come by, especially in developing countries.
|
||||||
|
|
||||||
|
So before wrapping up, let's make the extra effort to make our bib design
|
||||||
|
support paperless pattern.
|
||||||
|
|
||||||
|
## The paperless setting
|
||||||
|
|
||||||
|
Users can request paperless patterns by setting [the `paperless`
|
||||||
|
setting](/reference/settings/paperless) to a *truthy* value.
|
||||||
|
|
||||||
|
Like other settings, we can destructure it to get access to it.
|
||||||
|
Then, much like with the `complete` setting, we will wrap our
|
||||||
|
paperless-specific code in a condition so it only runs when the user wants
|
||||||
|
that.
|
||||||
|
|
||||||
|
With paperless enabled, FreeSewing will automatically render a grid for each
|
||||||
|
pattern part with metric or imperial markings, depending on the units requested
|
||||||
|
by the user.
|
||||||
|
|
||||||
|
Such a grid is already a good starting point. In addition, we'll be using
|
||||||
|
different macros to add *dimensions* to the pattern.
|
||||||
|
|
||||||
|
While the grid gets added automatically, the dimensions you have to add yourself.
|
||||||
|
Thankfully, there's macros that can help you with that, specifically:
|
||||||
|
|
||||||
|
- The `hd` macro adds a horizontal dimension
|
||||||
|
- The `vd` macro adds a vertical dimension
|
||||||
|
- The `ld` macro adds a linear dimension
|
||||||
|
- The `pd` macro adds a path dimension that follows a given path
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
Refer to [the list of macros](/reference/macros/) for more details.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
<Example tutorial paperless caption="Making your pattern paperless is the icing on the cake. Time to wrap up, go over what we've learned, and give some pointers on where to go from here">
|
||||||
|
```js
|
||||||
|
function draftBib({
|
||||||
|
Path,
|
||||||
|
Point,
|
||||||
|
paths,
|
||||||
|
points,
|
||||||
|
measurements,
|
||||||
|
options,
|
||||||
|
macro,
|
||||||
|
complete,
|
||||||
|
snippets,
|
||||||
|
Snippet,
|
||||||
|
// highlight-start
|
||||||
|
paperless,
|
||||||
|
// highlight-end
|
||||||
|
part,
|
||||||
|
}) {
|
||||||
|
|
||||||
|
// Construct the quarter neck opening
|
||||||
|
let tweak = 1
|
||||||
|
let target = (measurements.head * options.neckRatio) /4
|
||||||
|
let delta
|
||||||
|
do {
|
||||||
|
points.right = new Point(tweak * measurements.head / 10, 0)
|
||||||
|
points.bottom = new Point(0, tweak * measurements.head / 12)
|
||||||
|
|
||||||
|
points.rightCp1 = points.right.shift(90, points.bottom.dy(points.right)/2)
|
||||||
|
points.bottomCp2 = points.bottom.shift(0, points.bottom.dx(points.right)/2)
|
||||||
|
|
||||||
|
paths.quarterNeck = new Path()
|
||||||
|
.move(points.right)
|
||||||
|
.curve(points.rightCp1, points.bottomCp2, points.bottom)
|
||||||
|
.hide() // Add this line
|
||||||
|
|
||||||
|
delta = paths.quarterNeck.length() - target
|
||||||
|
if (delta > 0) tweak = tweak * 0.99
|
||||||
|
else tweak = tweak * 1.02
|
||||||
|
} while (Math.abs(delta) > 1)
|
||||||
|
|
||||||
|
// Construct the complete neck opening
|
||||||
|
points.rightCp2 = points.rightCp1.flipY()
|
||||||
|
points.bottomCp1 = points.bottomCp2.flipX()
|
||||||
|
points.left = points.right.flipX()
|
||||||
|
points.leftCp1 = points.rightCp2.flipX()
|
||||||
|
points.leftCp2 = points.rightCp1.flipX()
|
||||||
|
points.top = points.bottom.flipY()
|
||||||
|
points.topCp1 = points.bottomCp2.flipY()
|
||||||
|
points.topCp2 = points.bottomCp1.flipY()
|
||||||
|
|
||||||
|
// Drawing the bib outline
|
||||||
|
const width = measurements.head * options.widthRatio
|
||||||
|
const length = measurements.head * options.lengthRatio
|
||||||
|
|
||||||
|
points.topLeft = new Point(
|
||||||
|
width / -2,
|
||||||
|
points.top.y - (width / 2 - points.right.x)
|
||||||
|
)
|
||||||
|
points.topRight = points.topLeft.shift(0, width)
|
||||||
|
points.bottomLeft = points.topLeft.shift(-90, length)
|
||||||
|
points.bottomRight = points.topRight.shift(-90, length)
|
||||||
|
|
||||||
|
// Shape the straps
|
||||||
|
points.edgeLeft = new Point(points.topLeft.x, points.left.y)
|
||||||
|
points.edgeRight = new Point(points.topRight.x, points.right.y)
|
||||||
|
points.edgeTop = new Point(0, points.topLeft.y)
|
||||||
|
|
||||||
|
points.edgeLeftCp = points.edgeLeft.shiftFractionTowards(points.topLeft, 0.5)
|
||||||
|
points.edgeRightCp = points.edgeLeftCp.flipX()
|
||||||
|
points.edgeTopLeftCp = points.edgeTop.shiftFractionTowards(
|
||||||
|
points.topLeft,
|
||||||
|
0.5
|
||||||
|
)
|
||||||
|
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
|
||||||
|
|
||||||
|
// Round the straps
|
||||||
|
const strap = points.edgeTop.dy(points.top)
|
||||||
|
|
||||||
|
points.tipRight = points.edgeTop.translate(strap / 2, strap / 2)
|
||||||
|
points.tipRightTop = new Point(points.tipRight.x, points.edgeTop.y)
|
||||||
|
points.tipRightBottom = new Point(points.tipRight.x, points.top.y)
|
||||||
|
|
||||||
|
macro("round", {
|
||||||
|
from: points.edgeTop,
|
||||||
|
to: points.tipRight,
|
||||||
|
via: points.tipRightTop,
|
||||||
|
prefix: "tipRightTop",
|
||||||
|
})
|
||||||
|
macro("round", {
|
||||||
|
from: points.tipRight,
|
||||||
|
to: points.top,
|
||||||
|
via: points.tipRightBottom,
|
||||||
|
prefix: "tipRightBottom",
|
||||||
|
})
|
||||||
|
const rotateThese = [
|
||||||
|
"edgeTopLeftCp",
|
||||||
|
"edgeTop",
|
||||||
|
"tipRight",
|
||||||
|
"tipRightTop",
|
||||||
|
"tipRightTopStart",
|
||||||
|
"tipRightTopCp1",
|
||||||
|
"tipRightTopCp2",
|
||||||
|
"tipRightTopEnd",
|
||||||
|
"tipRightBottomStart",
|
||||||
|
"tipRightBottomCp1",
|
||||||
|
"tipRightBottomCp2",
|
||||||
|
"tipRightBottomEnd",
|
||||||
|
"tipRightBottom",
|
||||||
|
"top",
|
||||||
|
"topCp2"
|
||||||
|
]
|
||||||
|
while (points.tipRightBottomStart.x > -1) {
|
||||||
|
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Snap anchor
|
||||||
|
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||||
|
|
||||||
|
// Add points for second strap
|
||||||
|
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
|
||||||
|
points.topCp1 = points.topCp2.flipX()
|
||||||
|
points.tipLeftTopStart = points.tipRightTopStart.flipX()
|
||||||
|
points.tipLeftTopCp1 = points.tipRightTopCp1.flipX()
|
||||||
|
points.tipLeftTopCp2 = points.tipRightTopCp2.flipX()
|
||||||
|
points.tipLeftTopEnd = points.tipRightTopEnd.flipX()
|
||||||
|
points.tipLeftBottomStart = points.tipRightBottomStart.flipX()
|
||||||
|
points.tipLeftBottomCp1 = points.tipRightBottomCp1.flipX()
|
||||||
|
points.tipLeftBottomCp2 = points.tipRightBottomCp2.flipX()
|
||||||
|
points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
|
||||||
|
points.snapRight = points.snapLeft.flipX()
|
||||||
|
|
||||||
|
// Round the bottom corners
|
||||||
|
macro("round", {
|
||||||
|
from: points.topLeft,
|
||||||
|
to: points.bottomRight,
|
||||||
|
via: points.bottomLeft,
|
||||||
|
radius: points.bottomRight.x / 4,
|
||||||
|
prefix: "bottomLeft"
|
||||||
|
})
|
||||||
|
macro("round", {
|
||||||
|
from: points.bottomLeft,
|
||||||
|
to: points.topRight,
|
||||||
|
via: points.bottomRight,
|
||||||
|
radius: points.bottomRight.x / 4,
|
||||||
|
prefix: "bottomRight"
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create one path for the bib outline
|
||||||
|
paths.seam = new Path()
|
||||||
|
.move(points.edgeLeft)
|
||||||
|
.line(points.bottomLeftStart)
|
||||||
|
.curve(points.bottomLeftCp1, points.bottomLeftCp2, points.bottomLeftEnd)
|
||||||
|
.line(points.bottomRightStart)
|
||||||
|
.curve(points.bottomRightCp1, points.bottomRightCp2, points.bottomRightEnd)
|
||||||
|
.line(points.edgeRight)
|
||||||
|
.curve(
|
||||||
|
points.edgeRightCp,
|
||||||
|
points.edgeTopRightCp,
|
||||||
|
points.tipLeftTopStart
|
||||||
|
)
|
||||||
|
.curve(
|
||||||
|
points.tipLeftTopCp1,
|
||||||
|
points.tipLeftTopCp2,
|
||||||
|
points.tipLeftTopEnd
|
||||||
|
)
|
||||||
|
.curve(
|
||||||
|
points.tipLeftBottomCp1,
|
||||||
|
points.tipLeftBottomCp2,
|
||||||
|
points.tipLeftBottomEnd
|
||||||
|
)
|
||||||
|
.curve(
|
||||||
|
points.topCp1,
|
||||||
|
points.rightCp2,
|
||||||
|
points.right
|
||||||
|
)
|
||||||
|
.curve(
|
||||||
|
points.rightCp1,
|
||||||
|
points.bottomCp2,
|
||||||
|
points.bottom
|
||||||
|
)
|
||||||
|
.curve(
|
||||||
|
points.bottomCp1,
|
||||||
|
points.leftCp2,
|
||||||
|
points.left
|
||||||
|
)
|
||||||
|
.curve(
|
||||||
|
points.leftCp1,
|
||||||
|
points.topCp2,
|
||||||
|
points.tipRightBottomEnd
|
||||||
|
)
|
||||||
|
.curve(
|
||||||
|
points.tipRightBottomCp2,
|
||||||
|
points.tipRightBottomCp1,
|
||||||
|
points.tipRightBottomStart
|
||||||
|
)
|
||||||
|
.curve(
|
||||||
|
points.tipRightTopCp2,
|
||||||
|
points.tipRightTopCp1,
|
||||||
|
points.tipRightTopStart
|
||||||
|
)
|
||||||
|
.curve(
|
||||||
|
points.edgeTopLeftCp,
|
||||||
|
points.edgeLeftCp,
|
||||||
|
points.edgeLeft
|
||||||
|
)
|
||||||
|
.close()
|
||||||
|
.addClass("fabric")
|
||||||
|
|
||||||
|
if (complete) {
|
||||||
|
// Add snaps
|
||||||
|
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||||
|
points.snapRight = points.snapLeft.flipX()
|
||||||
|
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
|
||||||
|
snippets.snapSocket = new Snippet('snap-socket', points.snapRight)
|
||||||
|
.attr('opacity', 0.5)
|
||||||
|
|
||||||
|
// Add a logo
|
||||||
|
points.logo = new Point(0, 0)
|
||||||
|
snippets.logo = new Snippet("logo", points.logo)
|
||||||
|
|
||||||
|
// Add a title
|
||||||
|
points.title = points.bottom.shift(-90, 45)
|
||||||
|
macro("title", {
|
||||||
|
at: points.title,
|
||||||
|
nr: 1,
|
||||||
|
title: "bib",
|
||||||
|
scale: 0.7
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add a scalbox
|
||||||
|
points.scalebox = points.title.shift(-90, 55)
|
||||||
|
macro("scalebox", { at: points.scalebox })
|
||||||
|
|
||||||
|
paths.bias = paths.seam
|
||||||
|
.offset(-5)
|
||||||
|
.addClass("various dashed")
|
||||||
|
.addText("finishWithBiasTape", "center fill-various")
|
||||||
|
|
||||||
|
// highlight-start
|
||||||
|
/*
|
||||||
|
* Note that we are putting our paperless block
|
||||||
|
* inside our `complete` block since we should
|
||||||
|
* only add this when the users wants a compete pattern
|
||||||
|
*/
|
||||||
|
if (paperless) {
|
||||||
|
// Add dimensions
|
||||||
|
/*
|
||||||
|
* The `hd` macro adds a Horizontal Dimension (hd)
|
||||||
|
* It takes a from and to point, and a y value
|
||||||
|
* at which to place the dimension
|
||||||
|
*/
|
||||||
|
macro("hd", {
|
||||||
|
from: points.bottomLeftStart,
|
||||||
|
to: points.bottomRightEnd,
|
||||||
|
y: points.bottomLeft.y + 15
|
||||||
|
})
|
||||||
|
/*
|
||||||
|
* The `vd` macro adds a Vertical Dimension (vd)
|
||||||
|
* It takes a from and to point, and an x value
|
||||||
|
* at which to place the dimension
|
||||||
|
*/
|
||||||
|
macro("vd", {
|
||||||
|
from: points.bottomRightStart,
|
||||||
|
to: points.bottom,
|
||||||
|
x: points.bottomRight.x + 15
|
||||||
|
})
|
||||||
|
/*
|
||||||
|
* Let's do a few more of these
|
||||||
|
*/
|
||||||
|
macro("vd", {
|
||||||
|
from: points.bottomRightStart,
|
||||||
|
to: points.right,
|
||||||
|
x: points.bottomRight.x + 30
|
||||||
|
})
|
||||||
|
macro("vd", {
|
||||||
|
from: points.bottomRightStart,
|
||||||
|
to: points.tipLeftTopStart,
|
||||||
|
x: points.bottomRight.x + 45
|
||||||
|
})
|
||||||
|
macro("hd", {
|
||||||
|
from: points.left,
|
||||||
|
to: points.right,
|
||||||
|
y: points.left.y + 25
|
||||||
|
})
|
||||||
|
/*
|
||||||
|
* The `ld` macro adds a Linear Dimension (ld)
|
||||||
|
* It takes a from and to point, and a d value
|
||||||
|
* that sets its offset from the line from -> to
|
||||||
|
*/
|
||||||
|
macro("ld", {
|
||||||
|
from: points.tipLeftBottomEnd,
|
||||||
|
to: points.tipLeftTopStart,
|
||||||
|
d: 15
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// highlight-end
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return part
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</Example>
|
|
@ -117,9 +117,6 @@ function draftBib({
|
||||||
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Snap anchor
|
|
||||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
|
||||||
|
|
||||||
// Add points for second strap
|
// Add points for second strap
|
||||||
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
|
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
|
||||||
points.topCp1 = points.topCp2.flipX()
|
points.topCp1 = points.topCp2.flipX()
|
||||||
|
@ -131,7 +128,6 @@ function draftBib({
|
||||||
points.tipLeftBottomCp1 = points.tipRightBottomCp1.flipX()
|
points.tipLeftBottomCp1 = points.tipRightBottomCp1.flipX()
|
||||||
points.tipLeftBottomCp2 = points.tipRightBottomCp2.flipX()
|
points.tipLeftBottomCp2 = points.tipRightBottomCp2.flipX()
|
||||||
points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
|
points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
|
||||||
points.snapRight = points.snapLeft.flipX()
|
|
||||||
|
|
||||||
// highlight-start
|
// highlight-start
|
||||||
// Round the bottom corners
|
// Round the bottom corners
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue