feat: Add various content types to docusaurus (#7231)
This brings blog posts, showcase posts, and newsletter editions into the Docusaurus site. It also adds support for using TailwindCSS inside a container. So this will probably end up being the new freesewing.org site in v4.
This commit is contained in:
parent
ef8f68bcaf
commit
469eb43c95
595 changed files with 20432 additions and 2469 deletions
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Getting started with Codespaces
|
||||
order: 13
|
||||
sidebar_position: 13
|
||||
---
|
||||
|
||||
:::note
|
||||
|
@ -29,19 +29,22 @@ to have or use your own computer to perform this development work.
|
|||
## Accessing Codespaces
|
||||
|
||||
Access Codespaces from the GitHub website while logged in:
|
||||
|
||||
- The "Your Codespaces" page is accessed via the "Codespaces" link at the top
|
||||
of any GitHub page.
|
||||
of any GitHub page.
|
||||
- A shortcut URL is: https://github.com/codespaces
|
||||
|
||||
## Creating a codespace
|
||||
|
||||
To create a new codespace:
|
||||
|
||||
- Select the "New codespace" button at the top of the Your Codespaces page.
|
||||
- A shortcut URL is: https://github.com/codespaces/new
|
||||
|
||||
This will open a "Create a New Codespace" page.
|
||||
|
||||
On the Create a New Codespace page, select the options for your codespace:
|
||||
|
||||
- Repository -> ("`username/freesewing`" assuming that is the name of your GitHub repository)
|
||||
- Branch -> (select the branch you want to use)
|
||||
- Region -> (select the region most appropriate for you)
|
||||
|
@ -52,14 +55,13 @@ The Codespaces app will open in the browser window.
|
|||
The Codespaces app is basically the [Visual Studio Code][vs] app with
|
||||
Codespaces and GitHub integration built in.
|
||||
|
||||
[vs]: https://code.visualstudio.com
|
||||
|
||||
(Wait 45 seconds or so for the Codespace app to clone the repository from
|
||||
GitHub to the codespace repository and start.)
|
||||
[vs]: https://code.visualstudio.com 'Wait 45 seconds or so for the Codespace app to clone the repository from
|
||||
GitHub to the codespace repository and start.'
|
||||
|
||||
## Editing files
|
||||
|
||||
You can browse and edit files in your codespace repository from within the app:
|
||||
|
||||
- On the Activity Bar on the far left side of the page, select the
|
||||
Explorer icon.
|
||||
(The icon looks like two pages of paper.)
|
||||
|
@ -72,6 +74,7 @@ Auto-save is enabled by default, so any changes you make are
|
|||
automatically saved in your codespace repository.
|
||||
|
||||
To commit changes to your codespace repository:
|
||||
|
||||
- In the Activity Bar on the far left side of the page,
|
||||
select the Source Control icon.
|
||||
- In the Source Control sidebar you can see a list of changed files.
|
||||
|
@ -82,6 +85,7 @@ To commit changes to your codespace repository:
|
|||
|
||||
To push committed changes from your codespace repository back to your
|
||||
GitHub repository:
|
||||
|
||||
- After committing changes to your codespace repository, press the
|
||||
"Sync Changes" button to push the committed changes to your GitHub
|
||||
repository.
|
||||
|
@ -94,13 +98,16 @@ GitHub repository:
|
|||
In the "Terminal" panel at the bottom of the page, you can run commands.
|
||||
|
||||
To start the lab website (to view and test new designs and design changes):
|
||||
|
||||
- In the Terminal panel, run `yarn kickstart` and then `yarn lab`.
|
||||
|
||||
To start the dev or org websites (to view and test documentation changes):
|
||||
|
||||
- dev: In the Terminal panel, run `cd sites/dev` and `yarn start`.
|
||||
- org: In the Terminal panel, run `cd sites/org` and `yarn start`.
|
||||
|
||||
After the lab, dev, or org website starts:
|
||||
|
||||
- The usual `localhost:8000` port will automatically be forwarded to a custom
|
||||
URL.
|
||||
- A pop-up will appear saying that the port has been forwarded. The "Open in
|
||||
|
@ -122,6 +129,7 @@ However, you can make the port public so others can access it
|
|||
(or so you can access it on a different browser while not logged into GitHub).
|
||||
|
||||
To make the port public:
|
||||
|
||||
- In the Ports panel, right-click on the port and select
|
||||
Port Visibility -> Public.
|
||||
- The custom URL will be now be a publicly-accessible forwarded port.
|
||||
|
@ -130,6 +138,7 @@ To make the port public:
|
|||
## Starting and stopping a codespace
|
||||
|
||||
You can start and stop your codespace via the Your Codespaces page.
|
||||
|
||||
- To start: Click on the codespace name to browse to the Codespaces
|
||||
app URL for that codespace.
|
||||
(You can also right-click to copy the URL and open it in a
|
||||
|
@ -150,7 +159,8 @@ You can rename a codespace to make it easier to identify.
|
|||
(This will help if you have more than one codespace.)
|
||||
|
||||
To rename a codespace:
|
||||
- Go to the Your Codespaces page.
|
||||
|
||||
- Go to the Your Codespaces page.
|
||||
- Open the "..." ellipses menu next to the codespace
|
||||
and select "Rename".
|
||||
|
||||
|
@ -158,17 +168,18 @@ To rename a codespace:
|
|||
|
||||
You can access GitHub Settings via the user icon menu in the upper right
|
||||
corner of any GitHub page (but not on the Codespaces app page).
|
||||
|
||||
- Selecting the "Settings" menu item will open the GitHub Settings page.
|
||||
- The Codespaces settings are under "Codespaces" in the left sidebar
|
||||
on the Settings page.
|
||||
on the Settings page.
|
||||
- A shortcut URL is: https://github.com/settings/codespaces
|
||||
|
||||
|
||||
Among the Codespaces settings available are:
|
||||
|
||||
- "Default idle timeout" (how long codespaces continue to run when idle,
|
||||
before being stopped)
|
||||
before being stopped)
|
||||
- "Default retention period" (how long codespace repositories are kept
|
||||
when unused, before being deleted)
|
||||
when unused, before being deleted)
|
||||
|
||||
:::note
|
||||
Do not be confused by the other Settings icon/menu at the bottom left of the
|
||||
|
@ -180,11 +191,13 @@ are located.
|
|||
## Usage and Quotas
|
||||
|
||||
To check usage:
|
||||
|
||||
- Usage information is under "Billing and plans" in the left sidebar on
|
||||
the Settings page.
|
||||
- A shortcut URL is: https://github.com/settings/billing
|
||||
|
||||
About quotas:
|
||||
|
||||
- As a free account user, you have a quota of 120 core-hours of usage
|
||||
and 15 GB of storage per billing month.
|
||||
That is the total for all your codespaces combined.
|
||||
|
@ -209,18 +222,20 @@ Don't worry -- you won't get a bill if you exceed your quota!
|
|||
Instead, you will just be unable to start any of your codespaces
|
||||
until the start of the next billing month.
|
||||
And, if you have any work-in-progress changes that you need access to
|
||||
before then, you can export those changes to a new GitHub branch.
|
||||
before then, you can export those changes to a new GitHub branch.
|
||||
:::
|
||||
|
||||
## Deleting a codespace
|
||||
|
||||
To delete a codespace:
|
||||
|
||||
- Go to the Your Codespaces page.
|
||||
- Open the "..." ellipses menu next to the codespace
|
||||
and select "Delete".
|
||||
|
||||
:::note RELATED
|
||||
For more information, please see:
|
||||
|
||||
- [GitHub Codebases documentation](https://docs.github.com/en/codespaces).
|
||||
- [About billing for GitHub Codespaces](https://docs.github.com/en/billing/managing-billing-for-github-codespaces/about-billing-for-github-codespaces)
|
||||
:::
|
||||
:::
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Getting started with Gitpod
|
||||
order: 10
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
If you don't want to set up a dev environment or if you just want to kick the
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Setting up the FreeSewing development environment
|
||||
order: 40
|
||||
sidebar_position: 40
|
||||
---
|
||||
|
||||
FreeSewing provides a development environment to help you design and develop
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Start the development environment
|
||||
order: 50
|
||||
sidebar_position: 50
|
||||
---
|
||||
|
||||
FreeSewing provides a development environment to help you design and develop patterns.
|
||||
|
@ -21,7 +21,9 @@ yarn lab
|
|||
Then point your browser to http://localhost:8000
|
||||
|
||||
:::tip
|
||||
|
||||
### Adding a new design
|
||||
|
||||
This is all you need to work on existing designs. If you'd like to add a new design, run:
|
||||
|
||||
```bash
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Installing Node.js
|
||||
order: 20
|
||||
sidebar_position: 20
|
||||
---
|
||||
|
||||
Now we will use `nvm` to install Node.js. Run the following command:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Installing nvm
|
||||
order: 10
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
FreeSewing is built with [Node.js](https://nodejs.org/), a JavaScript runtime.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Using a different Node.js version
|
||||
order: 30
|
||||
sidebar_position: 30
|
||||
---
|
||||
|
||||
Now that you've got Node.js setup, we can start setting up the FreeSewing
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Getting started on Linux
|
||||
order: 15
|
||||
sidebar_position: 15
|
||||
---
|
||||
|
||||
In this tutorial, we will setup Node.js and initialize the FreeSewing
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Setting up the FreeSewing development environment
|
||||
order: 40
|
||||
sidebar_position: 40
|
||||
---
|
||||
|
||||
FreeSewing provides a development environment to help you design and develop
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Start the development environment
|
||||
order: 50
|
||||
sidebar_position: 50
|
||||
---
|
||||
|
||||
FreeSewing provides a development environment to help you design and develop patterns.
|
||||
|
@ -21,7 +21,9 @@ yarn lab
|
|||
Then point your browser to http://localhost:8000
|
||||
|
||||
:::tip
|
||||
|
||||
### Adding a new design
|
||||
|
||||
This is all you need to work on existing designs. If you'd like to add a new design, run:
|
||||
|
||||
```bash
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Installing Node.js
|
||||
order: 20
|
||||
sidebar_position: 20
|
||||
---
|
||||
|
||||
Now we will use `nvm` to install Node.js. Run the following command:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Installing nvm
|
||||
order: 15
|
||||
sidebar_position: 15
|
||||
---
|
||||
|
||||
FreeSewing is built with [Node.js](https://nodejs.org/), a JavaScript runtime.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Installing the Xcode command line tools
|
||||
order: 10
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
Before we can get started, we need some basic tools for development.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Using a different Node.js version
|
||||
order: 30
|
||||
sidebar_position: 30
|
||||
---
|
||||
|
||||
Now that you've got Node.js setup, we can start setting up the FreeSewing
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Getting started on Mac
|
||||
order: 25
|
||||
sidebar_position: 25
|
||||
---
|
||||
|
||||
In this tutorial, we will setup Node.js and initialize the FreeSewing
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Getting started with Vercel
|
||||
order: 14
|
||||
sidebar_position: 14
|
||||
---
|
||||
|
||||
## What is Vercel?
|
||||
|
@ -23,6 +23,7 @@ containing a fork of the FreeSewing repository.
|
|||
## Why you might want to use Vercel
|
||||
|
||||
There are reasons why you might want your own Vercel account:
|
||||
|
||||
- You can preview your changes:
|
||||
- if you develop on a mobile device or if you do not have access to a
|
||||
computer.
|
||||
|
@ -61,7 +62,7 @@ Free Hobby accounts are limited to 3 Projects per Git repository.
|
|||
|
||||
Under each project there will be many, many deployments.
|
||||
|
||||
_Deployments are simply builds, an instance of a website/app
|
||||
\_Deployments are simply builds, an instance of a website/app
|
||||
built from a specific commit version of a specific branch of the repository.
|
||||
These deployments can be accessed using a web browser to preview
|
||||
the web app or website.
|
||||
|
@ -103,11 +104,11 @@ account/credentials without having to create a separate username
|
|||
or password.
|
||||
|
||||
1. On the [Vercel website][v] select the "Sign Up" button.
|
||||
(A shortcut URL is: [https://vercel.com/signup][vsu].)
|
||||
(A shortcut URL is: [https://vercel.com/signup][vsu].)
|
||||
2. Select the "Continue with GitHub" button.
|
||||
3. A pop-up window will appear asking you for permission to access
|
||||
your GitHub information.
|
||||
Press the green "Authorize Vercel" button to continue.
|
||||
your GitHub information.
|
||||
Press the green "Authorize Vercel" button to continue.
|
||||
|
||||
[v]: https://vercel.com
|
||||
[vsu]: https://vercel.com/signup
|
||||
|
@ -125,12 +126,12 @@ FreeSewing repository.
|
|||
2. Select your personal GitHub account from the list.
|
||||
3. Select the "Only select repositories" radio button.
|
||||
4. In "Select repositories" drop-down menu, select your `freesewing`
|
||||
repository.
|
||||
repository.
|
||||
5. Click the green "Install" button.
|
||||
6. Confirm that you are giving permission to access the repository
|
||||
by entering your GitHub password.
|
||||
by entering your GitHub password.
|
||||
7. Finally, back at the Import Git Repository screen complete the
|
||||
import by selecting the white "Import" button.
|
||||
import by selecting the white "Import" button.
|
||||
|
||||
## Creating a project
|
||||
|
||||
|
@ -139,15 +140,16 @@ create a project.
|
|||
|
||||
By default, the default Root Directory will be `sites/dev`.
|
||||
The Root Directory setting will determine the build type for the project.
|
||||
|
||||
- `sites/dev` will build a freesewing.dev website
|
||||
- `sites/org` will build a freesewing.org website
|
||||
|
||||
1. Change the name of the project, if you wish.
|
||||
Names can consist of alphanumeric lowercase and hyphen characters.
|
||||
Names can consist of alphanumeric lowercase and hyphen characters.
|
||||
2. Change the Root Directory to the desired setting, as described above.
|
||||
3. In the Build & Development Settings,
|
||||
add `yarn build` as the Build Command override.
|
||||
(All the other settings will work fine with the default values.)
|
||||
add `yarn build` as the Build Command override.
|
||||
(All the other settings will work fine with the default values.)
|
||||
4. Press the white "Deploy" button.
|
||||
|
||||
Vercel will then create the project and start building the project's first
|
||||
|
@ -167,17 +169,18 @@ ones based on the `develop` branch
|
|||
`develop` instead of `main).
|
||||
|
||||
Created deployments include:
|
||||
|
||||
1. The initial production deployment. (Because you don't have a branch named
|
||||
`main` in your repository, Vercel will instead create the initial
|
||||
production deployment from the default `develop` branch.)
|
||||
`main` in your repository, Vercel will instead create the initial
|
||||
production deployment from the default `develop` branch.)
|
||||
2. A new preview deployment every time you update your `develop` branch in GitHub
|
||||
(for example, whenever you sync it with the latest `freesewing/freesewing`
|
||||
updates)
|
||||
(for example, whenever you sync it with the latest `freesewing/freesewing`
|
||||
updates)
|
||||
3. A new preview deployment for every new branch you push to GitHub
|
||||
4. A new preview deployment for every update you make to these new branches
|
||||
when you push to GitHub
|
||||
when you push to GitHub
|
||||
5. A new preview deployment for every update you make to your existing branches
|
||||
when you push to GitHub
|
||||
when you push to GitHub
|
||||
|
||||
If you have multiple projects for the same repository
|
||||
(for example, if you have both `sites/org` and `sites/dev` projects),
|
||||
|
@ -196,7 +199,7 @@ Once they start, deployments take about
|
|||
You will manage your account and projects from the Vercel Dashboard
|
||||
page, [https://vercel.com/dashboard][vd].
|
||||
|
||||
The default __Overview__ tab at the top of the Dashboard page will show your repositories
|
||||
The default **Overview** tab at the top of the Dashboard page will show your repositories
|
||||
and projects.
|
||||
Click on a project name to go to its project page.
|
||||
|
||||
|
@ -204,31 +207,32 @@ Click on a project name to go to its project page.
|
|||
|
||||
## Project pages
|
||||
|
||||
The default __Project__ tab at the top of the project page will show the
|
||||
The default **Project** tab at the top of the project page will show the
|
||||
the production deployment and some of the most recent preview
|
||||
deployments for that project.
|
||||
|
||||
Click on the __Deployments__ tab to see all of the project's deployments.
|
||||
Click on the **Deployments** tab to see all of the project's deployments.
|
||||
Click on a deployment name to go to its deployment page.
|
||||
|
||||
Click on the __Settings__ tab to see the project's settings.
|
||||
Click on the **Settings** tab to see the project's settings.
|
||||
|
||||
## Deployment pages
|
||||
|
||||
On the default __Deployment__ tab at the top of the deployment page
|
||||
On the default **Deployment** tab at the top of the deployment page
|
||||
you will see information about the deployment.
|
||||
|
||||
Under __Domains__ you will see one or more URLs that can be used to
|
||||
Under **Domains** you will see one or more URLs that can be used to
|
||||
access the deployment.
|
||||
These are also the URLs that you can share with others so they
|
||||
can view your deployments.
|
||||
|
||||
- URLs containing hash characters link to the deployment for a single
|
||||
commit.
|
||||
commit.
|
||||
- URLs without a hash point to the deployment for the latest version
|
||||
of that branch.
|
||||
of that branch.
|
||||
|
||||
If you ever want to delete a deployment you can do so on its
|
||||
deployment page, under the "__...__" three dots menu.
|
||||
deployment page, under the "**...**" three dots menu.
|
||||
|
||||
## Usage and Billing
|
||||
|
||||
|
@ -237,11 +241,12 @@ Vercel's free Hobby accounts come with
|
|||
This should be at least 10-15x the amount you will actually use in
|
||||
a month, so do not worry about this.
|
||||
|
||||
If you want to check your usage, please seee the __Usage__ tab at the
|
||||
If you want to check your usage, please seee the **Usage** tab at the
|
||||
top of the Dashboard page.
|
||||
|
||||
- A shortcut URL is [https://vercel.com/dashboard/usage][vu]
|
||||
- Or, [https://vercel.com/account/billing][vb] will show a summary
|
||||
of your usage.
|
||||
of your usage.
|
||||
|
||||
## Disabling automatic deployments
|
||||
|
||||
|
@ -249,8 +254,8 @@ You can disable and enable automatic deployments for a project,
|
|||
for example if you wish to temporarily stop them while working on
|
||||
a bug that prevents successful builds.
|
||||
|
||||
On the Project Settings page, select __Git__ from the menu on the
|
||||
left. Change the __Ignored Build Step__ behavior from "Automatic" to
|
||||
On the Project Settings page, select **Git** from the menu on the
|
||||
left. Change the **Ignored Build Step** behavior from "Automatic" to
|
||||
"Don't build anything".
|
||||
|
||||
[vu]: https://vercel.com/dashboard/usage
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Getting started on Windows
|
||||
order: 30
|
||||
sidebar_position: 30
|
||||
---
|
||||
|
||||
:::warning
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Setting up the development environment
|
||||
order: 20
|
||||
sidebar_position: 20
|
||||
---
|
||||
|
||||
FreeSewing provides a development environment that visualizes your design for
|
||||
|
@ -18,7 +18,7 @@ It will ask if it is ok to install the development environment in a new folder
|
|||
named `freesewing`. You can accept the default, or pick a different folder name
|
||||
if you prefer.
|
||||
|
||||
It will also ask what package manager you would like to use.
|
||||
It will also ask what package manager you would like to use.
|
||||
Here too the default (`npm`) is fine., unless you are certain you have **yarn** installed.
|
||||
|
||||
After answering these questions, files will be downloaded, dependencies installed,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Installing NodeJS
|
||||
order: 10
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
FreeSewing is a JavaScript project, so you need JavaScript to work with it.
|
||||
|
@ -9,14 +9,15 @@ precise. You can switch this website theme from light to dark mode, and
|
|||
that would not work without JavaScript.
|
||||
|
||||
As a **user** of FreeSewing, this is all you need. To develop with FreeSewing
|
||||
you are going to need to be able to run JavaScript *outside* the browser using
|
||||
a JavaScript *runtime*. Which just means a thing that can *run* JavaScript.
|
||||
you are going to need to be able to run JavaScript _outside_ the browser using
|
||||
a JavaScript _runtime_. Which just means a thing that can _run_ JavaScript.
|
||||
|
||||
We are going to be using [NodeJS](https://nodejs.org/) in this tutorial. It is
|
||||
the most established of the different JavaScript runtimes. But there's also
|
||||
other runtimes like [Deno](https://deno.com/) or [Bun](https://bun.sh/).
|
||||
the most established of the different JavaScript runtimes. But there's also
|
||||
other runtimes like [Deno](https://deno.com/) or [Bun](https://bun.sh/).
|
||||
|
||||
## Install
|
||||
|
||||
If you don't have NodeJS on your system, you can go to
|
||||
[NodeJS.org](https://nodejs.org/) and follow the install instructions.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: The FreeSewing development environment
|
||||
order: 30
|
||||
sidebar_position: 30
|
||||
---
|
||||
|
||||
If you have been to FreeSewing.org the FreeSewing development environment will look familiar.
|
||||
|
@ -44,4 +44,3 @@ For the following along this tutorial, you have two options:
|
|||
- Pick **From scratch** if you prefer to actively participate by recreating the design in this tutorial.
|
||||
|
||||
I recommend the latter. You will learn (and remember) a lot more if you are actively engaging.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Folder structure
|
||||
order: 40
|
||||
sidebar_position: 40
|
||||
---
|
||||
|
||||
Inside the `freesewing` folder -- which might have a different name if that is
|
||||
|
@ -23,10 +23,10 @@ this menu:
|
|||

|
||||
|
||||
As you might have guessed by now, each of these options is contained in its
|
||||
own subfolder under `designs`.
|
||||
own subfolder under `designs`.
|
||||
|
||||
You can edit the files under `designs/[template]/src/` and the changes you make
|
||||
will be reflected in the development environment.
|
||||
|
||||
Don't take my word for it though. Let's start doing exactly that
|
||||
Don't take my word for it though. Let's start doing exactly that
|
||||
in [Part 2](/tutorials/pattern-design/part2).
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
title: Adding measurements
|
||||
order: 30
|
||||
sidebar_position: 30
|
||||
---
|
||||
|
||||
FreeSewing is all about _bespoke_ sewing patterns -- or *parametric
|
||||
design* to use a more generic term.
|
||||
FreeSewing is all about _bespoke_ sewing patterns -- or _parametric
|
||||
design_ to use a more generic term.
|
||||
|
||||
That means that when drafting our pattern, I will take the measurements provided
|
||||
by the user into account.
|
||||
|
@ -21,7 +21,7 @@ So let's add it as a required measurement.
|
|||
In our `src/bib.mjs` file, we will add a `measurements` property to the `bib` object.
|
||||
This property will be an Array (a list) holding all required measurements for this part.
|
||||
|
||||
I am using [*the official name* of the measurement](/reference/measurements) here. For head
|
||||
I am using [_the official name_ of the measurement](/reference/measurements) here. For head
|
||||
circumference, that name is `head`.
|
||||
|
||||
:::note [FIXME]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Adding options
|
||||
order: 40
|
||||
sidebar_position: 40
|
||||
---
|
||||
|
||||
I have shown what our bib should look like, and added the _head_ measurement
|
||||
|
@ -12,7 +12,7 @@ to work with. But there's still a number of choices I have to make:
|
|||
|
||||
I could make all of these choices for the user and set them in stone, so to speak.
|
||||
|
||||
But since the pattern I am designing is code, it is trivial (and _IMHO_ very satisfying)
|
||||
But since the pattern I am designing is code, it is trivial (and _IMHO_ very satisfying)
|
||||
to make a pattern flexible and let the user choose.
|
||||
All I need to do to give control to the user is add _options_ to the part.
|
||||
|
||||
|
@ -34,10 +34,10 @@ export const bib = {
|
|||
measurements: [ 'head' ],
|
||||
// highlight-start
|
||||
options: {
|
||||
neckRatio: {
|
||||
pct: 80,
|
||||
min: 70,
|
||||
max: 90,
|
||||
neckRatio: {
|
||||
pct: 80,
|
||||
min: 70,
|
||||
max: 90,
|
||||
menu: 'fit'
|
||||
},
|
||||
},
|
||||
|
@ -61,7 +61,7 @@ They are all documented [in the part reference docs](/reference/api/part/config/
|
|||
|
||||
##### What is `menu` and why should you care?
|
||||
|
||||
The `menu` property on our option is *extra*.
|
||||
The `menu` property on our option is _extra_.
|
||||
It will be ignored by FreeSewing's core library and if we leave it out, our design will produce the same result.
|
||||
|
||||
Instead, this `menu` property is there for the benefit of FreeSewing's development environment which will use this to build a menu structure for the various
|
||||
|
@ -85,25 +85,25 @@ export const bib = {
|
|||
draft: draftBib,
|
||||
measurements: [ 'head' ],
|
||||
options: {
|
||||
neckRatio: {
|
||||
pct: 80,
|
||||
min: 70,
|
||||
max: 90,
|
||||
neckRatio: {
|
||||
pct: 80,
|
||||
min: 70,
|
||||
max: 90,
|
||||
menu: 'fit'
|
||||
},
|
||||
|
||||
|
||||
// highlight-start
|
||||
widthRatio: {
|
||||
pct: 45,
|
||||
min: 35,
|
||||
max: 55,
|
||||
menu: 'style'
|
||||
widthRatio: {
|
||||
pct: 45,
|
||||
min: 35,
|
||||
max: 55,
|
||||
menu: 'style'
|
||||
},
|
||||
lengthRatio: {
|
||||
pct: 75,
|
||||
min: 55,
|
||||
max: 85,
|
||||
menu: 'style'
|
||||
lengthRatio: {
|
||||
pct: 75,
|
||||
min: 55,
|
||||
max: 85,
|
||||
menu: 'style'
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
|
@ -116,4 +116,3 @@ Later, I will test-drive our pattern to see how it behaves when we adapt the opt
|
|||
between their minimum and maximum values. At that time, I may need to tweak these values.
|
||||
|
||||
With that out of the way, I will start drawing the bib.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Avoiding overlap
|
||||
order: 92
|
||||
sidebar_position: 92
|
||||
---
|
||||
|
||||
While we've only drawn the end of one strap, it's pretty obvious they overlap,
|
||||
|
@ -11,9 +11,10 @@ Specifically, we're going to rotate our strap out of the way until it no longer
|
|||
The rest of our bib should stay as it is, so let's start by making a list of points we need
|
||||
to rotate.
|
||||
|
||||
However, there is a catch.
|
||||
However, there is a catch.
|
||||
|
||||
## Macros and auto-generated IDs
|
||||
|
||||
We have used the `round` macro to help us round the corners
|
||||
of our strap, and it added a bunch of auto-generated points to our pattern. We need to
|
||||
rotate these points too, but what are their names?
|
||||
|
@ -49,7 +50,7 @@ that return value, but if we did, it would look like this:
|
|||
```
|
||||
|
||||
Those names aren't very handy to remember. So I will rewrite this code a bit to
|
||||
we'll capture these return values from the `round` macros and create
|
||||
we'll capture these return values from the `round` macros and create
|
||||
easy-to-remember points from them:
|
||||
|
||||
<Example tutorial caption="It looks the same as before, but now those macro points are accessible to us">
|
||||
|
@ -68,36 +69,38 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
/*
|
||||
* Construct the quarter neck opening
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Construct the quarter neck opening
|
||||
_/
|
||||
let tweak = 1
|
||||
let target = (measurements.head * options.neckRatio) /4
|
||||
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.right = new Point(
|
||||
tweak _ measurements.head / 10,
|
||||
0
|
||||
)
|
||||
points.bottom = new Point(
|
||||
0,
|
||||
tweak _ measurements.head / 12
|
||||
)
|
||||
|
||||
|
||||
points.rightCp1 = points.right.shift(
|
||||
90,
|
||||
90,
|
||||
points.bottom.dy(points.right) / 2
|
||||
)
|
||||
points.bottomCp2 = points.bottom.shift(
|
||||
0,
|
||||
0,
|
||||
points.bottom.dx(points.right) / 2
|
||||
)
|
||||
|
||||
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
.hide()
|
||||
|
@ -105,11 +108,13 @@ function draftBib({
|
|||
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
|
||||
*/
|
||||
} 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()
|
||||
|
@ -119,97 +124,103 @@ function draftBib({
|
|||
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')
|
||||
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)
|
||||
- Drawing the bib outline
|
||||
_/
|
||||
const width = measurements.head _ options.widthRatio
|
||||
const length = measurements.head \* options.lengthRatio
|
||||
|
||||
/*
|
||||
* Shape the straps
|
||||
*/
|
||||
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()
|
||||
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)
|
||||
// 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)
|
||||
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)
|
||||
|
||||
// highlight-start
|
||||
/*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
// highlight-start
|
||||
/\*
|
||||
|
||||
- Macros will return the auto-generated IDs
|
||||
\*/
|
||||
const ids1 = {
|
||||
tipRightTop: macro("round", {
|
||||
id: "tipRightTop",
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
hide: false
|
||||
}),
|
||||
tipRightBottom: macro("round", {
|
||||
id: "tipRightBottom",
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
hide: false
|
||||
})
|
||||
tipRightTop: macro("round", {
|
||||
id: "tipRightTop",
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
hide: false
|
||||
}),
|
||||
tipRightBottom: macro("round", {
|
||||
id: "tipRightBottom",
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
hide: false
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Create points from them with easy names
|
||||
\*/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
// highlight-end
|
||||
|
||||
/*
|
||||
* Now, adapt our `rect` path so it's no longer a rectangle:
|
||||
*/
|
||||
paths.rect = new Path()
|
||||
.move(points.edgeTop)
|
||||
.curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.edgeRight)
|
||||
.curve(points.edgeRightCp, points.edgeTopRightCp, points.edgeTop)
|
||||
.close()
|
||||
|
||||
return part
|
||||
/\*
|
||||
|
||||
- Now, adapt our `rect` path so it's no longer a rectangle:
|
||||
\*/
|
||||
paths.rect = new Path()
|
||||
.move(points.edgeTop)
|
||||
.curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.edgeRight)
|
||||
.curve(points.edgeRightCp, points.edgeTopRightCp, points.edgeTop)
|
||||
.close()
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
|
||||
````
|
||||
</Example>
|
||||
|
||||
Once we have our list of points to rotate, we can rotate them. How far? Until the strap no longer overlaps.
|
||||
|
@ -236,28 +247,28 @@ function draftBib({
|
|||
let delta
|
||||
do {
|
||||
points.right = new Point(
|
||||
tweak * measurements.head / 10,
|
||||
tweak * measurements.head / 10,
|
||||
0
|
||||
)
|
||||
points.bottom = new Point(
|
||||
0,
|
||||
0,
|
||||
tweak * measurements.head / 12
|
||||
)
|
||||
|
||||
|
||||
points.rightCp1 = points.right.shift(
|
||||
90,
|
||||
90,
|
||||
points.bottom.dy(points.right) / 2
|
||||
)
|
||||
points.bottomCp2 = points.bottom.shift(
|
||||
0,
|
||||
0,
|
||||
points.bottom.dx(points.right) / 2
|
||||
)
|
||||
|
||||
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
.hide()
|
||||
|
@ -266,7 +277,7 @@ function draftBib({
|
|||
if (delta > 0) tweak = tweak * 0.99
|
||||
else tweak = tweak * 1.02
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
|
||||
/*
|
||||
* Construct the complete neck opening
|
||||
*/
|
||||
|
@ -422,5 +433,6 @@ function draftBib({
|
|||
|
||||
return part
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
</Example>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Completing the neck opening
|
||||
order: 80
|
||||
sidebar_position: 80
|
||||
---
|
||||
|
||||
We've constructed the perfectly sized quarter neck, and we're going to use this
|
||||
|
@ -25,36 +25,38 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
/*
|
||||
* Construct the quarter neck opening
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Construct the quarter neck opening
|
||||
_/
|
||||
let tweak = 1
|
||||
let target = (measurements.head * options.neckRatio) /4
|
||||
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.right = new Point(
|
||||
tweak _ measurements.head / 10,
|
||||
0
|
||||
)
|
||||
points.bottom = new Point(
|
||||
0,
|
||||
tweak _ measurements.head / 12
|
||||
)
|
||||
|
||||
|
||||
points.rightCp1 = points.right.shift(
|
||||
90,
|
||||
90,
|
||||
points.bottom.dy(points.right) / 2
|
||||
)
|
||||
points.bottomCp2 = points.bottom.shift(
|
||||
0,
|
||||
0,
|
||||
points.bottom.dx(points.right) / 2
|
||||
)
|
||||
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
// highlight-start
|
||||
|
@ -64,11 +66,13 @@ function draftBib({
|
|||
delta = paths.quarterNeck.length() - target
|
||||
if (delta > 0) tweak = tweak * 0.99
|
||||
else tweak = tweak * 1.02
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
return part
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
|
||||
````
|
||||
</Example>
|
||||
|
||||
We're saying: _hide this path_. In other words, don't show it.
|
||||
|
@ -105,28 +109,28 @@ function draftBib({
|
|||
let delta
|
||||
do {
|
||||
points.right = new Point(
|
||||
tweak * measurements.head / 10,
|
||||
tweak * measurements.head / 10,
|
||||
0
|
||||
)
|
||||
points.bottom = new Point(
|
||||
0,
|
||||
0,
|
||||
tweak * measurements.head / 12
|
||||
)
|
||||
|
||||
points.rightCp1 = points.right.shift(
|
||||
90,
|
||||
90,
|
||||
points.bottom.dy(points.right) / 2
|
||||
)
|
||||
points.bottomCp2 = points.bottom.shift(
|
||||
0,
|
||||
0,
|
||||
points.bottom.dx(points.right) / 2
|
||||
)
|
||||
|
||||
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
.hide()
|
||||
|
@ -160,11 +164,12 @@ function draftBib({
|
|||
// highlight-end
|
||||
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 too, like `close()` and `addClass()`.
|
||||
here. There's a few new Path methods too, like `close()` and `addClass()`.
|
||||
|
||||
Perhaps you can figure out what they do? If not, both [the Point
|
||||
documentation](/reference/api/point/) and [the Path
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Conclusion (of part 2)
|
||||
order: 99
|
||||
sidebar_position: 99
|
||||
---
|
||||
|
||||
You made it to the end of part 2, in which we got to do some real parametric design.
|
||||
|
@ -14,7 +14,7 @@ way.
|
|||
You've also learned how to draw paths, which are the lines and curves that make up our pattern.
|
||||
And we've used macros which can help us with repetitive tasks.
|
||||
|
||||
What we've gotten so far is a perfectly suitable sewing pattern. You can print this,
|
||||
What we've gotten so far is a perfectly suitable sewing pattern. You can print this,
|
||||
and make a nice bib out of it.
|
||||
|
||||
But when we stick to these basics, FreeSewing doesn't really get a chance to shine.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Constructing the neck opening
|
||||
order: 60
|
||||
sidebar_position: 60
|
||||
---
|
||||
|
||||
Our goal is to construct an oval neck opening that has a circumference
|
||||
|
@ -51,39 +51,41 @@ function draftBib({
|
|||
}) {
|
||||
|
||||
// highlight-start
|
||||
/*
|
||||
* Construct the quarter neck opening
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Construct the quarter neck opening
|
||||
\*/
|
||||
points.right = new Point(
|
||||
measurements.head / 10,
|
||||
0
|
||||
measurements.head / 10,
|
||||
0
|
||||
)
|
||||
points.bottom = new Point(
|
||||
0,
|
||||
measurements.head / 12
|
||||
0,
|
||||
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
|
||||
)
|
||||
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
|
||||
)
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
// highlight-end
|
||||
|
||||
return part
|
||||
return part
|
||||
}
|
||||
```
|
||||
|
||||
````
|
||||
</Example>
|
||||
|
||||
We've added some points to our part, and drawn our first path.
|
||||
|
@ -93,10 +95,10 @@ Let's look at each line in detail.
|
|||
|
||||
```js
|
||||
points.right = new Point(
|
||||
measurements.head / 10,
|
||||
measurements.head / 10,
|
||||
0
|
||||
)
|
||||
```
|
||||
````
|
||||
|
||||
- We're adding a point named `right` to the `points` object which holds our
|
||||
part's points
|
||||
|
@ -108,10 +110,7 @@ points.right = new Point(
|
|||
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
|
||||
)
|
||||
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_
|
||||
|
@ -130,7 +129,9 @@ 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/).
|
||||
|
@ -144,11 +145,7 @@ introduced on the next line: Paths.
|
|||
```js
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
.curve(points.rightCp1, points.bottomCp2, points.bottom)
|
||||
```
|
||||
|
||||
- We're adding a path named `quarterNeck` to the `paths` object which holds our
|
||||
|
@ -166,7 +163,7 @@ From there, we drew a cubic Bézier curve to our `bottom` point by using
|
|||
|
||||
:::tip
|
||||
|
||||
Many of the methods in the FreeSewing API are *chainable* allowing you
|
||||
Many of the methods in the FreeSewing API are _chainable_ allowing you
|
||||
to string them together like in this example.
|
||||
:::
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Creating the closure
|
||||
order: 91
|
||||
sidebar_position: 91
|
||||
---
|
||||
|
||||
Things are starting to look good, but we can't fit the bib over the baby's head like this.
|
||||
|
@ -60,28 +60,27 @@ function draftBib({
|
|||
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
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
.hide()
|
||||
|
||||
delta = paths.quarterNeck.length() - target
|
||||
if (delta > 0) tweak = tweak * 0.99
|
||||
else tweak = tweak * 1.02
|
||||
delta = paths.quarterNeck.length() - target
|
||||
if (delta > 0) tweak = tweak _ 0.99
|
||||
else tweak = tweak _ 1.02
|
||||
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: A part's draft method
|
||||
order: 50
|
||||
sidebar_position: 50
|
||||
---
|
||||
|
||||
Time to turn our attention to the draft method of our part.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Drawing the bib outline
|
||||
order: 88
|
||||
sidebar_position: 88
|
||||
---
|
||||
|
||||
With our neck opening in place, let us draw the basic outline of our bib.
|
||||
|
@ -17,46 +17,47 @@ function draftBib({
|
|||
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
|
||||
)
|
||||
|
||||
// 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,
|
||||
90,
|
||||
points.bottom.dy(points.right) / 2
|
||||
)
|
||||
points.bottomCp2 = points.bottom.shift(
|
||||
0,
|
||||
0,
|
||||
points.bottom.dx(points.right) / 2
|
||||
)
|
||||
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
.hide()
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
.hide()
|
||||
|
||||
delta = paths.quarterNeck.length() - target
|
||||
if (delta > 0) tweak = tweak * 0.99
|
||||
else tweak = tweak * 1.02
|
||||
} while (Math.abs(delta) > 1)
|
||||
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
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Construct the complete neck opening
|
||||
\*/
|
||||
points.rightCp2 = points.rightCp1.flipY()
|
||||
points.bottomCp1 = points.bottomCp2.flipX()
|
||||
points.left = points.right.flipX()
|
||||
|
@ -66,43 +67,45 @@ function draftBib({
|
|||
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')
|
||||
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')
|
||||
|
||||
// highlight-start
|
||||
/*
|
||||
* 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)
|
||||
- Drawing the bib outline
|
||||
_/
|
||||
const width = measurements.head _ options.widthRatio
|
||||
const length = measurements.head \* options.lengthRatio
|
||||
|
||||
paths.rect = new Path()
|
||||
.move(points.topLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.topRight)
|
||||
.line(points.topLeft)
|
||||
.close()
|
||||
.addClass('fabric')
|
||||
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)
|
||||
|
||||
paths.rect = new Path()
|
||||
.move(points.topLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.topRight)
|
||||
.line(points.topLeft)
|
||||
.close()
|
||||
.addClass('fabric')
|
||||
// highlight-end
|
||||
|
||||
return part
|
||||
return part
|
||||
}
|
||||
```
|
||||
|
||||
````
|
||||
</Example>
|
||||
|
||||
First thing we did was create the `width` and `length` variables to
|
||||
|
@ -111,7 +114,7 @@ save ourselves some typing:
|
|||
```js
|
||||
const width = measurements.head * options.widthRatio
|
||||
const length = measurements.head * options.lengthRatio
|
||||
```
|
||||
````
|
||||
|
||||
Both the length and width of our bib are a factor of the head circumference.
|
||||
This way, our bib size will adapt to the size of the baby, and the user can tweak
|
||||
|
@ -120,10 +123,7 @@ the length and width by playing with the options we added to the pattern.
|
|||
Once we have our variables, we're adding some new points, and a second path called `rect`.
|
||||
|
||||
```js
|
||||
points.topLeft = new Point(
|
||||
width / -2,
|
||||
points.top.y - (width / 2 - points.right.x)
|
||||
)
|
||||
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)
|
||||
|
@ -142,4 +142,3 @@ We're calculating the `topLeft` point so that the top edge of our bib
|
|||
and the sides are equidistant from the neck opening.
|
||||
|
||||
We didn't have to do that. But it looks nicely balanced this way.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Drawing the straps
|
||||
order: 93
|
||||
sidebar_position: 93
|
||||
---
|
||||
|
||||
All we have to do now is flip a bunch of points on the other side,
|
||||
|
@ -28,36 +28,38 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
/*
|
||||
* Construct the neck opening
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Construct the neck opening
|
||||
_/
|
||||
let tweak = 1
|
||||
let target = (measurements.head * options.neckRatio) /4
|
||||
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.right = new Point(
|
||||
tweak _ measurements.head / 10,
|
||||
0
|
||||
)
|
||||
points.bottom = new Point(
|
||||
0,
|
||||
tweak _ measurements.head / 12
|
||||
)
|
||||
|
||||
|
||||
points.rightCp1 = points.right.shift(
|
||||
90,
|
||||
90,
|
||||
points.bottom.dy(points.right) / 2
|
||||
)
|
||||
points.bottomCp2 = points.bottom.shift(
|
||||
0,
|
||||
0,
|
||||
points.bottom.dx(points.right) / 2
|
||||
)
|
||||
|
||||
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
.hide()
|
||||
|
@ -65,11 +67,13 @@ function draftBib({
|
|||
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
|
||||
*/
|
||||
} 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()
|
||||
|
@ -79,233 +83,239 @@ function draftBib({
|
|||
points.topCp1 = points.bottomCp2.flipY()
|
||||
points.topCp2 = points.bottomCp1.flipY()
|
||||
|
||||
// strikeout-start
|
||||
/* Remove this path
|
||||
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')
|
||||
*/
|
||||
// strikeout-end
|
||||
// strikeout-start
|
||||
/_ Remove this path
|
||||
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')
|
||||
_/
|
||||
// strikeout-end
|
||||
|
||||
// Drawing the bib outline
|
||||
const width = measurements.head * options.widthRatio
|
||||
const length = measurements.head * options.lengthRatio
|
||||
// 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)
|
||||
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
|
||||
*/
|
||||
/\*
|
||||
|
||||
- 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()
|
||||
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)
|
||||
// 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)
|
||||
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)
|
||||
|
||||
/*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Macros will return the auto-generated IDs
|
||||
_/
|
||||
const ids1 = {
|
||||
tipRightTop: macro("round", {
|
||||
id: "tipRightTop",
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
// strikeout-start
|
||||
/* Remove this to have the macro
|
||||
* only create the points we need
|
||||
* and not draw a path
|
||||
hide: false
|
||||
*/
|
||||
// strikeout-end
|
||||
}),
|
||||
tipRightBottom: macro("round", {
|
||||
id: "tipRightBottom",
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
// strikeout-start
|
||||
/* Remove this to have the macro
|
||||
* only create the points we need
|
||||
* and not draw a path
|
||||
hide: false
|
||||
*/
|
||||
// strikeout-end
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the list of points we need to rotate
|
||||
* to move our strap out of the way
|
||||
*/
|
||||
|
||||
const rotateThese = [
|
||||
"edgeTopLeftCp",
|
||||
"edgeTop",
|
||||
"tipRight",
|
||||
"tipRightTop",
|
||||
"tipRightTopStart",
|
||||
"tipRightTopCp1",
|
||||
"tipRightTopCp2",
|
||||
"tipRightTopEnd",
|
||||
"tipRightBottomStart",
|
||||
"tipRightBottomCp1",
|
||||
"tipRightBottomCp2",
|
||||
"tipRightBottomEnd",
|
||||
"tipRightBottom",
|
||||
"top",
|
||||
"topCp2"
|
||||
]
|
||||
/*
|
||||
* We're rotating all the points in
|
||||
* the `rotateThese` array around
|
||||
* the `edgeLeft` point.
|
||||
*
|
||||
* We're using increments of 1 degree
|
||||
* until the `tipRightBottomStart` point
|
||||
* is 1 mm beyond the center of our bib.
|
||||
*/
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
|
||||
tipRightTop: macro("round", {
|
||||
id: "tipRightTop",
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
// strikeout-start
|
||||
/* Remove this repetition
|
||||
macro("round", {
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
prefix: "tipRightTop",
|
||||
hide: false,
|
||||
class: 'contrast dotted',
|
||||
})
|
||||
macro("round", {
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
prefix: "tipRightBottom",
|
||||
hide: false,
|
||||
class: 'contrast dotted',
|
||||
})
|
||||
|
||||
paths.rect = new Path()
|
||||
.move(points.edgeTop)
|
||||
.curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.edgeRight)
|
||||
.curve(points.edgeRightCp, points.edgeTopRightCp, points.edgeTop)
|
||||
.close()
|
||||
*/
|
||||
/_ Remove this to have the macro
|
||||
_ only create the points we need
|
||||
_ and not draw a path
|
||||
hide: false
|
||||
_/
|
||||
// strikeout-end
|
||||
}),
|
||||
tipRightBottom: macro("round", {
|
||||
id: "tipRightBottom",
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
// strikeout-start
|
||||
/_ Remove this to have the macro
|
||||
_ only create the points we need
|
||||
_ and not draw a path
|
||||
hide: false
|
||||
\*/
|
||||
// strikeout-end
|
||||
})
|
||||
}
|
||||
|
||||
// highlight-start
|
||||
// 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()
|
||||
/\*
|
||||
|
||||
// Create one path for the bib outline
|
||||
paths.seam = new Path()
|
||||
.move(points.edgeLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.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")
|
||||
// highlight-end
|
||||
- Create points from them with easy names
|
||||
\*/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
return part
|
||||
/\*
|
||||
|
||||
- This is the list of points we need to rotate
|
||||
- to move our strap out of the way
|
||||
\*/
|
||||
|
||||
const rotateThese = [
|
||||
"edgeTopLeftCp",
|
||||
"edgeTop",
|
||||
"tipRight",
|
||||
"tipRightTop",
|
||||
"tipRightTopStart",
|
||||
"tipRightTopCp1",
|
||||
"tipRightTopCp2",
|
||||
"tipRightTopEnd",
|
||||
"tipRightBottomStart",
|
||||
"tipRightBottomCp1",
|
||||
"tipRightBottomCp2",
|
||||
"tipRightBottomEnd",
|
||||
"tipRightBottom",
|
||||
"top",
|
||||
"topCp2"
|
||||
]
|
||||
/\*
|
||||
_ We're rotating all the points in
|
||||
_ the `rotateThese` array around
|
||||
_ the `edgeLeft` point.
|
||||
_
|
||||
_ We're using increments of 1 degree
|
||||
_ until the `tipRightBottomStart` point
|
||||
_ is 1 mm beyond the center of our bib.
|
||||
_/
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
|
||||
// strikeout-start
|
||||
/\* Remove this repetition
|
||||
macro("round", {
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
prefix: "tipRightTop",
|
||||
hide: false,
|
||||
class: 'contrast dotted',
|
||||
})
|
||||
macro("round", {
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
prefix: "tipRightBottom",
|
||||
hide: false,
|
||||
class: 'contrast dotted',
|
||||
})
|
||||
|
||||
paths.rect = new Path()
|
||||
.move(points.edgeTop)
|
||||
.curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.edgeRight)
|
||||
.curve(points.edgeRightCp, points.edgeTopRightCp, points.edgeTop)
|
||||
.close()
|
||||
\*/
|
||||
// strikeout-end
|
||||
|
||||
// highlight-start
|
||||
// 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()
|
||||
|
||||
// Create one path for the bib outline
|
||||
paths.seam = new Path()
|
||||
.move(points.edgeLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.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")
|
||||
// highlight-end
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
```
|
||||
</Example>
|
||||
```
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
title: Fitting the neck opening
|
||||
order: 70
|
||||
sidebar_position: 70
|
||||
---
|
||||
|
||||
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
|
||||
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">
|
||||
|
@ -19,54 +19,56 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
/*
|
||||
* Construct the quarter neck opening
|
||||
*/
|
||||
// highlight-start
|
||||
/\*
|
||||
|
||||
- Construct the quarter neck opening
|
||||
_/
|
||||
// highlight-start
|
||||
let tweak = 1
|
||||
let target = (measurements.head * options.neckRatio) /4
|
||||
let target = (measurements.head _ options.neckRatio) /4
|
||||
let delta
|
||||
do {
|
||||
// highlight-end
|
||||
points.right = new Point(
|
||||
// highlight-start
|
||||
tweak * measurements.head / 10,
|
||||
// highlight-end
|
||||
0
|
||||
)
|
||||
points.bottom = new Point(
|
||||
0,
|
||||
// highlight-start
|
||||
tweak * measurements.head / 12
|
||||
// highlight-end
|
||||
)
|
||||
// highlight-end
|
||||
points.right = new Point(
|
||||
// highlight-start
|
||||
tweak _ measurements.head / 10,
|
||||
// highlight-end
|
||||
0
|
||||
)
|
||||
points.bottom = new Point(
|
||||
0,
|
||||
// highlight-start
|
||||
tweak _ measurements.head / 12
|
||||
// highlight-end
|
||||
)
|
||||
|
||||
|
||||
points.rightCp1 = points.right.shift(
|
||||
90,
|
||||
90,
|
||||
points.bottom.dy(points.right) / 2
|
||||
)
|
||||
points.bottomCp2 = points.bottom.shift(
|
||||
0,
|
||||
0,
|
||||
points.bottom.dx(points.right) / 2
|
||||
)
|
||||
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
|
||||
|
||||
// highlight-start
|
||||
delta = paths.quarterNeck.length() - target
|
||||
if (delta > 0) tweak = tweak * 0.99
|
||||
else tweak = tweak * 1.02
|
||||
} while (Math.abs(delta) > 1)
|
||||
delta = paths.quarterNeck.length() - target
|
||||
if (delta > 0) tweak = tweak _ 0.99
|
||||
else tweak = tweak _ 1.02
|
||||
} while (Math.abs(delta) > 1)
|
||||
// highlight-end
|
||||
return part
|
||||
return part
|
||||
}
|
||||
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
@ -94,3 +96,4 @@ are within 1 mm of our target value.
|
|||
|
||||
Now that we're happy with the length of our quarter neck opening, let's
|
||||
complete the entire neck opening.
|
||||
```
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: Creating a new design
|
||||
order: 10
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
The development environment has already setup various designs for us.
|
||||
Since I am using the **From scratch** template, the files I want to edit live
|
||||
Since I am using the **From scratch** template, the files I want to edit live
|
||||
in `design/from-scratch`.
|
||||
|
||||
The design's main file is `design/from-scratch/src/index.mjs`, and our bib part
|
||||
will live in `design/from-scratch/src/bib.mjs`.
|
||||
will live in `design/from-scratch/src/bib.mjs`.
|
||||
|
||||
This `bib.mjs` file is where will be doing most of the work here in part 2 of this
|
||||
tutorial. But let's start with the `index.mjs` file as an appetizer, because this
|
||||
|
@ -37,7 +37,7 @@ Not too intimidating, is it?
|
|||
|
||||
## Imports
|
||||
|
||||
At the top of the file, we have a bunch of *imports*:
|
||||
At the top of the file, we have a bunch of _imports_:
|
||||
|
||||
```src/index.mjs
|
||||
import { Design } from '@freesewing/core'
|
||||
|
@ -48,13 +48,13 @@ import { bib } from './bib.mjs'
|
|||
An `import` is how JavaScript loads code from a different file. \
|
||||
It essentially says: _import **something** from **somewhere**_:
|
||||
|
||||
| Something | Somewhere | Description |
|
||||
| ---------:|:--------- |:----------- |
|
||||
| `Design` | `@freesewing/core` | Loads the `Design` constructor from FreeSewing's core library |
|
||||
| `i18n` | `../i18n/index.mjs` | Loads `i18n` from the `index.mjs` file in the `i18n` one level higher (these are the translations) |
|
||||
| `bib` | `./bib.mjs` | Loads `bib` from the `bib.mjs` file in the same folder (this is our part) |
|
||||
| Something | Somewhere | Description |
|
||||
| --------: | :------------------ | :------------------------------------------------------------------------------------------------- |
|
||||
| `Design` | `@freesewing/core` | Loads the `Design` constructor from FreeSewing's core library |
|
||||
| `i18n` | `../i18n/index.mjs` | Loads `i18n` from the `index.mjs` file in the `i18n` one level higher (these are the translations) |
|
||||
| `bib` | `./bib.mjs` | Loads `bib` from the `bib.mjs` file in the same folder (this is our part) |
|
||||
|
||||
As you can see, the *somewhere* can be different things. A local file like in
|
||||
As you can see, the _somewhere_ can be different things. A local file like in
|
||||
lines 2 and 3, or a package published on
|
||||
[NPM](https://www.npmjs.com/package/@freesewing/core), in line 1.
|
||||
|
||||
|
@ -82,7 +82,7 @@ If you are not familiar with this syntax, you'll get the hang of it soon enough.
|
|||
|
||||
## Design constructor
|
||||
|
||||
Finally, the most interesting part of this file is the middle part where we are
|
||||
Finally, the most interesting part of this file is the middle part where we are
|
||||
creating a new design:
|
||||
|
||||
```src/index.mjs
|
||||
|
@ -95,7 +95,7 @@ const FromScratch = new Design({
|
|||
})
|
||||
```
|
||||
|
||||
The `Design` that we imported on line 1 is a so-called **constructor**.
|
||||
The `Design` that we imported on line 1 is a so-called **constructor**.
|
||||
A constructor is a function that can create things out of nothing. Or,
|
||||
to be more accurate, that you can use with the `new` keyword.
|
||||
|
||||
|
@ -105,8 +105,8 @@ It's a convention that constructor names start with an **C**apital letter.
|
|||
:::
|
||||
|
||||
We are passing some info to this `Design` function, but the `data` we are
|
||||
passing is optional. If we strip that away for a moment, and don't bother
|
||||
assigning the result to a variable, we reveal the essence of what it takes to
|
||||
passing is optional. If we strip that away for a moment, and don't bother
|
||||
assigning the result to a variable, we reveal the essence of what it takes to
|
||||
create a new FreeSewing design:
|
||||
|
||||
```src/index.mjs
|
||||
|
@ -115,8 +115,8 @@ new Design({
|
|||
})
|
||||
```
|
||||
|
||||
In several places in this documentation, I will mention that *a design is not
|
||||
much more than a thin wrapper around parts*. But I feel nothing drives
|
||||
In several places in this documentation, I will mention that _a design is not
|
||||
much more than a thin wrapper around parts_. But I feel nothing drives
|
||||
that point home like seeing it in code like this.
|
||||
|
||||
To create a new design, we call the `Design` constructor and give it a list
|
||||
|
@ -124,9 +124,8 @@ To create a new design, we call the `Design` constructor and give it a list
|
|||
|
||||
:::note RELATED
|
||||
|
||||
Refer to [the design reference documentation](/reference/api/design) for
|
||||
Refer to [the design reference documentation](/reference/api/design) for
|
||||
all details about what you can pass to the Design constructor.
|
||||
:::
|
||||
|
||||
That's it. So let's look at where the real action is next: Our first part.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Creating a part
|
||||
order: 20
|
||||
sidebar_position: 20
|
||||
---
|
||||
|
||||
Much like garments themselves, patterns are made up of _parts_.
|
||||
|
@ -9,14 +9,14 @@ so on. The pattern you create today is very simple, and only has one part: the b
|
|||
|
||||
:::tip
|
||||
|
||||
It's a good idea to keep each part in its own file. You don't *have to* do
|
||||
this, but it's a good habit to get into.
|
||||
It's a good idea to keep each part in its own file. You don't _have to_ do
|
||||
this, but it's a good habit to get into.
|
||||
|
||||
:::
|
||||
|
||||
## bib.mjs
|
||||
|
||||
I am going to use the **From scratch** template. So the files I want to edit live
|
||||
I am going to use the **From scratch** template. So the files I want to edit live
|
||||
in `design/from-scratch`.
|
||||
|
||||
Our part lives in `design/from-scratch/src/bib.mjs`, and it currently looks like this:
|
||||
|
@ -41,8 +41,8 @@ The only mandatory keys on a part object are `name` and `draft`.
|
|||
|
||||
:::note RELATED
|
||||
|
||||
Refer to [the part reference documentation](/reference/api/part) for
|
||||
all details about configuring the part object
|
||||
Refer to [the part reference documentation](/reference/api/part) for
|
||||
all details about configuring the part object
|
||||
:::
|
||||
|
||||
:::note
|
||||
|
@ -52,7 +52,6 @@ Each parts stands on its own, and parts from various designs can be combined
|
|||
to create other designs.
|
||||
:::
|
||||
|
||||
|
||||
### The part name
|
||||
|
||||
```src/bib.mjs
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Rounding the corners
|
||||
order: 94
|
||||
sidebar_position: 94
|
||||
---
|
||||
|
||||
We already know how to round corners, we'll have the `round` macro take care of that for us.
|
||||
|
@ -22,36 +22,38 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
/*
|
||||
* Construct the quarter neck opening
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Construct the quarter neck opening
|
||||
_/
|
||||
let tweak = 1
|
||||
let target = (measurements.head * options.neckRatio) /4
|
||||
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.right = new Point(
|
||||
tweak _ measurements.head / 10,
|
||||
0
|
||||
)
|
||||
points.bottom = new Point(
|
||||
0,
|
||||
tweak _ measurements.head / 12
|
||||
)
|
||||
|
||||
|
||||
points.rightCp1 = points.right.shift(
|
||||
90,
|
||||
90,
|
||||
points.bottom.dy(points.right) / 2
|
||||
)
|
||||
points.bottomCp2 = points.bottom.shift(
|
||||
0,
|
||||
0,
|
||||
points.bottom.dx(points.right) / 2
|
||||
)
|
||||
|
||||
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
.hide()
|
||||
|
@ -59,11 +61,13 @@ function draftBib({
|
|||
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
|
||||
*/
|
||||
} 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()
|
||||
|
@ -73,216 +77,225 @@ function draftBib({
|
|||
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
|
||||
// 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)
|
||||
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
|
||||
*/
|
||||
/\*
|
||||
|
||||
- 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()
|
||||
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)
|
||||
// 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)
|
||||
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)
|
||||
|
||||
/*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Macros will return the auto-generated IDs
|
||||
\*/
|
||||
const ids1 = {
|
||||
tipRightTop: macro("round", {
|
||||
id: "tipRightTop",
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
}),
|
||||
tipRightBottom: macro("round", {
|
||||
id: "tipRightBottom",
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
})
|
||||
tipRightTop: macro("round", {
|
||||
id: "tipRightTop",
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
}),
|
||||
tipRightBottom: macro("round", {
|
||||
id: "tipRightBottom",
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Create points from them with easy names
|
||||
\*/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is the list of points we need to rotate
|
||||
* to move our strap out of the way
|
||||
*/
|
||||
|
||||
- This is the list of points we need to rotate
|
||||
- to move our strap out of the way
|
||||
_/
|
||||
const rotateThese = [
|
||||
"edgeTopLeftCp",
|
||||
"edgeTop",
|
||||
"tipRight",
|
||||
"tipRightTop",
|
||||
"tipRightTopStart",
|
||||
"tipRightTopCp1",
|
||||
"tipRightTopCp2",
|
||||
"tipRightTopEnd",
|
||||
"tipRightBottomStart",
|
||||
"tipRightBottomCp1",
|
||||
"tipRightBottomCp2",
|
||||
"tipRightBottomEnd",
|
||||
"tipRightBottom",
|
||||
"top",
|
||||
"topCp2"
|
||||
"edgeTopLeftCp",
|
||||
"edgeTop",
|
||||
"tipRight",
|
||||
"tipRightTop",
|
||||
"tipRightTopStart",
|
||||
"tipRightTopCp1",
|
||||
"tipRightTopCp2",
|
||||
"tipRightTopEnd",
|
||||
"tipRightBottomStart",
|
||||
"tipRightBottomCp1",
|
||||
"tipRightBottomCp2",
|
||||
"tipRightBottomEnd",
|
||||
"tipRightBottom",
|
||||
"top",
|
||||
"topCp2"
|
||||
]
|
||||
/*
|
||||
* We're rotating all the points in
|
||||
* the `rotateThese` array around
|
||||
* the `edgeLeft` point.
|
||||
*
|
||||
* We're using increments of 1 degree
|
||||
* until the `tipRightBottomStart` point
|
||||
* is 1 mm beyond the center of our bib.
|
||||
*/
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
/_
|
||||
- We're rotating all the points in
|
||||
- the `rotateThese` array around
|
||||
- the `edgeLeft` point.
|
||||
-
|
||||
- We're using increments of 1 degree
|
||||
- until the `tipRightBottomStart` point
|
||||
- is 1 mm beyond the center of our bib.
|
||||
\*/
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
||||
// highlight-start
|
||||
/*
|
||||
* Round the bottom corners
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
const ids2 = {
|
||||
bottomLeft: macro("round", {
|
||||
id: "bottomLeft",
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomRight: macro("round", {
|
||||
id: "bottomRight",
|
||||
from: points.bottomLeft,
|
||||
to: points.topRight,
|
||||
via: points.bottomRight,
|
||||
radius: points.bottomRight.x / 4,
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
for (const side in ids2) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
||||
// highlight-start
|
||||
/\*
|
||||
|
||||
- Round the bottom corners
|
||||
- Macros will return the auto-generated IDs
|
||||
\*/
|
||||
const ids2 = {
|
||||
bottomLeft: macro("round", {
|
||||
id: "bottomLeft",
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomRight: macro("round", {
|
||||
id: "bottomRight",
|
||||
from: points.bottomLeft,
|
||||
to: points.topRight,
|
||||
via: points.bottomRight,
|
||||
radius: points.bottomRight.x / 4,
|
||||
})
|
||||
}
|
||||
|
||||
/\*
|
||||
|
||||
- Create points from them with easy names
|
||||
\*/
|
||||
for (const side in ids2) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
// highlight-end
|
||||
|
||||
// Create one path for the bib outline
|
||||
paths.seam = new Path()
|
||||
.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)
|
||||
.curve(points.bottomLeftCp1, points.bottomLeftCp2, points.bottomLeftEnd)
|
||||
.line(points.bottomRightStart)
|
||||
.curve(points.bottomRightCp1, points.bottomRightCp2, points.bottomRightEnd)
|
||||
// highlight-end
|
||||
.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")
|
||||
// Create one path for the bib outline
|
||||
paths.seam = new Path()
|
||||
.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)
|
||||
.curve(points.bottomLeftCp1, points.bottomLeftCp2, points.bottomLeftEnd)
|
||||
.line(points.bottomRightStart)
|
||||
.curve(points.bottomRightCp1, points.bottomRightCp2, points.bottomRightEnd)
|
||||
// highlight-end
|
||||
.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")
|
||||
|
||||
return part
|
||||
return part
|
||||
}
|
||||
|
||||
```
|
||||
</Example>
|
||||
```
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Shaping the straps
|
||||
order: 90
|
||||
sidebar_position: 90
|
||||
---
|
||||
|
||||
Our straps should follow the neck opening, which isn't that hard to do.
|
||||
|
@ -15,7 +15,6 @@ As always, [the API docs](/reference/api/point/) have all the details.
|
|||
|
||||
:::
|
||||
|
||||
|
||||
<Example tutorial caption="All of a sudden, things are starting to look like a bib">
|
||||
```design/src/bib.mjs
|
||||
function draftBib({
|
||||
|
@ -28,36 +27,38 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
/*
|
||||
* Construct the quarter neck opening
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Construct the quarter neck opening
|
||||
_/
|
||||
let tweak = 1
|
||||
let target = (measurements.head * options.neckRatio) /4
|
||||
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.right = new Point(
|
||||
tweak _ measurements.head / 10,
|
||||
0
|
||||
)
|
||||
points.bottom = new Point(
|
||||
0,
|
||||
tweak _ measurements.head / 12
|
||||
)
|
||||
|
||||
|
||||
points.rightCp1 = points.right.shift(
|
||||
90,
|
||||
90,
|
||||
points.bottom.dy(points.right) / 2
|
||||
)
|
||||
points.bottomCp2 = points.bottom.shift(
|
||||
0,
|
||||
0,
|
||||
points.bottom.dx(points.right) / 2
|
||||
)
|
||||
|
||||
paths.quarterNeck = new Path()
|
||||
.move(points.right)
|
||||
.curve(
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.rightCp1,
|
||||
points.bottomCp2,
|
||||
points.bottom
|
||||
)
|
||||
.hide()
|
||||
|
@ -65,11 +66,13 @@ function draftBib({
|
|||
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
|
||||
*/
|
||||
} 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()
|
||||
|
@ -79,75 +82,81 @@ function draftBib({
|
|||
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')
|
||||
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)
|
||||
- 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)
|
||||
|
||||
// strikeout-start
|
||||
/*
|
||||
* Remove this path
|
||||
/\*
|
||||
|
||||
- Remove this path
|
||||
|
||||
paths.rect = new Path()
|
||||
.move(points.topLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.topRight)
|
||||
.line(points.topLeft)
|
||||
.close()
|
||||
.addClass('fabric')
|
||||
*/
|
||||
// strikeout-end
|
||||
.move(points.topLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.topRight)
|
||||
.line(points.topLeft)
|
||||
.close()
|
||||
.addClass('fabric')
|
||||
\*/
|
||||
// strikeout-end
|
||||
|
||||
// highlight-start
|
||||
/*
|
||||
* Shape the straps
|
||||
*/
|
||||
/\*
|
||||
|
||||
- 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()
|
||||
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()
|
||||
|
||||
/*
|
||||
* Now, adapt our `rect` path so it's no longer a rectangle:
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Now, adapt our `rect` path so it's no longer a rectangle:
|
||||
\*/
|
||||
paths.rect = new Path()
|
||||
.move(points.edgeTop)
|
||||
.curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.edgeRight)
|
||||
.curve(points.edgeRightCp, points.edgeTopRightCp, points.edgeTop)
|
||||
.close()
|
||||
.move(points.edgeTop)
|
||||
.curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.edgeRight)
|
||||
.curve(points.edgeRightCp, points.edgeTopRightCp, points.edgeTop)
|
||||
.close()
|
||||
|
||||
// highlight-end
|
||||
|
||||
return part
|
||||
return part
|
||||
}
|
||||
|
||||
```
|
||||
</Example>
|
||||
```
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
---
|
||||
title: Adding annotations
|
||||
order: 20
|
||||
sidebar_position: 20
|
||||
---
|
||||
|
||||
Our pattern is still a little bit *bare*. It would be nice to add some *annotations* to it.
|
||||
Our pattern is still a little bit _bare_. It would be nice to add some _annotations_ to it.
|
||||
|
||||
When I say *annotations* it's an umbrella term for things like text or other
|
||||
When I say _annotations_ it's an umbrella term for things like text or other
|
||||
bits of information that help the user understand the pattern.
|
||||
|
||||
## Adding snippets
|
||||
|
@ -42,15 +42,17 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
/*
|
||||
* Construct the neck opening
|
||||
*/
|
||||
const target = (measurements.head * options.neckRatio) / 4
|
||||
/\*
|
||||
|
||||
- Construct the neck opening
|
||||
_/
|
||||
const target = (measurements.head _ options.neckRatio) / 4
|
||||
let tweak = 1
|
||||
let delta
|
||||
do {
|
||||
points.right = new Point((tweak * measurements.head) / 10, 0)
|
||||
points.bottom = new Point(0, (tweak * measurements.head) / 12)
|
||||
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)
|
||||
|
@ -62,108 +64,116 @@ function draftBib({
|
|||
delta = paths.neck.length() - target
|
||||
if (delta > 0) tweak = tweak * 0.99
|
||||
else tweak = tweak * 1.02
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
points.rightCp2 = points.rightCp1.flipY()
|
||||
points.bottomCp1 = points.bottomCp2.flipX()
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
points.left = points.right.flipX()
|
||||
points.leftCp1 = points.rightCp2.flipX()
|
||||
points.leftCp2 = points.rightCp1.flipX()
|
||||
points.rightCp2 = points.rightCp1.flipY()
|
||||
points.bottomCp1 = points.bottomCp2.flipX()
|
||||
|
||||
points.top = points.bottom.flipY()
|
||||
points.topCp1 = points.bottomCp2.flipY()
|
||||
points.topCp2 = points.bottomCp1.flipY()
|
||||
points.left = points.right.flipX()
|
||||
points.leftCp1 = points.rightCp2.flipX()
|
||||
points.leftCp2 = points.rightCp1.flipX()
|
||||
|
||||
/*
|
||||
* Construct the outline
|
||||
*/
|
||||
let width = measurements.head * options.widthRatio
|
||||
let length = measurements.head * options.lengthRatio
|
||||
points.top = points.bottom.flipY()
|
||||
points.topCp1 = points.bottomCp2.flipY()
|
||||
points.topCp2 = points.bottomCp1.flipY()
|
||||
|
||||
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)
|
||||
/\*
|
||||
|
||||
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)
|
||||
- Construct the outline
|
||||
_/
|
||||
let width = measurements.head _ options.widthRatio
|
||||
let length = measurements.head \* options.lengthRatio
|
||||
|
||||
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()
|
||||
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)
|
||||
|
||||
/*
|
||||
* Round the end of 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 end of the straps
|
||||
\*/
|
||||
let 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)
|
||||
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)
|
||||
|
||||
/*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Macros will return the auto-generated IDs
|
||||
\*/
|
||||
const ids1 = {
|
||||
tipRightTop: macro('round', {
|
||||
id: 'tipRightTop',
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
}),
|
||||
tipRightBottom: macro('round', {
|
||||
id: 'tipRightBottom',
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
}),
|
||||
tipRightTop: macro('round', {
|
||||
id: 'tipRightTop',
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
}),
|
||||
tipRightBottom: macro('round', {
|
||||
id: 'tipRightBottom',
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
}),
|
||||
}
|
||||
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Create points from them with easy names
|
||||
\*/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate straps so they don't overlap
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Rotate straps so they don't overlap
|
||||
\*/
|
||||
let rotateThese = [
|
||||
'edgeTopLeftCp',
|
||||
'edgeTop',
|
||||
'tipRight',
|
||||
'tipRightTop',
|
||||
'tipRightTopStart',
|
||||
'tipRightTopCp1',
|
||||
'tipRightTopCp2',
|
||||
'tipRightTopEnd',
|
||||
'tipRightBottomStart',
|
||||
'tipRightBottomCp1',
|
||||
'tipRightBottomCp2',
|
||||
'tipRightBottomEnd',
|
||||
'tipRightBottom',
|
||||
'top',
|
||||
'topCp2',
|
||||
'edgeTopLeftCp',
|
||||
'edgeTop',
|
||||
'tipRight',
|
||||
'tipRightTop',
|
||||
'tipRightTopStart',
|
||||
'tipRightTopCp1',
|
||||
'tipRightTopCp2',
|
||||
'tipRightTopEnd',
|
||||
'tipRightBottomStart',
|
||||
'tipRightBottomCp1',
|
||||
'tipRightBottomCp2',
|
||||
'tipRightBottomEnd',
|
||||
'tipRightBottom',
|
||||
'top',
|
||||
'topCp2',
|
||||
]
|
||||
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (let p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (let p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
|
||||
/*
|
||||
* Add points to anchor snaps on
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Add points to anchor snaps on
|
||||
\*/
|
||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||
|
||||
/*
|
||||
* Mirror points to the other side
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Mirror points to the other side
|
||||
\*/
|
||||
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
|
||||
points.topCp1 = points.topCp2.flipX()
|
||||
points.tipLeftTopStart = points.tipRightTopStart.flipX()
|
||||
|
@ -176,83 +186,88 @@ function draftBib({
|
|||
points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
|
||||
points.snapRight = points.snapLeft.flipX()
|
||||
|
||||
/*
|
||||
* Round the bottom of the bib
|
||||
* Radius is fixed, but you could use an option for it)
|
||||
*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Round the bottom of the bib
|
||||
- Radius is fixed, but you could use an option for it)
|
||||
-
|
||||
- Macros will return the auto-generated IDs
|
||||
_/
|
||||
const ids2 = {
|
||||
bottomLeft: macro('round', {
|
||||
id: 'bottomLeft',
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomRight: macro('round', {
|
||||
id: 'bottomRight',
|
||||
from: points.bottomLeft,
|
||||
to: points.topRight,
|
||||
via: points.bottomRight,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomLeft: macro('round', {
|
||||
id: 'bottomLeft',
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomRight: macro('round', {
|
||||
id: 'bottomRight',
|
||||
from: points.bottomLeft,
|
||||
to: points.topRight,
|
||||
via: points.bottomRight,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
}
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
/_
|
||||
- Create points from them with easy names
|
||||
\*/
|
||||
for (const side in ids2) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
|
||||
}
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct the path
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Construct the path
|
||||
\*/
|
||||
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()
|
||||
.attr('class', 'fabric')
|
||||
.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()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
// highlight-start
|
||||
/*
|
||||
*
|
||||
* Annotations
|
||||
*
|
||||
*/
|
||||
// highlight-start
|
||||
/\*
|
||||
|
||||
/*
|
||||
* Add the snaps
|
||||
*/
|
||||
-
|
||||
- Annotations
|
||||
- \*/
|
||||
|
||||
/\*
|
||||
|
||||
- Add the snaps
|
||||
\*/
|
||||
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
|
||||
snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
|
||||
|
||||
/*
|
||||
* Add the logo
|
||||
*/
|
||||
/\*
|
||||
|
||||
- Add the logo
|
||||
\*/
|
||||
points.logo = new Point(0, 0)
|
||||
snippets.logo = new Snippet('logo', points.logo)
|
||||
// highlight-end
|
||||
|
||||
return part
|
||||
return part
|
||||
}
|
||||
```
|
||||
|
||||
````
|
||||
</Example>
|
||||
|
||||
## Setting the cutlist, adding a title and scalebox
|
||||
|
@ -522,6 +537,6 @@ function draftBib({
|
|||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
````
|
||||
|
||||
</Example>
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
---
|
||||
title: Dealing with laser cutters
|
||||
order: 25
|
||||
sidebar_position: 25
|
||||
---
|
||||
|
||||
Laser cutters is merely an example of a situation where your user wants not the
|
||||
complete detailed pattern with all annotations, but just the outlines.
|
||||
Essentially what we had at the end of part 2 of this tutorial.
|
||||
|
||||
Since then, we've added a bunch of embellishments, and perhaps the user does
|
||||
Since then, we've added a bunch of embellishments, and perhaps the user does
|
||||
not want those.
|
||||
|
||||
Well, good news: there is a setting for that too. That setting is `complete`,
|
||||
Well, good news: there is a setting for that too. That setting is `complete`,
|
||||
and more annotations will automatically take it into account.
|
||||
|
||||
For example, if you put a logo or title on the pattern, it will check the
|
||||
For example, if you put a logo or title on the pattern, it will check the
|
||||
`complete` setting and if it is `false` it will do nothing.
|
||||
When we say we're going to *complete* our pattern, we mean we're going to add
|
||||
When we say we're going to _complete_ our pattern, we mean we're going to add
|
||||
things like a title and a scalebox and so on.
|
||||
|
||||
So while in most scenarios you don't have to worry about `complete`, you
|
||||
So while in most scenarios you don't have to worry about `complete`, you
|
||||
should keep it in mind when you are adding text or paths to the design
|
||||
that should not be shown on a non-complete pattern.
|
||||
|
||||
|
@ -46,15 +46,15 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
/*
|
||||
* Construct the neck opening
|
||||
*/
|
||||
const target = (measurements.head * options.neckRatio) / 4
|
||||
let tweak = 1
|
||||
let delta
|
||||
do {
|
||||
points.right = new Point((tweak * measurements.head) / 10, 0)
|
||||
points.bottom = new Point(0, (tweak * measurements.head) / 12)
|
||||
/\*
|
||||
_ Construct the neck opening
|
||||
_/
|
||||
const target = (measurements.head _ options.neckRatio) / 4
|
||||
let tweak = 1
|
||||
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)
|
||||
|
@ -66,229 +66,229 @@ function draftBib({
|
|||
delta = paths.neck.length() - target
|
||||
if (delta > 0) tweak = tweak * 0.99
|
||||
else tweak = tweak * 1.02
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
points.rightCp2 = points.rightCp1.flipY()
|
||||
points.bottomCp1 = points.bottomCp2.flipX()
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
points.left = points.right.flipX()
|
||||
points.leftCp1 = points.rightCp2.flipX()
|
||||
points.leftCp2 = points.rightCp1.flipX()
|
||||
points.rightCp2 = points.rightCp1.flipY()
|
||||
points.bottomCp1 = points.bottomCp2.flipX()
|
||||
|
||||
points.top = points.bottom.flipY()
|
||||
points.topCp1 = points.bottomCp2.flipY()
|
||||
points.topCp2 = points.bottomCp1.flipY()
|
||||
points.left = points.right.flipX()
|
||||
points.leftCp1 = points.rightCp2.flipX()
|
||||
points.leftCp2 = points.rightCp1.flipX()
|
||||
|
||||
/*
|
||||
* Construct the outline
|
||||
*/
|
||||
let width = measurements.head * options.widthRatio
|
||||
let length = measurements.head * options.lengthRatio
|
||||
points.top = points.bottom.flipY()
|
||||
points.topCp1 = points.bottomCp2.flipY()
|
||||
points.topCp2 = points.bottomCp1.flipY()
|
||||
|
||||
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)
|
||||
/\*
|
||||
_ Construct the outline
|
||||
_/
|
||||
let width = measurements.head _ options.widthRatio
|
||||
let length = measurements.head _ options.lengthRatio
|
||||
|
||||
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.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)
|
||||
|
||||
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()
|
||||
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)
|
||||
|
||||
/*
|
||||
* Round the end of the straps
|
||||
*/
|
||||
let strap = points.edgeTop.dy(points.top)
|
||||
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()
|
||||
|
||||
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)
|
||||
/\*
|
||||
_ Round the end of the straps
|
||||
_/
|
||||
let strap = points.edgeTop.dy(points.top)
|
||||
|
||||
/*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
const ids1 = {
|
||||
tipRightTop: macro('round', {
|
||||
id: 'tipRightTop',
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
}),
|
||||
tipRightBottom: macro('round', {
|
||||
id: 'tipRightBottom',
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
}),
|
||||
}
|
||||
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)
|
||||
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate straps so they don't overlap
|
||||
*/
|
||||
let rotateThese = [
|
||||
'edgeTopLeftCp',
|
||||
'edgeTop',
|
||||
'tipRight',
|
||||
'tipRightTop',
|
||||
'tipRightTopStart',
|
||||
'tipRightTopCp1',
|
||||
'tipRightTopCp2',
|
||||
'tipRightTopEnd',
|
||||
'tipRightBottomStart',
|
||||
'tipRightBottomCp1',
|
||||
'tipRightBottomCp2',
|
||||
'tipRightBottomEnd',
|
||||
'tipRightBottom',
|
||||
'top',
|
||||
'topCp2',
|
||||
]
|
||||
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (let p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
|
||||
/*
|
||||
* Add points to anchor snaps on
|
||||
*/
|
||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||
|
||||
/*
|
||||
* Mirror points to the other side
|
||||
*/
|
||||
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 of the bib
|
||||
* Radius is fixed, but you could use an option for it)
|
||||
*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
const ids2 = {
|
||||
bottomLeft: macro('round', {
|
||||
id: 'bottomLeft',
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomRight: macro('round', {
|
||||
id: 'bottomRight',
|
||||
from: points.bottomLeft,
|
||||
to: points.topRight,
|
||||
via: points.bottomRight,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
}
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
for (const side in ids2) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct the path
|
||||
*/
|
||||
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()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
/*
|
||||
*
|
||||
* Annotations
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Cut list
|
||||
*/
|
||||
store.cutlist.addCut({ cut: 1, from: 'fabric' })
|
||||
|
||||
/*
|
||||
* Add the snaps
|
||||
*/
|
||||
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
|
||||
snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
|
||||
|
||||
// highlight-start
|
||||
/*
|
||||
* Add the bias tape
|
||||
*/
|
||||
if (complete)
|
||||
paths.bias = paths.seam
|
||||
.offset(-5)
|
||||
.addClass('note dashed')
|
||||
.addText('tutorial:finishWithBiasTape', 'center fill-note')
|
||||
// highlight-end
|
||||
|
||||
/*
|
||||
* Add the title
|
||||
*/
|
||||
points.title = points.bottom.shift(-90, 45)
|
||||
macro('title', {
|
||||
at: points.title,
|
||||
nr: 1,
|
||||
title: 'bib',
|
||||
align: 'center',
|
||||
scale: 0.8,
|
||||
})
|
||||
|
||||
/*
|
||||
* Add the scalebox
|
||||
*/
|
||||
points.scalebox = points.title.shift(-90, 65)
|
||||
macro('scalebox', { at: points.scalebox })
|
||||
|
||||
/*
|
||||
* Add the logo
|
||||
*/
|
||||
points.logo = new Point(0, 0)
|
||||
snippets.logo = new Snippet('logo', points.logo)
|
||||
|
||||
return part
|
||||
/\*
|
||||
_ Macros will return the auto-generated IDs
|
||||
_/
|
||||
const ids1 = {
|
||||
tipRightTop: macro('round', {
|
||||
id: 'tipRightTop',
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
}),
|
||||
tipRightBottom: macro('round', {
|
||||
id: 'tipRightBottom',
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
}),
|
||||
}
|
||||
```
|
||||
|
||||
/\*
|
||||
_ Create points from them with easy names
|
||||
_/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Rotate straps so they don't overlap
|
||||
_/
|
||||
let rotateThese = [
|
||||
'edgeTopLeftCp',
|
||||
'edgeTop',
|
||||
'tipRight',
|
||||
'tipRightTop',
|
||||
'tipRightTopStart',
|
||||
'tipRightTopCp1',
|
||||
'tipRightTopCp2',
|
||||
'tipRightTopEnd',
|
||||
'tipRightBottomStart',
|
||||
'tipRightBottomCp1',
|
||||
'tipRightBottomCp2',
|
||||
'tipRightBottomEnd',
|
||||
'tipRightBottom',
|
||||
'top',
|
||||
'topCp2',
|
||||
]
|
||||
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (let p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Add points to anchor snaps on
|
||||
_/
|
||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||
|
||||
/\*
|
||||
_ Mirror points to the other side
|
||||
_/
|
||||
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 of the bib
|
||||
_ Radius is fixed, but you could use an option for it) \*
|
||||
_ Macros will return the auto-generated IDs
|
||||
_/
|
||||
const ids2 = {
|
||||
bottomLeft: macro('round', {
|
||||
id: 'bottomLeft',
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomRight: macro('round', {
|
||||
id: 'bottomRight',
|
||||
from: points.bottomLeft,
|
||||
to: points.topRight,
|
||||
via: points.bottomRight,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
}
|
||||
/\*
|
||||
_ Create points from them with easy names
|
||||
_/
|
||||
for (const side in ids2) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Construct the path
|
||||
_/
|
||||
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()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
/\* \*
|
||||
_ Annotations
|
||||
_
|
||||
\*/
|
||||
|
||||
/\*
|
||||
_ Cut list
|
||||
_/
|
||||
store.cutlist.addCut({ cut: 1, from: 'fabric' })
|
||||
|
||||
/\*
|
||||
_ Add the snaps
|
||||
_/
|
||||
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
|
||||
snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
|
||||
|
||||
// highlight-start
|
||||
/\*
|
||||
_ Add the bias tape
|
||||
_/
|
||||
if (complete)
|
||||
paths.bias = paths.seam
|
||||
.offset(-5)
|
||||
.addClass('note dashed')
|
||||
.addText('tutorial:finishWithBiasTape', 'center fill-note')
|
||||
// highlight-end
|
||||
|
||||
/\*
|
||||
_ Add the title
|
||||
_/
|
||||
points.title = points.bottom.shift(-90, 45)
|
||||
macro('title', {
|
||||
at: points.title,
|
||||
nr: 1,
|
||||
title: 'bib',
|
||||
align: 'center',
|
||||
scale: 0.8,
|
||||
})
|
||||
|
||||
/\*
|
||||
_ Add the scalebox
|
||||
_/
|
||||
points.scalebox = points.title.shift(-90, 65)
|
||||
macro('scalebox', { at: points.scalebox })
|
||||
|
||||
/\*
|
||||
_ Add the logo
|
||||
_/
|
||||
points.logo = new Point(0, 0)
|
||||
snippets.logo = new Snippet('logo', points.logo)
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
````
|
||||
</Example>
|
||||
|
||||
|
||||
|
@ -556,6 +556,6 @@ function draftBib({
|
|||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
````
|
||||
|
||||
</Example>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Conclusion
|
||||
order: 90
|
||||
sidebar_position: 90
|
||||
---
|
||||
|
||||
Congratulations, we have created our first pattern. And while it's arguably
|
||||
|
@ -25,13 +25,14 @@ 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?
|
||||
|
||||
You could do me a real favor by letting me 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,
|
||||
rushed through another one too quickly? Your feedback helps improve things,
|
||||
so don't be shy and tell me what you think.
|
||||
|
||||
You can reach me at joost@freesewing.org
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Saving space (and trees) with exand
|
||||
order: 40
|
||||
sidebar_position: 40
|
||||
---
|
||||
|
||||
There is one more way we like to save space (and trees): The `expand` setting.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
title: How to communicate to the user
|
||||
order: 50
|
||||
sidebar_position: 50
|
||||
---
|
||||
|
||||
As a designer, there are times you want to bring something to the attention of
|
||||
the user. I am not talking about generic information that can go in the
|
||||
the user. I am not talking about generic information that can go in the
|
||||
documentation, but rather a message that is tailored specifically to this
|
||||
pattern, much like this pattern is specifically tailored to the user.
|
||||
|
||||
|
@ -47,15 +47,15 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
/*
|
||||
* Construct the neck opening
|
||||
*/
|
||||
const target = (measurements.head * options.neckRatio) / 4
|
||||
let tweak = 1
|
||||
let delta
|
||||
do {
|
||||
points.right = new Point((tweak * measurements.head) / 10, 0)
|
||||
points.bottom = new Point(0, (tweak * measurements.head) / 12)
|
||||
/\*
|
||||
_ Construct the neck opening
|
||||
_/
|
||||
const target = (measurements.head _ options.neckRatio) / 4
|
||||
let tweak = 1
|
||||
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)
|
||||
|
@ -67,277 +67,278 @@ function draftBib({
|
|||
delta = paths.neck.length() - target
|
||||
if (delta > 0) tweak = tweak * 0.99
|
||||
else tweak = tweak * 1.02
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
points.rightCp2 = points.rightCp1.flipY()
|
||||
points.bottomCp1 = points.bottomCp2.flipX()
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
points.left = points.right.flipX()
|
||||
points.leftCp1 = points.rightCp2.flipX()
|
||||
points.leftCp2 = points.rightCp1.flipX()
|
||||
points.rightCp2 = points.rightCp1.flipY()
|
||||
points.bottomCp1 = points.bottomCp2.flipX()
|
||||
|
||||
points.top = points.bottom.flipY()
|
||||
points.topCp1 = points.bottomCp2.flipY()
|
||||
points.topCp2 = points.bottomCp1.flipY()
|
||||
points.left = points.right.flipX()
|
||||
points.leftCp1 = points.rightCp2.flipX()
|
||||
points.leftCp2 = points.rightCp1.flipX()
|
||||
|
||||
/*
|
||||
* Construct the outline
|
||||
*/
|
||||
let width = measurements.head * options.widthRatio
|
||||
let length = measurements.head * options.lengthRatio
|
||||
points.top = points.bottom.flipY()
|
||||
points.topCp1 = points.bottomCp2.flipY()
|
||||
points.topCp2 = points.bottomCp1.flipY()
|
||||
|
||||
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)
|
||||
/\*
|
||||
_ Construct the outline
|
||||
_/
|
||||
let width = measurements.head _ options.widthRatio
|
||||
let length = measurements.head _ options.lengthRatio
|
||||
|
||||
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.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)
|
||||
|
||||
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()
|
||||
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)
|
||||
|
||||
/*
|
||||
* Round the end of the straps
|
||||
*/
|
||||
let strap = points.edgeTop.dy(points.top)
|
||||
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()
|
||||
|
||||
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)
|
||||
/\*
|
||||
_ Round the end of the straps
|
||||
_/
|
||||
let strap = points.edgeTop.dy(points.top)
|
||||
|
||||
/*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
const ids1 = {
|
||||
tipRightTop: macro('round', {
|
||||
id: 'tipRightTop',
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
}),
|
||||
tipRightBottom: macro('round', {
|
||||
id: 'tipRightBottom',
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
}),
|
||||
}
|
||||
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)
|
||||
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate straps so they don't overlap
|
||||
*/
|
||||
let rotateThese = [
|
||||
'edgeTopLeftCp',
|
||||
'edgeTop',
|
||||
'tipRight',
|
||||
'tipRightTop',
|
||||
'tipRightTopStart',
|
||||
'tipRightTopCp1',
|
||||
'tipRightTopCp2',
|
||||
'tipRightTopEnd',
|
||||
'tipRightBottomStart',
|
||||
'tipRightBottomCp1',
|
||||
'tipRightBottomCp2',
|
||||
'tipRightBottomEnd',
|
||||
'tipRightBottom',
|
||||
'top',
|
||||
'topCp2',
|
||||
]
|
||||
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (let p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
|
||||
/*
|
||||
* Add points to anchor snaps on
|
||||
*/
|
||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||
|
||||
/*
|
||||
* Mirror points to the other side
|
||||
*/
|
||||
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 of the bib
|
||||
* Radius is fixed, but you could use an option for it)
|
||||
*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
const ids2 = {
|
||||
bottomLeft: macro('round', {
|
||||
id: 'bottomLeft',
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomRight: macro('round', {
|
||||
id: 'bottomRight',
|
||||
from: points.bottomLeft,
|
||||
to: points.topRight,
|
||||
via: points.bottomRight,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
}
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
for (const side in ids2) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct the path
|
||||
*/
|
||||
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()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
/*
|
||||
*
|
||||
* Annotations
|
||||
*
|
||||
*/
|
||||
|
||||
// highlight-start
|
||||
/*
|
||||
* Let the user know about the bias tape and fabric requirements
|
||||
*/
|
||||
store.flag.note({
|
||||
msg: 'tutorial:biasTapeLength',
|
||||
replace: {
|
||||
l: units(paths.seam.length()),
|
||||
},
|
||||
})
|
||||
// highlight-end
|
||||
|
||||
/*
|
||||
* Cut list
|
||||
*/
|
||||
store.cutlist.addCut({ cut: 1, from: 'fabric' })
|
||||
|
||||
/*
|
||||
* Add the snaps
|
||||
*/
|
||||
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
|
||||
snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
|
||||
|
||||
/*
|
||||
* Add the bias tape
|
||||
*/
|
||||
if (complete)
|
||||
paths.bias = paths.seam
|
||||
.offset(-5)
|
||||
.addClass('note dashed')
|
||||
.addText('finishWithBiasTape', 'center fill-note')
|
||||
|
||||
/*
|
||||
* Add the title
|
||||
*/
|
||||
points.title = points.bottom.shift(-90, 45)
|
||||
macro('title', {
|
||||
at: points.title,
|
||||
nr: 1,
|
||||
title: 'bib',
|
||||
align: 'center',
|
||||
scale: 0.8,
|
||||
})
|
||||
|
||||
/*
|
||||
* Add the scalebox
|
||||
*/
|
||||
points.scalebox = points.title.shift(-90, 65)
|
||||
macro('scalebox', { at: points.scalebox })
|
||||
|
||||
/*
|
||||
* Add the logo
|
||||
*/
|
||||
points.logo = new Point(0, 0)
|
||||
snippets.logo = new Snippet('logo', points.logo)
|
||||
|
||||
/*
|
||||
* Add dimensions
|
||||
*/
|
||||
macro('hd', {
|
||||
id: 'wFull',
|
||||
from: points.bottomLeftStart,
|
||||
to: points.bottomRightEnd,
|
||||
y: points.bottomLeft.y + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hBottomToOpeningBottom',
|
||||
from: points.bottomRightStart,
|
||||
to: points.bottom,
|
||||
x: points.bottomRight.x + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hBottomToOpeningCenter',
|
||||
from: points.bottomRightStart,
|
||||
to: points.right,
|
||||
x: points.bottomRight.x + 30,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hTotal',
|
||||
from: points.bottomRightStart,
|
||||
to: points.tipLeftTopStart,
|
||||
x: points.bottomRight.x + 45,
|
||||
})
|
||||
macro('hd', {
|
||||
id: 'wOpening',
|
||||
from: points.left,
|
||||
to: points.right,
|
||||
y: points.left.y + 25,
|
||||
})
|
||||
macro('ld', {
|
||||
id: 'wStrap',
|
||||
from: points.tipLeftBottomEnd,
|
||||
to: points.tipLeftTopStart,
|
||||
d: -15,
|
||||
})
|
||||
|
||||
return part
|
||||
/\*
|
||||
_ Macros will return the auto-generated IDs
|
||||
_/
|
||||
const ids1 = {
|
||||
tipRightTop: macro('round', {
|
||||
id: 'tipRightTop',
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
}),
|
||||
tipRightBottom: macro('round', {
|
||||
id: 'tipRightBottom',
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
}),
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Create points from them with easy names
|
||||
_/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Rotate straps so they don't overlap
|
||||
_/
|
||||
let rotateThese = [
|
||||
'edgeTopLeftCp',
|
||||
'edgeTop',
|
||||
'tipRight',
|
||||
'tipRightTop',
|
||||
'tipRightTopStart',
|
||||
'tipRightTopCp1',
|
||||
'tipRightTopCp2',
|
||||
'tipRightTopEnd',
|
||||
'tipRightBottomStart',
|
||||
'tipRightBottomCp1',
|
||||
'tipRightBottomCp2',
|
||||
'tipRightBottomEnd',
|
||||
'tipRightBottom',
|
||||
'top',
|
||||
'topCp2',
|
||||
]
|
||||
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (let p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Add points to anchor snaps on
|
||||
_/
|
||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||
|
||||
/\*
|
||||
_ Mirror points to the other side
|
||||
_/
|
||||
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 of the bib
|
||||
_ Radius is fixed, but you could use an option for it) \*
|
||||
_ Macros will return the auto-generated IDs
|
||||
_/
|
||||
const ids2 = {
|
||||
bottomLeft: macro('round', {
|
||||
id: 'bottomLeft',
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomRight: macro('round', {
|
||||
id: 'bottomRight',
|
||||
from: points.bottomLeft,
|
||||
to: points.topRight,
|
||||
via: points.bottomRight,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
}
|
||||
/\*
|
||||
_ Create points from them with easy names
|
||||
_/
|
||||
for (const side in ids2) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Construct the path
|
||||
_/
|
||||
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()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
/\* \*
|
||||
_ Annotations
|
||||
_
|
||||
\*/
|
||||
|
||||
// highlight-start
|
||||
/\*
|
||||
_ Let the user know about the bias tape and fabric requirements
|
||||
_/
|
||||
store.flag.note({
|
||||
msg: 'tutorial:biasTapeLength',
|
||||
replace: {
|
||||
l: units(paths.seam.length()),
|
||||
},
|
||||
})
|
||||
// highlight-end
|
||||
|
||||
/\*
|
||||
_ Cut list
|
||||
_/
|
||||
store.cutlist.addCut({ cut: 1, from: 'fabric' })
|
||||
|
||||
/\*
|
||||
_ Add the snaps
|
||||
_/
|
||||
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
|
||||
snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
|
||||
|
||||
/\*
|
||||
_ Add the bias tape
|
||||
_/
|
||||
if (complete)
|
||||
paths.bias = paths.seam
|
||||
.offset(-5)
|
||||
.addClass('note dashed')
|
||||
.addText('finishWithBiasTape', 'center fill-note')
|
||||
|
||||
/\*
|
||||
_ Add the title
|
||||
_/
|
||||
points.title = points.bottom.shift(-90, 45)
|
||||
macro('title', {
|
||||
at: points.title,
|
||||
nr: 1,
|
||||
title: 'bib',
|
||||
align: 'center',
|
||||
scale: 0.8,
|
||||
})
|
||||
|
||||
/\*
|
||||
_ Add the scalebox
|
||||
_/
|
||||
points.scalebox = points.title.shift(-90, 65)
|
||||
macro('scalebox', { at: points.scalebox })
|
||||
|
||||
/\*
|
||||
_ Add the logo
|
||||
_/
|
||||
points.logo = new Point(0, 0)
|
||||
snippets.logo = new Snippet('logo', points.logo)
|
||||
|
||||
/\*
|
||||
_ Add dimensions
|
||||
_/
|
||||
macro('hd', {
|
||||
id: 'wFull',
|
||||
from: points.bottomLeftStart,
|
||||
to: points.bottomRightEnd,
|
||||
y: points.bottomLeft.y + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hBottomToOpeningBottom',
|
||||
from: points.bottomRightStart,
|
||||
to: points.bottom,
|
||||
x: points.bottomRight.x + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hBottomToOpeningCenter',
|
||||
from: points.bottomRightStart,
|
||||
to: points.right,
|
||||
x: points.bottomRight.x + 30,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hTotal',
|
||||
from: points.bottomRightStart,
|
||||
to: points.tipLeftTopStart,
|
||||
x: points.bottomRight.x + 45,
|
||||
})
|
||||
macro('hd', {
|
||||
id: 'wOpening',
|
||||
from: points.left,
|
||||
to: points.right,
|
||||
y: points.left.y + 25,
|
||||
})
|
||||
macro('ld', {
|
||||
id: 'wStrap',
|
||||
from: points.tipLeftBottomEnd,
|
||||
to: points.tipLeftTopStart,
|
||||
d: -15,
|
||||
})
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
```
|
||||
</Example>
|
||||
```
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Supporting translation
|
||||
order: 80
|
||||
sidebar_position: 80
|
||||
---
|
||||
|
||||
:::note [FIXME]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Facilitating frontend integration
|
||||
order: 60
|
||||
sidebar_position: 60
|
||||
---
|
||||
|
||||
Strictly speaking, this tutorial is about learning to use FreeSewing's core
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Supporting paperless patterns
|
||||
order: 30
|
||||
sidebar_position: 30
|
||||
---
|
||||
|
||||
The goal of paperless patterns is to create a pattern that we don't need to
|
||||
|
@ -14,14 +14,14 @@ So let's make the extra effort to make our bib design support paperless.
|
|||
## The paperless setting
|
||||
|
||||
Users can request paperless patterns by setting [the `paperless`
|
||||
setting](/reference/settings/paperless) to a *truthy* value.
|
||||
setting](/reference/settings/paperless) to a _truthy_ value.
|
||||
|
||||
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.
|
||||
different macros to add _dimensions_ to the pattern.
|
||||
|
||||
While the grid gets added automatically, the dimensions we have to add ourselves.
|
||||
Thankfully, there's macros that can help us with that, specifically:
|
||||
|
@ -58,15 +58,15 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
/*
|
||||
* Construct the neck opening
|
||||
*/
|
||||
const target = (measurements.head * options.neckRatio) / 4
|
||||
let tweak = 1
|
||||
let delta
|
||||
do {
|
||||
points.right = new Point((tweak * measurements.head) / 10, 0)
|
||||
points.bottom = new Point(0, (tweak * measurements.head) / 12)
|
||||
/\*
|
||||
_ Construct the neck opening
|
||||
_/
|
||||
const target = (measurements.head _ options.neckRatio) / 4
|
||||
let tweak = 1
|
||||
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)
|
||||
|
@ -78,267 +78,268 @@ function draftBib({
|
|||
delta = paths.neck.length() - target
|
||||
if (delta > 0) tweak = tweak * 0.99
|
||||
else tweak = tweak * 1.02
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
points.rightCp2 = points.rightCp1.flipY()
|
||||
points.bottomCp1 = points.bottomCp2.flipX()
|
||||
} while (Math.abs(delta) > 1)
|
||||
|
||||
points.left = points.right.flipX()
|
||||
points.leftCp1 = points.rightCp2.flipX()
|
||||
points.leftCp2 = points.rightCp1.flipX()
|
||||
points.rightCp2 = points.rightCp1.flipY()
|
||||
points.bottomCp1 = points.bottomCp2.flipX()
|
||||
|
||||
points.top = points.bottom.flipY()
|
||||
points.topCp1 = points.bottomCp2.flipY()
|
||||
points.topCp2 = points.bottomCp1.flipY()
|
||||
points.left = points.right.flipX()
|
||||
points.leftCp1 = points.rightCp2.flipX()
|
||||
points.leftCp2 = points.rightCp1.flipX()
|
||||
|
||||
/*
|
||||
* Construct the outline
|
||||
*/
|
||||
let width = measurements.head * options.widthRatio
|
||||
let length = measurements.head * options.lengthRatio
|
||||
points.top = points.bottom.flipY()
|
||||
points.topCp1 = points.bottomCp2.flipY()
|
||||
points.topCp2 = points.bottomCp1.flipY()
|
||||
|
||||
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)
|
||||
/\*
|
||||
_ Construct the outline
|
||||
_/
|
||||
let width = measurements.head _ options.widthRatio
|
||||
let length = measurements.head _ options.lengthRatio
|
||||
|
||||
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.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)
|
||||
|
||||
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()
|
||||
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)
|
||||
|
||||
/*
|
||||
* Round the end of the straps
|
||||
*/
|
||||
let strap = points.edgeTop.dy(points.top)
|
||||
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()
|
||||
|
||||
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)
|
||||
/\*
|
||||
_ Round the end of the straps
|
||||
_/
|
||||
let strap = points.edgeTop.dy(points.top)
|
||||
|
||||
/*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
const ids1 = {
|
||||
tipRightTop: macro('round', {
|
||||
id: 'tipRightTop',
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
}),
|
||||
tipRightBottom: macro('round', {
|
||||
id: 'tipRightBottom',
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
}),
|
||||
}
|
||||
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)
|
||||
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate straps so they don't overlap
|
||||
*/
|
||||
let rotateThese = [
|
||||
'edgeTopLeftCp',
|
||||
'edgeTop',
|
||||
'tipRight',
|
||||
'tipRightTop',
|
||||
'tipRightTopStart',
|
||||
'tipRightTopCp1',
|
||||
'tipRightTopCp2',
|
||||
'tipRightTopEnd',
|
||||
'tipRightBottomStart',
|
||||
'tipRightBottomCp1',
|
||||
'tipRightBottomCp2',
|
||||
'tipRightBottomEnd',
|
||||
'tipRightBottom',
|
||||
'top',
|
||||
'topCp2',
|
||||
]
|
||||
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (let p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
|
||||
/*
|
||||
* Add points to anchor snaps on
|
||||
*/
|
||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||
|
||||
/*
|
||||
* Mirror points to the other side
|
||||
*/
|
||||
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 of the bib
|
||||
* Radius is fixed, but you could use an option for it)
|
||||
*
|
||||
* Macros will return the auto-generated IDs
|
||||
*/
|
||||
const ids2 = {
|
||||
bottomLeft: macro('round', {
|
||||
id: 'bottomLeft',
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomRight: macro('round', {
|
||||
id: 'bottomRight',
|
||||
from: points.bottomLeft,
|
||||
to: points.topRight,
|
||||
via: points.bottomRight,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
}
|
||||
/*
|
||||
* Create points from them with easy names
|
||||
*/
|
||||
for (const side in ids2) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct the path
|
||||
*/
|
||||
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()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
/*
|
||||
*
|
||||
* Annotations
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Cut list
|
||||
*/
|
||||
store.cutlist.addCut({ cut: 1, from: 'fabric' })
|
||||
|
||||
/*
|
||||
* Add the snaps
|
||||
*/
|
||||
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
|
||||
snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
|
||||
|
||||
/*
|
||||
* Add the bias tape
|
||||
*/
|
||||
if (complete)
|
||||
paths.bias = paths.seam
|
||||
.offset(-5)
|
||||
.addClass('note dashed')
|
||||
.addText('fronscratch:finishWithBiasTape', 'center fill-note')
|
||||
|
||||
/*
|
||||
* Add the title
|
||||
*/
|
||||
points.title = points.bottom.shift(-90, 45)
|
||||
macro('title', {
|
||||
at: points.title,
|
||||
nr: 1,
|
||||
title: 'bib',
|
||||
align: 'center',
|
||||
scale: 0.8,
|
||||
})
|
||||
|
||||
/*
|
||||
* Add the scalebox
|
||||
*/
|
||||
points.scalebox = points.title.shift(-90, 65)
|
||||
macro('scalebox', { at: points.scalebox })
|
||||
|
||||
/*
|
||||
* Add the logo
|
||||
*/
|
||||
points.logo = new Point(0, 0)
|
||||
snippets.logo = new Snippet('logo', points.logo)
|
||||
|
||||
// highlight-start
|
||||
/*
|
||||
* Add dimensions
|
||||
*/
|
||||
macro('hd', {
|
||||
id: 'wFull',
|
||||
from: points.bottomLeftStart,
|
||||
to: points.bottomRightEnd,
|
||||
y: points.bottomLeft.y + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hBottomToOpeningBottom',
|
||||
from: points.bottomRightStart,
|
||||
to: points.bottom,
|
||||
x: points.bottomRight.x + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hBottomToOpeningCenter',
|
||||
from: points.bottomRightStart,
|
||||
to: points.right,
|
||||
x: points.bottomRight.x + 30,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hTotal',
|
||||
from: points.bottomRightStart,
|
||||
to: points.tipLeftTopStart,
|
||||
x: points.bottomRight.x + 45,
|
||||
})
|
||||
macro('hd', {
|
||||
id: 'wOpening',
|
||||
from: points.left,
|
||||
to: points.right,
|
||||
y: points.left.y + 25,
|
||||
})
|
||||
macro('ld', {
|
||||
id: 'wStrap',
|
||||
from: points.tipLeftBottomEnd,
|
||||
to: points.tipLeftTopStart,
|
||||
d: -15,
|
||||
})
|
||||
// highlight-end
|
||||
|
||||
return part
|
||||
/\*
|
||||
_ Macros will return the auto-generated IDs
|
||||
_/
|
||||
const ids1 = {
|
||||
tipRightTop: macro('round', {
|
||||
id: 'tipRightTop',
|
||||
from: points.edgeTop,
|
||||
to: points.tipRight,
|
||||
via: points.tipRightTop,
|
||||
}),
|
||||
tipRightBottom: macro('round', {
|
||||
id: 'tipRightBottom',
|
||||
from: points.tipRight,
|
||||
to: points.top,
|
||||
via: points.tipRightBottom,
|
||||
}),
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Create points from them with easy names
|
||||
_/
|
||||
for (const side in ids1) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Rotate straps so they don't overlap
|
||||
_/
|
||||
let rotateThese = [
|
||||
'edgeTopLeftCp',
|
||||
'edgeTop',
|
||||
'tipRight',
|
||||
'tipRightTop',
|
||||
'tipRightTopStart',
|
||||
'tipRightTopCp1',
|
||||
'tipRightTopCp2',
|
||||
'tipRightTopEnd',
|
||||
'tipRightBottomStart',
|
||||
'tipRightBottomCp1',
|
||||
'tipRightBottomCp2',
|
||||
'tipRightBottomEnd',
|
||||
'tipRightBottom',
|
||||
'top',
|
||||
'topCp2',
|
||||
]
|
||||
|
||||
while (points.tipRightBottomStart.x > -1) {
|
||||
for (let p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Add points to anchor snaps on
|
||||
_/
|
||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||
|
||||
/\*
|
||||
_ Mirror points to the other side
|
||||
_/
|
||||
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 of the bib
|
||||
_ Radius is fixed, but you could use an option for it) \*
|
||||
_ Macros will return the auto-generated IDs
|
||||
_/
|
||||
const ids2 = {
|
||||
bottomLeft: macro('round', {
|
||||
id: 'bottomLeft',
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
bottomRight: macro('round', {
|
||||
id: 'bottomRight',
|
||||
from: points.bottomLeft,
|
||||
to: points.topRight,
|
||||
via: points.bottomRight,
|
||||
radius: points.bottomRight.x / 4,
|
||||
}),
|
||||
}
|
||||
/\*
|
||||
_ Create points from them with easy names
|
||||
_/
|
||||
for (const side in ids2) {
|
||||
for (const id of ['start', 'cp1', 'cp2', 'end']) {
|
||||
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
|
||||
}
|
||||
}
|
||||
|
||||
/\*
|
||||
_ Construct the path
|
||||
_/
|
||||
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()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
/\* \*
|
||||
_ Annotations
|
||||
_
|
||||
\*/
|
||||
|
||||
/\*
|
||||
_ Cut list
|
||||
_/
|
||||
store.cutlist.addCut({ cut: 1, from: 'fabric' })
|
||||
|
||||
/\*
|
||||
_ Add the snaps
|
||||
_/
|
||||
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
|
||||
snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
|
||||
|
||||
/\*
|
||||
_ Add the bias tape
|
||||
_/
|
||||
if (complete)
|
||||
paths.bias = paths.seam
|
||||
.offset(-5)
|
||||
.addClass('note dashed')
|
||||
.addText('fronscratch:finishWithBiasTape', 'center fill-note')
|
||||
|
||||
/\*
|
||||
_ Add the title
|
||||
_/
|
||||
points.title = points.bottom.shift(-90, 45)
|
||||
macro('title', {
|
||||
at: points.title,
|
||||
nr: 1,
|
||||
title: 'bib',
|
||||
align: 'center',
|
||||
scale: 0.8,
|
||||
})
|
||||
|
||||
/\*
|
||||
_ Add the scalebox
|
||||
_/
|
||||
points.scalebox = points.title.shift(-90, 65)
|
||||
macro('scalebox', { at: points.scalebox })
|
||||
|
||||
/\*
|
||||
_ Add the logo
|
||||
_/
|
||||
points.logo = new Point(0, 0)
|
||||
snippets.logo = new Snippet('logo', points.logo)
|
||||
|
||||
// highlight-start
|
||||
/\*
|
||||
_ Add dimensions
|
||||
_/
|
||||
macro('hd', {
|
||||
id: 'wFull',
|
||||
from: points.bottomLeftStart,
|
||||
to: points.bottomRightEnd,
|
||||
y: points.bottomLeft.y + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hBottomToOpeningBottom',
|
||||
from: points.bottomRightStart,
|
||||
to: points.bottom,
|
||||
x: points.bottomRight.x + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hBottomToOpeningCenter',
|
||||
from: points.bottomRightStart,
|
||||
to: points.right,
|
||||
x: points.bottomRight.x + 30,
|
||||
})
|
||||
macro('vd', {
|
||||
id: 'hTotal',
|
||||
from: points.bottomRightStart,
|
||||
to: points.tipLeftTopStart,
|
||||
x: points.bottomRight.x + 45,
|
||||
})
|
||||
macro('hd', {
|
||||
id: 'wOpening',
|
||||
from: points.left,
|
||||
to: points.right,
|
||||
y: points.left.y + 25,
|
||||
})
|
||||
macro('ld', {
|
||||
id: 'wStrap',
|
||||
from: points.tipLeftBottomEnd,
|
||||
to: points.tipLeftTopStart,
|
||||
d: -15,
|
||||
})
|
||||
// highlight-end
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
```
|
||||
</Example>
|
||||
```
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Adding seam allowance
|
||||
order: 10
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
When adding seam allowance to a pattern, there are 3 things that come into play:
|
||||
|
@ -24,29 +24,30 @@ function draftBib({
|
|||
part,
|
||||
}) {
|
||||
|
||||
points.topLeft = new Point(0,0)
|
||||
points.bottomRight = new Point(100,40)
|
||||
points.topRight = new Point(points.bottomRight.x, points.topLeft.y)
|
||||
points.bottomLeft = new Point(points.topLeft.x, points.bottomRight.y)
|
||||
points.cp1 = new Point(50, 20)
|
||||
points.cp2 = new Point(70, 60)
|
||||
points.topLeft = new Point(0,0)
|
||||
points.bottomRight = new Point(100,40)
|
||||
points.topRight = new Point(points.bottomRight.x, points.topLeft.y)
|
||||
points.bottomLeft = new Point(points.topLeft.x, points.bottomRight.y)
|
||||
points.cp1 = new Point(50, 20)
|
||||
points.cp2 = new Point(70, 60)
|
||||
|
||||
paths.shape = new Path()
|
||||
.move(points.topLeft)
|
||||
.line(points.bottomLeft)
|
||||
.curve(points.cp1, points.cp2, points.bottomRight)
|
||||
.line(points.topRight)
|
||||
.line(points.topLeft)
|
||||
.close()
|
||||
.addClass('fabric')
|
||||
paths.shape = new Path()
|
||||
.move(points.topLeft)
|
||||
.line(points.bottomLeft)
|
||||
.curve(points.cp1, points.cp2, points.bottomRight)
|
||||
.line(points.topRight)
|
||||
.line(points.topLeft)
|
||||
.close()
|
||||
.addClass('fabric')
|
||||
|
||||
// highlight-start
|
||||
if (sa) paths.sa = paths.shape.offset(sa).addClass('fabric sa')
|
||||
// highlight-end
|
||||
// highlight-start
|
||||
if (sa) paths.sa = paths.shape.offset(sa).addClass('fabric sa')
|
||||
// highlight-end
|
||||
|
||||
return part
|
||||
return part
|
||||
}
|
||||
```
|
||||
|
||||
````
|
||||
</Example>
|
||||
|
||||
As you can see from the source, we can destructure an `sa` variable (short for
|
||||
|
@ -63,7 +64,7 @@ seam allowance:
|
|||
if (sa) paths.sa = paths.shape
|
||||
.offset(sa)
|
||||
.addClass('fabric sa')
|
||||
```
|
||||
````
|
||||
|
||||
To refer back to our three question: Whether the user wants seam allowance, and
|
||||
if so how much seam allowance is answered by the `sa` value passed to our draft
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Testing your designs
|
||||
order: 70
|
||||
sidebar_position: 70
|
||||
---
|
||||
|
||||
With the basic outline of our pattern ready, now would be a good time
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
title: Tutorials
|
||||
order: zaa
|
||||
---
|
||||
|
||||
You can find a list of all FreeSewing tutorials below:
|
||||
|
@ -14,4 +13,3 @@ You can find a list of all FreeSewing tutorials below:
|
|||
Tutorials are lessons that take you by the hand through a series of steps to complete a project.
|
||||
|
||||
:::
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue