1
0
Fork 0

wip(markdown): Work on tutorial

This commit is contained in:
Joost De Cock 2022-10-10 04:50:43 +02:00
parent ed576747d8
commit 2d5cdf5806
6 changed files with 339 additions and 153 deletions

View file

@ -3,58 +3,111 @@ title: Completing the neck opening
order: 180
---
## Hiding our quarter neck
We've constructed the perfectly sized quarter neck, and we're going to use this
to create our complete neck path by flipping and mirroring it.
## Hiding our quarter neck opening
To make our code easier to understand, we're going to leave the `quarterNeck` path
as it is, and simply chose to not show it.
To accomplish this, update the code and add this one line:
To accomplish this, we'll call the `hide()` method on our path:
<Example tutorial caption="A hidden path is not shown">
```js
function draftBib({
Path,
Point,
paths,
points,
measurements,
options,
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)
.setRender(false) // <== Add this line
```
.hide() // Add this line
We're saying: don't render this path. In other words, don't show it.
The path is now known, and we can still use it to calculate the length of the neck opening.
delta = paths.quarterNeck.length() - target
if (delta > 0) tweak = tweak * 0.99
else tweak = tweak * 1.02
} while (Math.abs(delta) > 1)
return part
}
```
</Example>
We're saying: _hide this path_. In other words, don't show it.
The path is still known, and we can still use it to calculate the length of the neck opening.
But it won't show up on screen or on the page.
## Create the complete neck path
## Create the complete neck opening
Now that we've hidden our homework, let's create the complete neck path.
As the neck opening is symmetrical, there's no need to re-calculate the points
on the other side. You can just flip them over, so to speak. And that's exactly what you'll do.
on the other side. You can just flip them over, so to speak. And that's exactly
what you'll do.
Below your code (under the line with `while` on it), let's add some more points:
Let's add some more points, and then construct the complete path for the neck
opening.
<Example tutorial caption="Our completed neck opening">
```js
function draftBib({
Path,
Point,
paths,
points,
measurements,
options,
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()
```
<Note>
We're using the `Point.flipX()` and `Point.flipY()` methods here.
Perhaps you can figure out what they do? If not, check [the API documentation](/reference/api/point/).
</Note>
Then, below those new points, and the following code to create your path for the neck opening:
```js
paths.neck = new Path()
.move(points.top)
.curve(points.topCp2, points.leftCp1, points.left)
@ -62,8 +115,17 @@ paths.neck = new Path()
.curve(points.bottomCp2, points.rightCp1, points.right)
.curve(points.rightCp2, points.topCp1, points.top)
.close()
```
.addClass('fabric')
<Example pattern="tutorial" part="step4">
And now you have a complete neck opening
return part
}
```
</Example>
To add the points, we're using the `Point.flipX()` and `Point.flipY()` methods
here. There's a few new Path methods to, like `close()` and `addClass()`.
Perhaps you can figure out what they do? If not, both [the Point
documentation](/reference/api/point/) and [the Path
documentation](/reference/api/path) have detailed info on all the methods
available, including these.

View file

@ -3,34 +3,53 @@ title: Constructing the neck opening
order: 160
---
Your goal is to construct a slightly oval neck opening that has a circumference that is
the `head` measurements multiplied by the `neckRatio` option.
Our goal is to construct an oval neck opening that has a circumference
that is the `head` measurements multiplied by the `neckRatio` option.
That might involve some trial and error. But since the neck opening will be symetric
both horizontal and vertical, you only need to construct one quadrant.
both horizontal and vertical, we only need to construct one quadrant.
We'll be adding some points to our pattern to do just that. But we want to have access
to our measurements and options to do so. For this, you first update the shorthand call
to indicate you also want access to `measurements` and `options`:
## Desructuring measurements and options
```js
const {
Point,
points,
We'll be adding some points to our pattern to do just that. But we want to have
access to our measurements and options to do so. For this, we first destructure
`measurements` and `options` so we can access them:
```design/src/bib.mjs
function draftBib({
Path,
Point,
paths,
complete,
sa,
paperless,
points,
// Add the following two lines:
measurements,
options
} = part.shorthand()
part,
}) {
return part
}
```
Great. Now let's get to work:
Great. Now let's get to work.
## Drawing our first path
Let's add some points, and use them to draw our first curve:
<Example tutorial caption="Our very first path forms a quarter of our neck opening">
```js
// Design pattern here
function draftBib({
Path,
Point,
paths,
points,
measurements,
options,
part,
}) {
// Construct the quarter neck opening
points.right = new Point(measurements.head / 10, 0)
points.bottom = new Point(0, measurements.head / 12)
@ -42,44 +61,61 @@ points.bottomCp2 = points.bottom
paths.quarterNeck = new Path()
.move(points.right)
.curve(points.rightCp1, points.bottomCp2, points.bottom)
```
You've added some points to your part, and drawn your first path. Let's look at each line in detail:
return part
}
```
</Example>
You've added some points to your part, and drawn your first path.
Let's look at each line in detail.
## Adding points
```js
points.right = new Point(measurements.head / 10, 0)
```
- We're adding a point named `right` to `points` which holds our part's points
- We're using the Point constructor, which takes two arguments: The point's X and Y values
- We're adding a point named `right` to the `points` object which holds our
part's points
- We're using the Point constructor, which takes two arguments: The point's X
and Y values
- The X value is `measurements.head / 10`
- The Y value is `0`
The `bottom` part is very similar, so let's skip to the next line:
The creation of `points.bottom` is very similar, so let's skip to the next line:
```js
points.rightCp1 = points.right
.shift(90, points.bottom.dy(points.right)/2)
```
- We're adding a point named `rightCp1`, which will become the _control point_ of the right part
- Instead of using the Point constructor, we're calling the `Point.shift()` method on an existing point
- We're adding a point named `rightCp1`, which will become the _control point_
of the right part
- Instead of using the Point constructor, we're calling the `Point.shift()`
method on an existing point
- It takes two arguments: The angle to shift towards, and the distance
- You can see that we're shifting 90 degrees (that means up) but the distance uses another method
- The `Point.dy()` method returns the delta along the Y axis between the point you call it on and the point you pass it
- You can see that we're shifting 90 degrees (that means up) but the distance
uses another method
- The `Point.dy()` method returns the delta along the Y axis between the point
you call it on and the point you pass it
- We shift half of the Y-delta
The next point is very similar again, except that this time we're shifting to the right (0 degrees) for half of
the X-delta between points `bottom` and `right`.
The next point is very similar again, except that this time we're shifting to
the right (0 degrees) for half of the X-delta between points `bottom` and
`right`.
<Tip>
##### Further reading
The `Point.shift()` and `Point.dy()` are just the tip of the iceberg.
Points come with a bunch of these methods.
You can find them all in [the Point API docs](/reference/api/point/).
</Tip>
The next line introduces you to something new: Paths:
## Adding paths
Adding points is typically merely a means to an end. And that end gets
introduced on the next line: Paths.
```js
paths.quarterNeck = new Path()
@ -87,20 +123,20 @@ paths.quarterNeck = new Path()
.curve(points.rightCp1, points.bottomCp2, points.bottom)
```
- We're adding a path named `quarterNeck` to `paths` which holds our part's paths
- We're adding a path named `quarterNeck` to the `paths` object which holds our
part's paths
- We're using the Path constructor, which takes no arguments
- We're following up with a `Path.move()` call that takes one Point as argument
- Then, there's a `Path.curve()` call that takes 3 points as arguments
If you've read through the high-level [Pattern guide](/guides/patterns/) you will have learned that paths
always start with a `move()` operation. In this case, we moved to our `right` points.
If you've read through the high-level [Pattern guide](/guides/patterns) you
will have learned that paths always start with a `move()` operation. In this
case, we moved to our `right` points.
From there, we drew a Bezier curve to our `bottom` point by using `rightCp1` and `bottomCp2` as control points.
When all is said and done, we now have a quarter of our neck opening:
<Example pattern="tutorial" part="step2">You have drawn your first path</Example>
From there, we drew a cubic Bezier curve to our `bottom` point by using
`rightCp1` and `bottomCp2` as control points.
When all is said and done, we now have a quarter of our neck opening.
The only problem is, we have no guarantee whatsoever that this opening is the correct size.
Rather than hope it is the correct size, you'll make sure it is next.
Rather than hope it is the correct size, we'll make sure it is next.

View file

@ -28,6 +28,16 @@ need to draft your method. Destructuring is a way to *pull things out of the
object into their own variable*. It saves us a bunch of typing as these two are
equivalent:
<Tabs tabs="Without destructuring, With destructuring">
<Tab>
```design/src/bib.mjs
function draftBib({ part }) {
return part
}
```
</Tab>
<Tab>
```design/src/bib.mjs
function draftBib(props) {
@ -35,13 +45,8 @@ function draftBib(props) {
}
```
```design/src/bib.mjs
function draftBib({ part }) {
return part
}
```
</Tab>
</Tabs>
As we'll make our way through this tutorial, we'll need more and more stuff, so
we'll be pulling it out of the object passed to the draft method via

View file

@ -3,16 +3,68 @@ title: Drawing the bib outline
order: 190
---
With our neck opening in place, let's draw the basic outline of our bib:
With our neck opening in place, let us draw the basic outline of our bib.
<Example tutorial caption="Note how the neck opening is the same distance from the left, right, and top edge">
```js
let width = measurements.head * options.widthRatio
let length = measurements.head * options.lengthRatio
function draftBib({
Path,
Point,
paths,
points,
measurements,
options,
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()
paths.neck = new Path()
.move(points.top)
.curve(points.topCp2, points.leftCp1, points.left)
.curve(points.leftCp2, points.bottomCp1, points.bottom)
.curve(points.bottomCp2, points.rightCp1, points.right)
.curve(points.rightCp2, points.topCp1, points.top)
.close()
.addClass('fabric')
// 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)
@ -24,14 +76,19 @@ paths.rect = new Path()
.line(points.topRight)
.line(points.topLeft)
.close()
.addClass('fabric')
return part
}
```
</Example>
First thing we did was create the `width` and `length` variables to
save ourselves some typing:
```js
let width = measurements.head * options.widthRatio
let length = measurements.head * options.lengthRatio
const width = measurements.head * options.widthRatio
const length = measurements.head * options.lengthRatio
```
Both the length and width of your bib are a factor of the head circumference.
@ -56,13 +113,11 @@ paths.rect = new Path()
.line(points.topRight)
.line(points.topLeft)
.close()
.addClass('fabric')
```
We're calculating the `topLeft` point so that the top edge of our bib
and the sides are equidistant from the neck neck opening.
You didn't have to do that. But it looks nicely balanced this way:
We didn't have to do that. But it looks nicely balanced this way.
<Example pattern="tutorial" part="step5">
Note how the neck opening is the same distance from the left, right, and top edge
</Example>

View file

@ -5,6 +5,14 @@ title: Pattern design tutorial
Welcome to the FreeSewing pattern design tutorial, where you'll learn how to
design a made-to-measure sewing pattern, start to finish.
<Tip>
##### Before you start
If you haven't done so yet, read the [Before you start
guide](/guides/prerequisites). It's very short, but covers some basic
terminology and concepts that we'll use throughout this guide.
</Tip>
You will be designing a pattern for a baby bib. It's a very simple pattern, but
that's the point. Your focus today is on learning FreeSewing and how to
translate your designs into code.

View file

@ -3,9 +3,23 @@ title: Fitting the neck opening
order: 170
---
Here's how we'll make sure the neck opening is _just right_:
We are not going to create some opening that we _hope_ is the right size, we're
going to make sure it is. Here's how we'll make sure the neck opening is _just
right_:
<Example tutorial caption="It might look the same as before, but now it's just right">
```js
function draftBib({
Path,
Point,
paths,
points,
measurements,
options,
part,
}) {
// Construct the quarter neck opening
let tweak = 1
let target = (measurements.head * options.neckRatio) /4
let delta
@ -24,27 +38,33 @@ do {
if (delta > 0) tweak = tweak * 0.99
else tweak = tweak * 1.02
} while (Math.abs(delta) > 1)
return part
}
```
</Example>
We've added a few new variables:
- `tweak`: A _tweak factor_ that we'll use to increase or decrease the neck opening by making it more or less than 1
- `tweak`: A _tweak factor_ that we'll use to increase or decrease the neck
opening by making it more or less than 1
- `target`: How long our (quarter) neck opening should be
- `delta`: How far we're off. Positive numbers mean it's too long, negative means too short
- `delta`: How far we're off. Positive numbers mean it's too long, negative
means too short
Now that we know what `target` is, we construct our path as we did before.
But this time around, we multiply our point coordinates with our `tweak` variable (1 at the start).
Now that we know what `target` is, we construct our path as we did before. But
this time around, we multiply our point coordinates with our `tweak` variable
(1 at the start).
Then, we compare our `target` to the result of `paths.neck.length()` which — you guessed it — returns the
length of our neck path.
Then, we compare our `target` to the result of `paths.neck.length()` which —
you guessed it — returns the length of our neck path.
If the delta is positive, our path is too long and we reduce the tweak factor.
If the delta is negative, our path is too short and we increase the tweak factor.
If the delta is negative, our path is too short and we increase the tweak
factor.
We keep on doing this until `Math.abs(delta)` is less than 1. Meaning that we are within 1mm of our target value.
We keep on doing this until `Math.abs(delta)` is less than 1. Meaning that we
are within 1mm of our target value.
<Example pattern="tutorial" part="step2">
It might look the same as before, but now it's just right
</Example>
Now that we're happy with the length of our quarter neck opening, let's construct the entire neck opening.
Now that we're happy with the length of our quarter neck opening, let's
construct the entire neck opening.