chore(plugin-annotations): Refactor plugin structure
This commit is contained in:
parent
607bc010da
commit
94d8ae4cab
11 changed files with 611 additions and 706 deletions
|
@ -1,5 +1,3 @@
|
|||
import { version, name } from '../data.mjs'
|
||||
|
||||
// Method that draws the actual bartack
|
||||
const drawBartack = (pointList, { Path }) => {
|
||||
let path = new Path().move(pointList.path1[0])
|
||||
|
@ -102,33 +100,25 @@ function createBartack(so, props) {
|
|||
return true
|
||||
}
|
||||
|
||||
// The actual plugin
|
||||
export const bartack = {
|
||||
name,
|
||||
version,
|
||||
macros: {
|
||||
bartack: function (so, props) {
|
||||
return createBartack(so, props)
|
||||
},
|
||||
bartackAlong: function (so, props) {
|
||||
so.bartackFractionAlong = false
|
||||
so.bartackAlong = true
|
||||
so.anchor = false
|
||||
so.from = false
|
||||
so.to = false
|
||||
return createBartack(so, props)
|
||||
},
|
||||
bartackFractionAlong: function (so, props) {
|
||||
so.bartackFractionAlong = true
|
||||
so.bartackAlong = false
|
||||
so.anchor = false
|
||||
so.from = false
|
||||
so.to = false
|
||||
return createBartack(so, props)
|
||||
},
|
||||
// Export macros
|
||||
export const bartackMacros = {
|
||||
bartack: function (so, props) {
|
||||
return createBartack(so, props)
|
||||
},
|
||||
bartackAlong: function (so, props) {
|
||||
so.bartackFractionAlong = false
|
||||
so.bartackAlong = true
|
||||
so.anchor = false
|
||||
so.from = false
|
||||
so.to = false
|
||||
return createBartack(so, props)
|
||||
},
|
||||
bartackFractionAlong: function (so, props) {
|
||||
so.bartackFractionAlong = true
|
||||
so.bartackAlong = false
|
||||
so.anchor = false
|
||||
so.from = false
|
||||
so.to = false
|
||||
return createBartack(so, props)
|
||||
},
|
||||
}
|
||||
|
||||
// More specifically named exports
|
||||
export const bartackPlugin = bartack
|
||||
export const pluginBartack = bartack
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { name, version } from '../data.mjs'
|
||||
|
||||
const defs = [
|
||||
// button
|
||||
`
|
||||
|
@ -65,18 +63,13 @@ const defs = [
|
|||
</g>`,
|
||||
]
|
||||
|
||||
export const buttons = {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: function (svg) {
|
||||
// Export hooks
|
||||
export const buttonsHooks = {
|
||||
preRender: [
|
||||
function (svg) {
|
||||
for (const def of defs) {
|
||||
if (svg.defs.indexOf(def) === -1) svg.defs += def
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
// More specifically named exports
|
||||
export const buttonsPlugin = buttons
|
||||
export const pluginButtons = buttons
|
||||
|
|
|
@ -1,62 +1,53 @@
|
|||
import { name, version } from '../data.mjs'
|
||||
// Export macros
|
||||
export const crossboxMacros = {
|
||||
crossbox: function (so, { points, Point, paths, Path, getId }) {
|
||||
let id = getId()
|
||||
let shiftFraction = 0.1
|
||||
points[id + '_boxTopLeft'] = so.from.copy()
|
||||
points[id + '_boxBottomRight'] = so.to.copy()
|
||||
points[id + '_boxTopRight'] = new Point(so.to.x, so.from.y)
|
||||
points[id + '_boxBottomLeft'] = new Point(so.from.x, so.to.y)
|
||||
|
||||
export const crossbox = {
|
||||
name: 'crossbox',
|
||||
version,
|
||||
macros: {
|
||||
crossbox: function (so, { points, Point, paths, Path, getId }) {
|
||||
let id = getId()
|
||||
let shiftFraction = 0.1
|
||||
points[id + '_boxTopLeft'] = so.from.copy()
|
||||
points[id + '_boxBottomRight'] = so.to.copy()
|
||||
points[id + '_boxTopRight'] = new Point(so.to.x, so.from.y)
|
||||
points[id + '_boxBottomLeft'] = new Point(so.from.x, so.to.y)
|
||||
points[id + '_topCrossTL'] = points[id + '_boxTopLeft'].shiftFractionTowards(
|
||||
points[id + '_boxBottomRight'],
|
||||
shiftFraction
|
||||
)
|
||||
points[id + '_topCrossTR'] = points[id + '_boxTopRight'].shiftFractionTowards(
|
||||
points[id + '_boxBottomLeft'],
|
||||
shiftFraction
|
||||
)
|
||||
points[id + '_topCrossBL'] = points[id + '_boxBottomLeft'].shiftFractionTowards(
|
||||
points[id + '_boxTopRight'],
|
||||
shiftFraction
|
||||
)
|
||||
points[id + '_topCrossBR'] = points[id + '_boxBottomRight'].shiftFractionTowards(
|
||||
points[id + '_boxTopLeft'],
|
||||
shiftFraction
|
||||
)
|
||||
|
||||
points[id + '_topCrossTL'] = points[id + '_boxTopLeft'].shiftFractionTowards(
|
||||
points[id + '_boxBottomRight'],
|
||||
shiftFraction
|
||||
)
|
||||
points[id + '_topCrossTR'] = points[id + '_boxTopRight'].shiftFractionTowards(
|
||||
points[id + '_boxBottomLeft'],
|
||||
shiftFraction
|
||||
)
|
||||
points[id + '_topCrossBL'] = points[id + '_boxBottomLeft'].shiftFractionTowards(
|
||||
points[id + '_boxTopRight'],
|
||||
shiftFraction
|
||||
)
|
||||
points[id + '_topCrossBR'] = points[id + '_boxBottomRight'].shiftFractionTowards(
|
||||
points[id + '_boxTopLeft'],
|
||||
shiftFraction
|
||||
)
|
||||
|
||||
paths[id + 'crossBox'] = new Path()
|
||||
.move(points[id + '_boxTopLeft'])
|
||||
.line(points[id + '_boxTopRight'])
|
||||
.line(points[id + '_boxBottomRight'])
|
||||
.line(points[id + '_boxBottomLeft'])
|
||||
.line(points[id + '_boxTopLeft'])
|
||||
.close()
|
||||
.attr('class', 'lining dotted stroke-sm')
|
||||
paths[id + '_topCross'] = new Path()
|
||||
.move(points[id + '_topCrossTL'])
|
||||
.line(points[id + '_topCrossBR'])
|
||||
.line(points[id + '_topCrossTR'])
|
||||
.line(points[id + '_topCrossBL'])
|
||||
.line(points[id + '_topCrossTL'])
|
||||
.line(points[id + '_topCrossTR'])
|
||||
.move(points[id + '_topCrossBR'])
|
||||
.line(points[id + '_topCrossBL'])
|
||||
.attr('class', 'lining dotted stroke-sm')
|
||||
if (typeof so.text === 'string') {
|
||||
points.textAnchor = points[id + '_boxTopLeft']
|
||||
.shiftFractionTowards(points[id + '_boxBottomRight'], 0.5)
|
||||
.attr('data-text', so.text)
|
||||
.attr('data-text-class', 'center')
|
||||
}
|
||||
},
|
||||
paths[id + 'crossBox'] = new Path()
|
||||
.move(points[id + '_boxTopLeft'])
|
||||
.line(points[id + '_boxTopRight'])
|
||||
.line(points[id + '_boxBottomRight'])
|
||||
.line(points[id + '_boxBottomLeft'])
|
||||
.line(points[id + '_boxTopLeft'])
|
||||
.close()
|
||||
.attr('class', 'lining dotted stroke-sm')
|
||||
paths[id + '_topCross'] = new Path()
|
||||
.move(points[id + '_topCrossTL'])
|
||||
.line(points[id + '_topCrossBR'])
|
||||
.line(points[id + '_topCrossTR'])
|
||||
.line(points[id + '_topCrossBL'])
|
||||
.line(points[id + '_topCrossTL'])
|
||||
.line(points[id + '_topCrossTR'])
|
||||
.move(points[id + '_topCrossBR'])
|
||||
.line(points[id + '_topCrossBL'])
|
||||
.attr('class', 'lining dotted stroke-sm')
|
||||
if (typeof so.text === 'string') {
|
||||
points.textAnchor = points[id + '_boxTopLeft']
|
||||
.shiftFractionTowards(points[id + '_boxBottomRight'], 0.5)
|
||||
.attr('data-text', so.text)
|
||||
.attr('data-text-class', 'center')
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// More specifically named exports
|
||||
export const crossboxPlugin = crossbox
|
||||
export const pluginCrossbox = crossbox
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { name, version } from '../data.mjs'
|
||||
|
||||
const markers = `
|
||||
<marker orient="auto" refY="4.0" refX="0.0" id="cutonfoldFrom" style="overflow:visible;" markerWidth="12" markerHeight="8">
|
||||
<path class="note fill-note" d="M 0,4 L 12,0 C 10,2 10,6 12,8 z" />
|
||||
|
@ -9,63 +7,59 @@ const markers = `
|
|||
</marker>
|
||||
`
|
||||
|
||||
export const cutonfold = {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: (svg) => {
|
||||
// Export hooks
|
||||
export const cutonfoldHooks = {
|
||||
preRender: [
|
||||
function (svg) {
|
||||
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
||||
},
|
||||
},
|
||||
macros: {
|
||||
cutonfold: function (so, { points, paths, Path, complete, setCutOnFold, setGrain, scale }) {
|
||||
if (so === false) {
|
||||
delete points.cutonfoldFrom
|
||||
delete points.cutonfoldTo
|
||||
delete points.cutonfoldVia1
|
||||
delete points.cutonfoldVia2
|
||||
delete paths.cutonfold
|
||||
// setCutOnFold relies on plugin-cutlist
|
||||
if (typeof setCutOnFold === 'function') {
|
||||
setCutOnFold(false) // Restore default
|
||||
}
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
offset: 15,
|
||||
margin: 5,
|
||||
prefix: 'cutonfold',
|
||||
...so,
|
||||
}
|
||||
],
|
||||
}
|
||||
// Export macros
|
||||
export const cutonfoldMacros = {
|
||||
cutonfold: function (so, { points, paths, Path, complete, setCutOnFold, setGrain, scale }) {
|
||||
if (so === false) {
|
||||
delete points.cutonfoldFrom
|
||||
delete points.cutonfoldTo
|
||||
delete points.cutonfoldVia1
|
||||
delete points.cutonfoldVia2
|
||||
delete paths.cutonfold
|
||||
// setCutOnFold relies on plugin-cutlist
|
||||
if (typeof setCutOnFold === 'function') {
|
||||
setCutOnFold(so.from, so.to)
|
||||
if (so.grainline) setGrain(so.from.angle(so.to))
|
||||
setCutOnFold(false) // Restore default
|
||||
}
|
||||
if (complete) {
|
||||
points[so.prefix + 'From'] = so.from.shiftFractionTowards(so.to, so.margin / 100)
|
||||
points[so.prefix + 'To'] = so.to.shiftFractionTowards(so.from, so.margin / 100)
|
||||
points[so.prefix + 'Via1'] = points[so.prefix + 'From']
|
||||
.shiftTowards(so.from, so.offset * scale)
|
||||
.rotate(-90, points[so.prefix + 'From'])
|
||||
points[so.prefix + 'Via2'] = points[so.prefix + 'To']
|
||||
.shiftTowards(so.to, so.offset * scale)
|
||||
.rotate(90, points[so.prefix + 'To'])
|
||||
const text = so.grainline ? 'cutOnFoldAndGrainline' : 'cutOnFold'
|
||||
paths[so.prefix + 'Cutonfold'] = new Path()
|
||||
.move(points[so.prefix + 'From'])
|
||||
.line(points[so.prefix + 'Via1'])
|
||||
.line(points[so.prefix + 'Via2'])
|
||||
.line(points[so.prefix + 'To'])
|
||||
.attr('class', 'note')
|
||||
.attr('marker-start', 'url(#cutonfoldFrom)')
|
||||
.attr('marker-end', 'url(#cutonfoldTo)')
|
||||
.attr('data-text', text)
|
||||
.attr('data-text-class', 'center fill-note')
|
||||
}
|
||||
},
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
offset: 15,
|
||||
margin: 5,
|
||||
prefix: 'cutonfold',
|
||||
...so,
|
||||
}
|
||||
if (typeof setCutOnFold === 'function') {
|
||||
setCutOnFold(so.from, so.to)
|
||||
if (so.grainline) setGrain(so.from.angle(so.to))
|
||||
}
|
||||
if (complete) {
|
||||
points[so.prefix + 'From'] = so.from.shiftFractionTowards(so.to, so.margin / 100)
|
||||
points[so.prefix + 'To'] = so.to.shiftFractionTowards(so.from, so.margin / 100)
|
||||
points[so.prefix + 'Via1'] = points[so.prefix + 'From']
|
||||
.shiftTowards(so.from, so.offset * scale)
|
||||
.rotate(-90, points[so.prefix + 'From'])
|
||||
points[so.prefix + 'Via2'] = points[so.prefix + 'To']
|
||||
.shiftTowards(so.to, so.offset * scale)
|
||||
.rotate(90, points[so.prefix + 'To'])
|
||||
const text = so.grainline ? 'cutOnFoldAndGrainline' : 'cutOnFold'
|
||||
paths[so.prefix + 'Cutonfold'] = new Path()
|
||||
.move(points[so.prefix + 'From'])
|
||||
.line(points[so.prefix + 'Via1'])
|
||||
.line(points[so.prefix + 'Via2'])
|
||||
.line(points[so.prefix + 'To'])
|
||||
.attr('class', 'note')
|
||||
.attr('marker-start', 'url(#cutonfoldFrom)')
|
||||
.attr('marker-end', 'url(#cutonfoldTo)')
|
||||
.attr('data-text', text)
|
||||
.attr('data-text-class', 'center fill-note')
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// More specifically named exports
|
||||
export const cutonfoldPlugin = cutonfold
|
||||
export const pluginCutonfold = cutonfold
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { name, version } from '../data.mjs'
|
||||
|
||||
const markers = `
|
||||
<marker orient="auto" refY="4.0" refX="10.0" id="grainlineFrom" style="overflow:visible;" markerWidth="12" markerHeight="8">
|
||||
<path class="note fill-note" d="M 0,4 L 12,0 C 10,2 10,6 12,8 z" />
|
||||
|
@ -10,47 +8,42 @@ const markers = `
|
|||
|
||||
const dflts = { text: 'grainline' }
|
||||
|
||||
export const grainline = {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: (svg) => {
|
||||
// Export hooks and macros
|
||||
export const grainlineHooks = {
|
||||
preRender: [
|
||||
function (svg) {
|
||||
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
||||
},
|
||||
},
|
||||
macros: {
|
||||
grainline: function (so = {}, { points, paths, Path, complete, setGrain }) {
|
||||
if (so === false) {
|
||||
delete points.grainlineFrom
|
||||
delete points.grainlineTo
|
||||
delete paths.grainline
|
||||
setGrain(90) // Restoring default
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
...dflts,
|
||||
...so,
|
||||
}
|
||||
// setGrain relies on plugin-cutlist
|
||||
if (typeof setGrain === 'function') {
|
||||
setGrain(so.from.angle(so.to))
|
||||
}
|
||||
if (complete) {
|
||||
points.grainlineFrom = so.from.shiftFractionTowards(so.to, 0.05)
|
||||
points.grainlineTo = so.to.shiftFractionTowards(so.from, 0.05)
|
||||
paths.grainline = new Path()
|
||||
.move(points.grainlineFrom)
|
||||
.line(points.grainlineTo)
|
||||
.attr('class', 'note')
|
||||
.attr('marker-start', 'url(#grainlineFrom)')
|
||||
.attr('marker-end', 'url(#grainlineTo)')
|
||||
.attr('data-text', so.text)
|
||||
.attr('data-text-class', 'center fill-note')
|
||||
}
|
||||
},
|
||||
],
|
||||
}
|
||||
export const grainlineMacros = {
|
||||
grainline: function (so = {}, { points, paths, Path, complete, setGrain }) {
|
||||
if (so === false) {
|
||||
delete points.grainlineFrom
|
||||
delete points.grainlineTo
|
||||
delete paths.grainline
|
||||
setGrain(90) // Restoring default
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
...dflts,
|
||||
...so,
|
||||
}
|
||||
// setGrain relies on plugin-cutlist
|
||||
if (typeof setGrain === 'function') {
|
||||
setGrain(so.from.angle(so.to))
|
||||
}
|
||||
if (complete) {
|
||||
points.grainlineFrom = so.from.shiftFractionTowards(so.to, 0.05)
|
||||
points.grainlineTo = so.to.shiftFractionTowards(so.from, 0.05)
|
||||
paths.grainline = new Path()
|
||||
.move(points.grainlineFrom)
|
||||
.line(points.grainlineTo)
|
||||
.attr('class', 'note')
|
||||
.attr('marker-start', 'url(#grainlineFrom)')
|
||||
.attr('marker-end', 'url(#grainlineTo)')
|
||||
.attr('data-text', so.text)
|
||||
.attr('data-text-class', 'center fill-note')
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// More specifically named exports
|
||||
export const grainlinePlugin = grainline
|
||||
export const pluginGrainline = grainline
|
||||
|
|
|
@ -1,59 +1,41 @@
|
|||
import { name, version } from '../data.mjs'
|
||||
|
||||
import { bartackPlugin } from './bartack.mjs'
|
||||
import { buttonsPlugin } from './buttons.mjs'
|
||||
import { crossboxPlugin } from './crossbox.mjs'
|
||||
import { cutonfoldPlugin } from './cutonfold.mjs'
|
||||
import { grainlinePlugin } from './grainline.mjs'
|
||||
import { logoPlugin } from './logo.mjs'
|
||||
import { notchesPlugin } from './notches.mjs'
|
||||
import { pleatPlugin } from './pleat.mjs'
|
||||
import { scaleboxPlugin } from './scalebox.mjs'
|
||||
import { sewtogetherPlugin } from './sewtogether.mjs'
|
||||
|
||||
const annotationPlugins = [
|
||||
bartackPlugin,
|
||||
buttonsPlugin,
|
||||
crossboxPlugin,
|
||||
cutonfoldPlugin,
|
||||
grainlinePlugin,
|
||||
logoPlugin,
|
||||
notchesPlugin,
|
||||
pleatPlugin,
|
||||
scaleboxPlugin,
|
||||
sewtogetherPlugin,
|
||||
]
|
||||
|
||||
function annotationHooks() {
|
||||
const hooks = {}
|
||||
for (const plugin of annotationPlugins) {
|
||||
for (const i in plugin.hooks) {
|
||||
if (typeof hooks[i] === 'undefined') hooks[i] = []
|
||||
const hook = plugin.hooks[i]
|
||||
if (typeof hook === 'function') hooks[i].push(hook)
|
||||
else if (typeof hook === 'object') {
|
||||
for (let method of hook) hooks[i].push(method)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hooks
|
||||
}
|
||||
|
||||
function annotationMacros() {
|
||||
const macros = {}
|
||||
for (const plugin of annotationPlugins) {
|
||||
for (const i in plugin.macros) macros[i] = plugin.macros[i]
|
||||
}
|
||||
|
||||
return macros
|
||||
}
|
||||
// Hooks only
|
||||
import { buttonsHooks } from './buttons.mjs'
|
||||
import { logoHooks } from './logo.mjs'
|
||||
import { notchesHooks } from './notches.mjs'
|
||||
// Macros only
|
||||
import { bartackMacros } from './bartack.mjs'
|
||||
import { crossboxMacros } from './crossbox.mjs'
|
||||
import { scaleboxMacros } from './scalebox.mjs'
|
||||
// Hooks and Macros
|
||||
import { cutonfoldMacros, cutonfoldHooks } from './cutonfold.mjs'
|
||||
import { grainlineMacros, grainlineHooks } from './grainline.mjs'
|
||||
import { pleatMacros, pleatHooks } from './pleat.mjs'
|
||||
import { sewtogetherMacros, sewtogetherHooks } from './sewtogether.mjs'
|
||||
|
||||
export const plugin = {
|
||||
name,
|
||||
version,
|
||||
hooks: annotationHooks(),
|
||||
macros: annotationMacros(),
|
||||
hooks: {
|
||||
preRender: [
|
||||
...buttonsHooks.preRender,
|
||||
...logoHooks.preRender,
|
||||
...notchesHooks.preRender,
|
||||
...cutonfoldHooks.preRender,
|
||||
...grainlineHooks.preRender,
|
||||
...pleatHooks.preRender,
|
||||
...sewtogetherHooks.preRender,
|
||||
],
|
||||
},
|
||||
macros: {
|
||||
...bartackMacros,
|
||||
...crossboxMacros,
|
||||
...scaleboxMacros,
|
||||
...cutonfoldMacros,
|
||||
...grainlineMacros,
|
||||
...pleatMacros,
|
||||
...sewtogetherMacros,
|
||||
},
|
||||
}
|
||||
|
||||
export const annotationPlugin = plugin
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,3 @@
|
|||
import { name, version } from '../data.mjs'
|
||||
|
||||
const markers = `
|
||||
<g id="notch">
|
||||
<circle cy="0" cx="0" r="1.4" class="fill-note" />
|
||||
|
@ -10,16 +8,11 @@ const markers = `
|
|||
<circle cy="0" cx="0" r="2.8" class="note" />
|
||||
</g>`
|
||||
|
||||
export const notches = {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: function (svg) {
|
||||
// Export hooks
|
||||
export const notchesHooks = {
|
||||
preRender: [
|
||||
function (svg) {
|
||||
if (svg.defs.indexOf(`id="notch"`) === -1) svg.defs += markers
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
// More specifically named exports
|
||||
export const notchesPlugin = notches
|
||||
export const pluginNotches = notches
|
||||
|
|
|
@ -1,76 +1,71 @@
|
|||
import { name, version } from '../data.mjs'
|
||||
|
||||
const markers = `
|
||||
<marker id="pleatTo" markerWidth="12" markerHeight="8" orient="auto" refY="4" refX="12">
|
||||
<path class="note fill-note" d="M 12,4 L 0,0 C 2,2 2,6 0,8 z" />
|
||||
</marker>
|
||||
`
|
||||
|
||||
export const pleat = {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: (svg) => {
|
||||
// Export hooks
|
||||
export const pleatHooks = {
|
||||
preRender: [
|
||||
function (svg) {
|
||||
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
||||
},
|
||||
},
|
||||
macros: {
|
||||
pleat: function (so, { points, paths, Path, complete, scale }) {
|
||||
if (so === false) {
|
||||
delete points.pleatFrom
|
||||
delete points.pleatFromIn
|
||||
delete points.pleatTo
|
||||
delete points.pleatToIn
|
||||
delete paths.pleatTo
|
||||
delete paths.pleatFrom
|
||||
delete paths.pleatArrow
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
margin: 35,
|
||||
prefix: 'pleat',
|
||||
reverse: false,
|
||||
...so,
|
||||
}
|
||||
if (complete) {
|
||||
points[so.prefix + 'From'] = so.from
|
||||
points[so.prefix + 'To'] = so.to
|
||||
points[so.prefix + 'FromIn'] = points[so.prefix + 'From'].shift(
|
||||
so.from.shiftTowards(so.to, 0.1).angle(so.from) + 270,
|
||||
so.margin * scale
|
||||
)
|
||||
points[so.prefix + 'ToIn'] = points[so.prefix + 'To'].shift(
|
||||
so.from.shiftTowards(so.to, 0.1).angle(so.to) + 90,
|
||||
so.margin * scale
|
||||
)
|
||||
paths[so.prefix + 'PleatFrom'] = new Path()
|
||||
.move(points[so.prefix + 'From'])
|
||||
.line(points[so.prefix + 'FromIn'])
|
||||
.attr('class', 'note' + (so.reverse ? ' dashed' : ''))
|
||||
paths[so.prefix + 'PleatTo'] = new Path()
|
||||
.move(points[so.prefix + 'To'])
|
||||
.line(points[so.prefix + 'ToIn'])
|
||||
.attr('class', 'note' + (so.reverse ? '' : ' dashed'))
|
||||
paths[so.prefix + 'PleatArrow'] = new Path()
|
||||
.move(
|
||||
points[so.prefix + (so.reverse ? 'To' : 'From')].shiftFractionTowards(
|
||||
points[so.prefix + (so.reverse ? 'ToIn' : 'FromIn')],
|
||||
0.25
|
||||
)
|
||||
)
|
||||
.line(
|
||||
points[so.prefix + (so.reverse ? 'From' : 'To')].shiftFractionTowards(
|
||||
points[so.prefix + (so.reverse ? 'FromIn' : 'ToIn')],
|
||||
0.25
|
||||
)
|
||||
)
|
||||
.attr('class', 'note')
|
||||
.attr('marker-end', 'url(#pleatTo)')
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
// More specifically named exports
|
||||
export const pleatPlugin = pleat
|
||||
export const pluginPleat = pleat
|
||||
// Export macros
|
||||
export const pleatMacros = {
|
||||
pleat: function (so, { points, paths, Path, complete, scale }) {
|
||||
if (so === false) {
|
||||
delete points.pleatFrom
|
||||
delete points.pleatFromIn
|
||||
delete points.pleatTo
|
||||
delete points.pleatToIn
|
||||
delete paths.pleatTo
|
||||
delete paths.pleatFrom
|
||||
delete paths.pleatArrow
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
margin: 35,
|
||||
prefix: 'pleat',
|
||||
reverse: false,
|
||||
...so,
|
||||
}
|
||||
if (complete) {
|
||||
points[so.prefix + 'From'] = so.from
|
||||
points[so.prefix + 'To'] = so.to
|
||||
points[so.prefix + 'FromIn'] = points[so.prefix + 'From'].shift(
|
||||
so.from.shiftTowards(so.to, 0.1).angle(so.from) + 270,
|
||||
so.margin * scale
|
||||
)
|
||||
points[so.prefix + 'ToIn'] = points[so.prefix + 'To'].shift(
|
||||
so.from.shiftTowards(so.to, 0.1).angle(so.to) + 90,
|
||||
so.margin * scale
|
||||
)
|
||||
paths[so.prefix + 'PleatFrom'] = new Path()
|
||||
.move(points[so.prefix + 'From'])
|
||||
.line(points[so.prefix + 'FromIn'])
|
||||
.attr('class', 'note' + (so.reverse ? ' dashed' : ''))
|
||||
paths[so.prefix + 'PleatTo'] = new Path()
|
||||
.move(points[so.prefix + 'To'])
|
||||
.line(points[so.prefix + 'ToIn'])
|
||||
.attr('class', 'note' + (so.reverse ? '' : ' dashed'))
|
||||
paths[so.prefix + 'PleatArrow'] = new Path()
|
||||
.move(
|
||||
points[so.prefix + (so.reverse ? 'To' : 'From')].shiftFractionTowards(
|
||||
points[so.prefix + (so.reverse ? 'ToIn' : 'FromIn')],
|
||||
0.25
|
||||
)
|
||||
)
|
||||
.line(
|
||||
points[so.prefix + (so.reverse ? 'From' : 'To')].shiftFractionTowards(
|
||||
points[so.prefix + (so.reverse ? 'FromIn' : 'ToIn')],
|
||||
0.25
|
||||
)
|
||||
)
|
||||
.attr('class', 'note')
|
||||
.attr('marker-end', 'url(#pleatTo)')
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,297 +1,282 @@
|
|||
import { name, version } from '../data.mjs'
|
||||
// Export macros
|
||||
export const scaleboxMacros = {
|
||||
scalebox: function (so, { store, points, paths, scale, Point, Path }) {
|
||||
// Passing `false` will remove the scalebox
|
||||
if (so === false) {
|
||||
for (let id of [
|
||||
'__scaleboxMetricTopLeft',
|
||||
'__scaleboxMetricTopRight',
|
||||
'__scaleboxMetricBottomRight',
|
||||
'__scaleboxMetricBottomLeft',
|
||||
'__scaleboxImperialTopLeft',
|
||||
'__scaleboxImperialTopRight',
|
||||
'__scaleboxImperialBottomRight',
|
||||
'__scaleboxImperialBottomLeft',
|
||||
'__scaleboxLead',
|
||||
'__scaleboxTitle',
|
||||
'__scaleboxText',
|
||||
'__scaleboxLink',
|
||||
'__scaleboxMetric',
|
||||
'__scaleboxImperial',
|
||||
])
|
||||
delete points[id]
|
||||
for (let id of ['__scaleboxMetric', '__scaleboxImperial']) delete paths[id]
|
||||
return true
|
||||
}
|
||||
|
||||
const markers = `
|
||||
<marker id="pleatTo" markerWidth="12" markerHeight="8" orient="auto" refY="4" refX="12">
|
||||
<path class="note fill-note" d="M 12,4 L 0,0 C 2,2 2,6 0,8 z" />
|
||||
</marker>
|
||||
`
|
||||
// Convert scale to a value between 0 and 9, inclusive.
|
||||
const scaleIndex = Math.round(10 * Math.max(0.1, Math.min(1, scale))) - 1
|
||||
|
||||
export const scalebox = {
|
||||
name,
|
||||
version,
|
||||
macros: {
|
||||
scalebox: function (so, { store, points, paths, scale, Point, Path }) {
|
||||
// Passing `false` will remove the scalebox
|
||||
if (so === false) {
|
||||
for (let id of [
|
||||
'__scaleboxMetricTopLeft',
|
||||
'__scaleboxMetricTopRight',
|
||||
'__scaleboxMetricBottomRight',
|
||||
'__scaleboxMetricBottomLeft',
|
||||
'__scaleboxImperialTopLeft',
|
||||
'__scaleboxImperialTopRight',
|
||||
'__scaleboxImperialBottomRight',
|
||||
'__scaleboxImperialBottomLeft',
|
||||
'__scaleboxLead',
|
||||
'__scaleboxTitle',
|
||||
'__scaleboxText',
|
||||
'__scaleboxLink',
|
||||
'__scaleboxMetric',
|
||||
'__scaleboxImperial',
|
||||
])
|
||||
delete points[id]
|
||||
for (let id of ['__scaleboxMetric', '__scaleboxImperial']) delete paths[id]
|
||||
return true
|
||||
}
|
||||
// Metric width and height in mm and display width and height for each scale index.
|
||||
const metricSizes = [
|
||||
[10, 5, '1cm', '0.5cm'],
|
||||
[20, 10, '2cm', '1cm'],
|
||||
[30, 15, '3cm', '1.5cm'],
|
||||
[40, 20, '4cm', '2cm'],
|
||||
[50, 25, '5cm', '2.5cm'],
|
||||
[60, 30, '6cm', '3cm'],
|
||||
[70, 35, '7cm', '3.5cm'],
|
||||
[80, 40, '8cm', '4cm'],
|
||||
[90, 45, '9cm', '4.5cm'],
|
||||
[100, 50, '10cm', '5cm'],
|
||||
]
|
||||
|
||||
// Convert scale to a value between 0 and 9, inclusive.
|
||||
const scaleIndex = Math.round(10 * Math.max(0.1, Math.min(1, scale))) - 1
|
||||
const metricWidth = metricSizes[scaleIndex][0]
|
||||
const metricHeight = metricSizes[scaleIndex][1]
|
||||
const metricDisplayWidth = metricSizes[scaleIndex][2]
|
||||
const metricDisplayHeight = metricSizes[scaleIndex][3]
|
||||
|
||||
// Metric width and height in mm and display width and height for each scale index.
|
||||
const metricSizes = [
|
||||
[10, 5, '1cm', '0.5cm'],
|
||||
[20, 10, '2cm', '1cm'],
|
||||
[30, 15, '3cm', '1.5cm'],
|
||||
[40, 20, '4cm', '2cm'],
|
||||
[50, 25, '5cm', '2.5cm'],
|
||||
[60, 30, '6cm', '3cm'],
|
||||
[70, 35, '7cm', '3.5cm'],
|
||||
[80, 40, '8cm', '4cm'],
|
||||
[90, 45, '9cm', '4.5cm'],
|
||||
[100, 50, '10cm', '5cm'],
|
||||
// Imperial width and height in mm and display width and heigth for each scale index.
|
||||
const imperialSizes = [
|
||||
[25.4 * 0.5, 25.4 * 0.25, '½″', '¼″'],
|
||||
[25.4 * 0.875, 25.4 * 0.5, '⅞″', '½″'],
|
||||
[25.4 * 1.25, 25.4 * 0.625, '1 ¼″', '⅝″'],
|
||||
[25.4 * 1.625, 25.4 * 0.875, '1 ⅝″', '⅞″'],
|
||||
[25.4 * 2, 25.4 * 1, '2″', '1″'],
|
||||
[25.4 * 2.375, 25.4 * 1.25, '2 ⅜″', '1 ¼″'],
|
||||
[25.4 * 2.875, 25.4 * 1.5, '2 ⅞″', '1 ½″'],
|
||||
[25.4 * 3.25, 25.4 * 1.625, '3 ¼″', '1 ⅝″'],
|
||||
[25.4 * 3.625, 25.4 * 1.875, '3 ⅝″', '1 ⅞″'],
|
||||
[25.4 * 4, 25.4 * 2, '4″', '2″'],
|
||||
]
|
||||
|
||||
const imperialWidth = imperialSizes[scaleIndex][0]
|
||||
const imperialHeight = imperialSizes[scaleIndex][1]
|
||||
const imperialDisplayWidth = imperialSizes[scaleIndex][2]
|
||||
const imperialDisplayHeight = imperialSizes[scaleIndex][3]
|
||||
|
||||
// Box points
|
||||
points.__scaleboxMetricTopLeft = new Point(
|
||||
so.at.x - metricWidth / 2,
|
||||
so.at.y - metricHeight / 2
|
||||
)
|
||||
points.__scaleboxMetricTopRight = new Point(
|
||||
so.at.x + metricWidth / 2,
|
||||
so.at.y - metricHeight / 2
|
||||
)
|
||||
points.__scaleboxMetricBottomLeft = new Point(
|
||||
so.at.x - metricWidth / 2,
|
||||
so.at.y + metricHeight / 2
|
||||
)
|
||||
points.__scaleboxMetricBottomRight = new Point(
|
||||
so.at.x + metricWidth / 2,
|
||||
so.at.y + metricHeight / 2
|
||||
)
|
||||
points.__scaleboxImperialTopLeft = new Point(
|
||||
so.at.x - imperialWidth / 2,
|
||||
so.at.y - imperialHeight / 2
|
||||
)
|
||||
points.__scaleboxImperialTopRight = new Point(
|
||||
so.at.x + imperialWidth / 2,
|
||||
so.at.y - imperialHeight / 2
|
||||
)
|
||||
points.__scaleboxImperialBottomLeft = new Point(
|
||||
so.at.x - imperialWidth / 2,
|
||||
so.at.y + imperialHeight / 2
|
||||
)
|
||||
points.__scaleboxImperialBottomRight = new Point(
|
||||
so.at.x + imperialWidth / 2,
|
||||
so.at.y + imperialHeight / 2
|
||||
)
|
||||
// Text anchor points
|
||||
points.__scaleboxLead = new Point(so.at.x - 45 * scale, so.at.y - 15 * scale)
|
||||
points.__scaleboxTitle = points.__scaleboxLead.shift(-90, 10 * scale)
|
||||
points.__scaleboxText = points.__scaleboxTitle.shift(-90, 12 * scale)
|
||||
points.__scaleboxLink = points.__scaleboxText.shift(-90, 5 * scale)
|
||||
points.__scaleboxMetric = new Point(so.at.x, so.at.y + 20 * scale)
|
||||
points.__scaleboxImperial = new Point(so.at.x, so.at.y + 24 * scale)
|
||||
// Rotation
|
||||
if (so.rotate) {
|
||||
so.rotate = Number(so.rotate)
|
||||
let toRotate = [
|
||||
'__scaleboxMetricTopLeft',
|
||||
'__scaleboxMetricTopRight',
|
||||
'__scaleboxMetricBottomLeft',
|
||||
'__scaleboxMetricBottomRight',
|
||||
'__scaleboxImperialTopLeft',
|
||||
'__scaleboxImperialTopRight',
|
||||
'__scaleboxImperialBottomLeft',
|
||||
'__scaleboxImperialBottomRight',
|
||||
'__scaleboxLead',
|
||||
'__scaleboxTitle',
|
||||
'__scaleboxText',
|
||||
'__scaleboxLink',
|
||||
'__scaleboxMetric',
|
||||
'__scaleboxImperial',
|
||||
]
|
||||
for (let pid of toRotate) points[pid] = points[pid].rotate(so.rotate, so.at)
|
||||
for (let pid of toRotate.slice(8)) {
|
||||
points[pid].attributes.set(
|
||||
'data-text-transform',
|
||||
`rotate(${so.rotate * -1}, ${points[pid].x}, ${points[pid].y})`
|
||||
)
|
||||
}
|
||||
}
|
||||
// Paths
|
||||
paths.__scaleboxImperial = new Path()
|
||||
.attr('class', 'scalebox imperial fill-current')
|
||||
.move(points.__scaleboxImperialTopLeft)
|
||||
.line(points.__scaleboxImperialBottomLeft)
|
||||
.line(points.__scaleboxImperialBottomRight)
|
||||
.line(points.__scaleboxImperialTopRight)
|
||||
.close()
|
||||
paths.__scaleboxMetric = new Path()
|
||||
.attr('class', 'scalebox metric fill-bg')
|
||||
.move(points.__scaleboxMetricTopLeft)
|
||||
.line(points.__scaleboxMetricBottomLeft)
|
||||
.line(points.__scaleboxMetricBottomRight)
|
||||
.line(points.__scaleboxMetricTopRight)
|
||||
.close()
|
||||
// Lead
|
||||
points.__scaleboxLead = points.__scaleboxLead
|
||||
.attr('data-text', so.lead || 'FreeSewing')
|
||||
.attr('data-text-class', 'text-sm')
|
||||
// Title
|
||||
if (so.title) points.__scaleboxTitle.attributes.set('data-text', so.title)
|
||||
else {
|
||||
let name = store.data?.name || 'No Name'
|
||||
if (name.indexOf('@freesewing/') !== -1) name = name.replace('@freesewing/', '')
|
||||
points.__scaleboxTitle = points.__scaleboxTitle
|
||||
.attr('data-text', name)
|
||||
.attr('data-text', 'v' + (store.data?.version || 'No Version'))
|
||||
}
|
||||
points.__scaleboxTitle.attributes.add('data-text-class', 'text-lg')
|
||||
// Text
|
||||
if (typeof so.text === 'string') {
|
||||
points.__scaleboxText.attr('data-text', so.text)
|
||||
} else {
|
||||
points.__scaleboxText.attr('data-text', 'supportFreesewingBecomeAPatron')
|
||||
points.__scaleboxLink = points.__scaleboxLink
|
||||
.attr('data-text', 'freesewing.org/patrons/join')
|
||||
.attr('data-text-class', 'text-sm fill-note')
|
||||
}
|
||||
points.__scaleboxText.attr('data-text-class', 'text-xs').attr('data-text-lineheight', 4)
|
||||
// Instructions
|
||||
points.__scaleboxMetric = points.__scaleboxMetric
|
||||
.attr('data-text', 'theWhiteInsideOfThisBoxShouldMeasure')
|
||||
.attr('data-text', `${metricDisplayWidth}`)
|
||||
.attr('data-text', 'x')
|
||||
.attr('data-text', `${metricDisplayHeight}`)
|
||||
.attr('data-text-class', 'text-xs center')
|
||||
points.__scaleboxImperial = points.__scaleboxImperial
|
||||
.attr('data-text', 'theBlackOutsideOfThisBoxShouldMeasure')
|
||||
.attr('data-text', `${imperialDisplayWidth}`)
|
||||
.attr('data-text', 'x')
|
||||
.attr('data-text', `${imperialDisplayHeight}`)
|
||||
.attr('data-text-class', 'text-xs center ')
|
||||
},
|
||||
miniscale(so, { store, points, paths, scale, Point, Path }) {
|
||||
// Passing `false` will remove the miniscale
|
||||
if (so === false) {
|
||||
for (const id of [
|
||||
'__miniscaleMetricTopLeft',
|
||||
'__miniscaleMetricTopRight',
|
||||
'__miniscaleMetricBottomRight',
|
||||
'__miniscaleMetricBottomLeft',
|
||||
'__miniscaleImperialTopLeft',
|
||||
'__miniscaleImperialTopRight',
|
||||
'__miniscaleImperialBottomRight',
|
||||
'__miniscaleImperialBottomLeft',
|
||||
'__miniscaleMetric',
|
||||
'__miniscaleImperial',
|
||||
])
|
||||
delete points[id]
|
||||
for (const id of ['__miniscaleMetric', '__miniscaleImperial']) delete paths[id]
|
||||
return true
|
||||
}
|
||||
|
||||
const metricWidth = metricSizes[scaleIndex][0]
|
||||
const metricHeight = metricSizes[scaleIndex][1]
|
||||
const metricDisplayWidth = metricSizes[scaleIndex][2]
|
||||
const metricDisplayHeight = metricSizes[scaleIndex][3]
|
||||
// Convert scale to a value between 0 and 5, inclusive.
|
||||
const scaleIndex = Math.ceil(6 * Math.max(0.1, Math.min(1, scale))) - 1
|
||||
|
||||
// Imperial width and height in mm and display width and heigth for each scale index.
|
||||
const imperialSizes = [
|
||||
[25.4 * 0.5, 25.4 * 0.25, '½″', '¼″'],
|
||||
[25.4 * 0.875, 25.4 * 0.5, '⅞″', '½″'],
|
||||
[25.4 * 1.25, 25.4 * 0.625, '1 ¼″', '⅝″'],
|
||||
[25.4 * 1.625, 25.4 * 0.875, '1 ⅝″', '⅞″'],
|
||||
[25.4 * 2, 25.4 * 1, '2″', '1″'],
|
||||
[25.4 * 2.375, 25.4 * 1.25, '2 ⅜″', '1 ¼″'],
|
||||
[25.4 * 2.875, 25.4 * 1.5, '2 ⅞″', '1 ½″'],
|
||||
[25.4 * 3.25, 25.4 * 1.625, '3 ¼″', '1 ⅝″'],
|
||||
[25.4 * 3.625, 25.4 * 1.875, '3 ⅝″', '1 ⅞″'],
|
||||
[25.4 * 4, 25.4 * 2, '4″', '2″'],
|
||||
// Metric size in mm / display value and imperial size in mm / display value for each scale index.
|
||||
const sizes = [
|
||||
[10, '1cm', 25.4 * 0.375, '⅜″'],
|
||||
[13, '1.3cm', 25.4 * 0.5, '½″'],
|
||||
[16, '1.6cm', 25.4 * 0.625, '⅝″'],
|
||||
[19, '1.9cm', 25.4 * 0.75, '¾″'],
|
||||
[22, '2.2cm', 25.4 * 0.875, '⅞″'],
|
||||
[25, '2.5cm', 25.4 * 1, '1″'],
|
||||
]
|
||||
const m = sizes[scaleIndex][0] / 2
|
||||
const i = sizes[scaleIndex][2] / 2
|
||||
const metricDisplaySize = sizes[scaleIndex][1]
|
||||
const imperialDisplaySize = sizes[scaleIndex][3]
|
||||
// Box points
|
||||
points.__miniscaleMetricTopLeft = new Point(so.at.x - m, so.at.y - m)
|
||||
points.__miniscaleMetricTopRight = new Point(so.at.x + m, so.at.y - m)
|
||||
points.__miniscaleMetricBottomLeft = new Point(so.at.x - m, so.at.y + m)
|
||||
points.__miniscaleMetricBottomRight = new Point(so.at.x + m, so.at.y + m)
|
||||
points.__miniscaleImperialTopLeft = new Point(so.at.x - i, so.at.y - i)
|
||||
points.__miniscaleImperialTopRight = new Point(so.at.x + i, so.at.y - i)
|
||||
points.__miniscaleImperialBottomLeft = new Point(so.at.x - i, so.at.y + i)
|
||||
points.__miniscaleImperialBottomRight = new Point(so.at.x + i, so.at.y + i)
|
||||
// Text anchor points
|
||||
points.__miniscaleMetric = new Point(so.at.x, so.at.y - 2 * scale)
|
||||
points.__miniscaleImperial = new Point(so.at.x, so.at.y + 8 * scale)
|
||||
// Rotation
|
||||
if (so.rotate) {
|
||||
so.rotate = Number(so.rotate)
|
||||
let toRotate = [
|
||||
'__miniscaleMetricTopLeft',
|
||||
'__miniscaleMetricTopRight',
|
||||
'__miniscaleMetricBottomLeft',
|
||||
'__miniscaleMetricBottomRight',
|
||||
'__miniscaleImperialTopLeft',
|
||||
'__miniscaleImperialTopRight',
|
||||
'__miniscaleImperialBottomLeft',
|
||||
'__miniscaleImperialBottomRight',
|
||||
'__miniscaleMetric',
|
||||
'__miniscaleImperial',
|
||||
]
|
||||
|
||||
const imperialWidth = imperialSizes[scaleIndex][0]
|
||||
const imperialHeight = imperialSizes[scaleIndex][1]
|
||||
const imperialDisplayWidth = imperialSizes[scaleIndex][2]
|
||||
const imperialDisplayHeight = imperialSizes[scaleIndex][3]
|
||||
|
||||
// Box points
|
||||
points.__scaleboxMetricTopLeft = new Point(
|
||||
so.at.x - metricWidth / 2,
|
||||
so.at.y - metricHeight / 2
|
||||
)
|
||||
points.__scaleboxMetricTopRight = new Point(
|
||||
so.at.x + metricWidth / 2,
|
||||
so.at.y - metricHeight / 2
|
||||
)
|
||||
points.__scaleboxMetricBottomLeft = new Point(
|
||||
so.at.x - metricWidth / 2,
|
||||
so.at.y + metricHeight / 2
|
||||
)
|
||||
points.__scaleboxMetricBottomRight = new Point(
|
||||
so.at.x + metricWidth / 2,
|
||||
so.at.y + metricHeight / 2
|
||||
)
|
||||
points.__scaleboxImperialTopLeft = new Point(
|
||||
so.at.x - imperialWidth / 2,
|
||||
so.at.y - imperialHeight / 2
|
||||
)
|
||||
points.__scaleboxImperialTopRight = new Point(
|
||||
so.at.x + imperialWidth / 2,
|
||||
so.at.y - imperialHeight / 2
|
||||
)
|
||||
points.__scaleboxImperialBottomLeft = new Point(
|
||||
so.at.x - imperialWidth / 2,
|
||||
so.at.y + imperialHeight / 2
|
||||
)
|
||||
points.__scaleboxImperialBottomRight = new Point(
|
||||
so.at.x + imperialWidth / 2,
|
||||
so.at.y + imperialHeight / 2
|
||||
)
|
||||
// Text anchor points
|
||||
points.__scaleboxLead = new Point(so.at.x - 45 * scale, so.at.y - 15 * scale)
|
||||
points.__scaleboxTitle = points.__scaleboxLead.shift(-90, 10 * scale)
|
||||
points.__scaleboxText = points.__scaleboxTitle.shift(-90, 12 * scale)
|
||||
points.__scaleboxLink = points.__scaleboxText.shift(-90, 5 * scale)
|
||||
points.__scaleboxMetric = new Point(so.at.x, so.at.y + 20 * scale)
|
||||
points.__scaleboxImperial = new Point(so.at.x, so.at.y + 24 * scale)
|
||||
// Rotation
|
||||
if (so.rotate) {
|
||||
so.rotate = Number(so.rotate)
|
||||
let toRotate = [
|
||||
'__scaleboxMetricTopLeft',
|
||||
'__scaleboxMetricTopRight',
|
||||
'__scaleboxMetricBottomLeft',
|
||||
'__scaleboxMetricBottomRight',
|
||||
'__scaleboxImperialTopLeft',
|
||||
'__scaleboxImperialTopRight',
|
||||
'__scaleboxImperialBottomLeft',
|
||||
'__scaleboxImperialBottomRight',
|
||||
'__scaleboxLead',
|
||||
'__scaleboxTitle',
|
||||
'__scaleboxText',
|
||||
'__scaleboxLink',
|
||||
'__scaleboxMetric',
|
||||
'__scaleboxImperial',
|
||||
]
|
||||
for (let pid of toRotate) points[pid] = points[pid].rotate(so.rotate, so.at)
|
||||
for (let pid of toRotate.slice(8)) {
|
||||
points[pid].attributes.set(
|
||||
'data-text-transform',
|
||||
`rotate(${so.rotate * -1}, ${points[pid].x}, ${points[pid].y})`
|
||||
)
|
||||
}
|
||||
for (const pid of toRotate) points[pid] = points[pid].rotate(so.rotate, so.at)
|
||||
for (const pid of toRotate.slice(8)) {
|
||||
points[pid].attributes.set(
|
||||
'data-text-transform',
|
||||
`rotate(${so.rotate * -1}, ${points[pid].x}, ${points[pid].y})`
|
||||
)
|
||||
}
|
||||
// Paths
|
||||
paths.__scaleboxImperial = new Path()
|
||||
.attr('class', 'scalebox imperial fill-current')
|
||||
.move(points.__scaleboxImperialTopLeft)
|
||||
.line(points.__scaleboxImperialBottomLeft)
|
||||
.line(points.__scaleboxImperialBottomRight)
|
||||
.line(points.__scaleboxImperialTopRight)
|
||||
.close()
|
||||
paths.__scaleboxMetric = new Path()
|
||||
.attr('class', 'scalebox metric fill-bg')
|
||||
.move(points.__scaleboxMetricTopLeft)
|
||||
.line(points.__scaleboxMetricBottomLeft)
|
||||
.line(points.__scaleboxMetricBottomRight)
|
||||
.line(points.__scaleboxMetricTopRight)
|
||||
.close()
|
||||
// Lead
|
||||
points.__scaleboxLead = points.__scaleboxLead
|
||||
.attr('data-text', so.lead || 'FreeSewing')
|
||||
.attr('data-text-class', 'text-sm')
|
||||
// Title
|
||||
if (so.title) points.__scaleboxTitle.attributes.set('data-text', so.title)
|
||||
else {
|
||||
let name = store.data?.name || 'No Name'
|
||||
if (name.indexOf('@freesewing/') !== -1) name = name.replace('@freesewing/', '')
|
||||
points.__scaleboxTitle = points.__scaleboxTitle
|
||||
.attr('data-text', name)
|
||||
.attr('data-text', 'v' + (store.data?.version || 'No Version'))
|
||||
}
|
||||
points.__scaleboxTitle.attributes.add('data-text-class', 'text-lg')
|
||||
// Text
|
||||
if (typeof so.text === 'string') {
|
||||
points.__scaleboxText.attr('data-text', so.text)
|
||||
} else {
|
||||
points.__scaleboxText.attr('data-text', 'supportFreesewingBecomeAPatron')
|
||||
points.__scaleboxLink = points.__scaleboxLink
|
||||
.attr('data-text', 'freesewing.org/patrons/join')
|
||||
.attr('data-text-class', 'text-sm fill-note')
|
||||
}
|
||||
points.__scaleboxText.attr('data-text-class', 'text-xs').attr('data-text-lineheight', 4)
|
||||
// Instructions
|
||||
points.__scaleboxMetric = points.__scaleboxMetric
|
||||
.attr('data-text', 'theWhiteInsideOfThisBoxShouldMeasure')
|
||||
.attr('data-text', `${metricDisplayWidth}`)
|
||||
.attr('data-text', 'x')
|
||||
.attr('data-text', `${metricDisplayHeight}`)
|
||||
.attr('data-text-class', 'text-xs center')
|
||||
points.__scaleboxImperial = points.__scaleboxImperial
|
||||
.attr('data-text', 'theBlackOutsideOfThisBoxShouldMeasure')
|
||||
.attr('data-text', `${imperialDisplayWidth}`)
|
||||
.attr('data-text', 'x')
|
||||
.attr('data-text', `${imperialDisplayHeight}`)
|
||||
.attr('data-text-class', 'text-xs center ')
|
||||
},
|
||||
miniscale(so, { store, points, paths, scale, Point, Path }) {
|
||||
// Passing `false` will remove the miniscale
|
||||
if (so === false) {
|
||||
for (const id of [
|
||||
'__miniscaleMetricTopLeft',
|
||||
'__miniscaleMetricTopRight',
|
||||
'__miniscaleMetricBottomRight',
|
||||
'__miniscaleMetricBottomLeft',
|
||||
'__miniscaleImperialTopLeft',
|
||||
'__miniscaleImperialTopRight',
|
||||
'__miniscaleImperialBottomRight',
|
||||
'__miniscaleImperialBottomLeft',
|
||||
'__miniscaleMetric',
|
||||
'__miniscaleImperial',
|
||||
])
|
||||
delete points[id]
|
||||
for (const id of ['__miniscaleMetric', '__miniscaleImperial']) delete paths[id]
|
||||
return true
|
||||
}
|
||||
|
||||
// Convert scale to a value between 0 and 5, inclusive.
|
||||
const scaleIndex = Math.ceil(6 * Math.max(0.1, Math.min(1, scale))) - 1
|
||||
|
||||
// Metric size in mm / display value and imperial size in mm / display value for each scale index.
|
||||
const sizes = [
|
||||
[10, '1cm', 25.4 * 0.375, '⅜″'],
|
||||
[13, '1.3cm', 25.4 * 0.5, '½″'],
|
||||
[16, '1.6cm', 25.4 * 0.625, '⅝″'],
|
||||
[19, '1.9cm', 25.4 * 0.75, '¾″'],
|
||||
[22, '2.2cm', 25.4 * 0.875, '⅞″'],
|
||||
[25, '2.5cm', 25.4 * 1, '1″'],
|
||||
]
|
||||
const m = sizes[scaleIndex][0] / 2
|
||||
const i = sizes[scaleIndex][2] / 2
|
||||
const metricDisplaySize = sizes[scaleIndex][1]
|
||||
const imperialDisplaySize = sizes[scaleIndex][3]
|
||||
// Box points
|
||||
points.__miniscaleMetricTopLeft = new Point(so.at.x - m, so.at.y - m)
|
||||
points.__miniscaleMetricTopRight = new Point(so.at.x + m, so.at.y - m)
|
||||
points.__miniscaleMetricBottomLeft = new Point(so.at.x - m, so.at.y + m)
|
||||
points.__miniscaleMetricBottomRight = new Point(so.at.x + m, so.at.y + m)
|
||||
points.__miniscaleImperialTopLeft = new Point(so.at.x - i, so.at.y - i)
|
||||
points.__miniscaleImperialTopRight = new Point(so.at.x + i, so.at.y - i)
|
||||
points.__miniscaleImperialBottomLeft = new Point(so.at.x - i, so.at.y + i)
|
||||
points.__miniscaleImperialBottomRight = new Point(so.at.x + i, so.at.y + i)
|
||||
// Text anchor points
|
||||
points.__miniscaleMetric = new Point(so.at.x, so.at.y - 2 * scale)
|
||||
points.__miniscaleImperial = new Point(so.at.x, so.at.y + 8 * scale)
|
||||
// Rotation
|
||||
if (so.rotate) {
|
||||
so.rotate = Number(so.rotate)
|
||||
let toRotate = [
|
||||
'__miniscaleMetricTopLeft',
|
||||
'__miniscaleMetricTopRight',
|
||||
'__miniscaleMetricBottomLeft',
|
||||
'__miniscaleMetricBottomRight',
|
||||
'__miniscaleImperialTopLeft',
|
||||
'__miniscaleImperialTopRight',
|
||||
'__miniscaleImperialBottomLeft',
|
||||
'__miniscaleImperialBottomRight',
|
||||
'__miniscaleMetric',
|
||||
'__miniscaleImperial',
|
||||
]
|
||||
for (const pid of toRotate) points[pid] = points[pid].rotate(so.rotate, so.at)
|
||||
for (const pid of toRotate.slice(8)) {
|
||||
points[pid].attributes.set(
|
||||
'data-text-transform',
|
||||
`rotate(${so.rotate * -1}, ${points[pid].x}, ${points[pid].y})`
|
||||
)
|
||||
}
|
||||
}
|
||||
// Paths
|
||||
paths.__miniscaleImperial = new Path()
|
||||
.attr('class', 'scalebox imperial fill-current')
|
||||
.move(points.__miniscaleImperialTopLeft)
|
||||
.line(points.__miniscaleImperialBottomLeft)
|
||||
.line(points.__miniscaleImperialBottomRight)
|
||||
.line(points.__miniscaleImperialTopRight)
|
||||
.close()
|
||||
paths.__miniscaleMetric = new Path()
|
||||
.attr('class', 'scalebox metric fill-bg')
|
||||
.move(points.__miniscaleMetricTopLeft)
|
||||
.line(points.__miniscaleMetricBottomLeft)
|
||||
.line(points.__miniscaleMetricBottomRight)
|
||||
.line(points.__miniscaleMetricTopRight)
|
||||
.close()
|
||||
// Text
|
||||
points.__miniscaleMetric = points.__miniscaleMetric
|
||||
.attr('data-text', `${metricDisplaySize} x ${metricDisplaySize}`)
|
||||
.attr('data-text-class', 'text-xs center')
|
||||
points.__miniscaleImperial = points.__miniscaleImperial
|
||||
.attr('data-text', `${imperialDisplaySize} x ${imperialDisplaySize}`)
|
||||
.attr('data-text-class', 'text-xs center ')
|
||||
},
|
||||
}
|
||||
// Paths
|
||||
paths.__miniscaleImperial = new Path()
|
||||
.attr('class', 'scalebox imperial fill-current')
|
||||
.move(points.__miniscaleImperialTopLeft)
|
||||
.line(points.__miniscaleImperialBottomLeft)
|
||||
.line(points.__miniscaleImperialBottomRight)
|
||||
.line(points.__miniscaleImperialTopRight)
|
||||
.close()
|
||||
paths.__miniscaleMetric = new Path()
|
||||
.attr('class', 'scalebox metric fill-bg')
|
||||
.move(points.__miniscaleMetricTopLeft)
|
||||
.line(points.__miniscaleMetricBottomLeft)
|
||||
.line(points.__miniscaleMetricBottomRight)
|
||||
.line(points.__miniscaleMetricTopRight)
|
||||
.close()
|
||||
// Text
|
||||
points.__miniscaleMetric = points.__miniscaleMetric
|
||||
.attr('data-text', `${metricDisplaySize} x ${metricDisplaySize}`)
|
||||
.attr('data-text-class', 'text-xs center')
|
||||
points.__miniscaleImperial = points.__miniscaleImperial
|
||||
.attr('data-text', `${imperialDisplaySize} x ${imperialDisplaySize}`)
|
||||
.attr('data-text-class', 'text-xs center ')
|
||||
},
|
||||
}
|
||||
|
||||
// More specifically named exports
|
||||
export const scaleboxPlugin = scalebox
|
||||
export const pluginScalebox = scalebox
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { name, version } from '../data.mjs'
|
||||
|
||||
const markers = `
|
||||
<marker id="sewTogetherStart" markerWidth="4" markerHeight="4" orient="auto" refX="0" refY="2">
|
||||
<path class="note stroke-sm" d="M4,4 L0,2 4,0" />
|
||||
|
@ -12,83 +10,80 @@ const markers = `
|
|||
</marker>
|
||||
`
|
||||
|
||||
export const sewtogether = {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: (svg) => {
|
||||
// Export hooks
|
||||
export const sewtogetherHooks = {
|
||||
preRender: [
|
||||
function (svg) {
|
||||
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
||||
},
|
||||
},
|
||||
macros: {
|
||||
sewtogether: function (so, { points, paths, Path, complete, scale, sa }) {
|
||||
if (so === false) {
|
||||
delete points.sewtogetherFrom
|
||||
delete points.sewtogetherFromCp
|
||||
delete points.sewtogetherMiddle
|
||||
delete points.sewtogetherTo
|
||||
delete points.sewtogetherHinge
|
||||
delete points.sewtogetherToCp
|
||||
delete paths.sewtogetherSewTogetherHinge
|
||||
delete paths.sewtogetherSewTogether
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
prefix: 'sewtogether',
|
||||
...so,
|
||||
}
|
||||
if (complete) {
|
||||
if (null == so.middle) {
|
||||
so.middle = so.from.shiftFractionTowards(so.to, 0.5)
|
||||
}
|
||||
points[so.prefix + 'From'] = so.from
|
||||
points[so.prefix + 'Middle'] = so.middle
|
||||
points[so.prefix + 'To'] = so.to
|
||||
|
||||
points[so.prefix + 'FromCp'] = points[so.prefix + 'From'].shift(
|
||||
points[so.prefix + 'From'].angle(points[so.prefix + 'Middle']) + 90,
|
||||
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']) / 1.5
|
||||
)
|
||||
points[so.prefix + 'ToCp'] = points[so.prefix + 'To'].shift(
|
||||
points[so.prefix + 'To'].angle(points[so.prefix + 'Middle']) - 90,
|
||||
points[so.prefix + 'To'].dist(points[so.prefix + 'Middle']) / 1.5
|
||||
)
|
||||
|
||||
if (so.hinge) {
|
||||
points[so.prefix + 'Hinge'] = points[so.prefix + 'Middle'].shift(
|
||||
points[so.prefix + 'Middle'].angle(points[so.prefix + 'To']) +
|
||||
Math.abs(
|
||||
points[so.prefix + 'Middle'].angle(points[so.prefix + 'From']) -
|
||||
points[so.prefix + 'Middle'].angle(points[so.prefix + 'To'])
|
||||
) /
|
||||
2 +
|
||||
(sa ? 180 : 0),
|
||||
sa
|
||||
? sa
|
||||
: Math.min(
|
||||
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']),
|
||||
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle'])
|
||||
) / 4
|
||||
)
|
||||
paths[so.prefix + 'SewTogetherHinge'] = new Path()
|
||||
.move(points[so.prefix + 'Middle'])
|
||||
.line(points[so.prefix + 'Hinge'])
|
||||
.attr('marker-start', 'url(#sewTogetherCross)')
|
||||
.attr('class', 'dotted note stroke-sm')
|
||||
}
|
||||
paths[so.prefix + 'SewTogether'] = new Path()
|
||||
.move(points[so.prefix + 'From'])
|
||||
.curve(points[so.prefix + 'FromCp'], points[so.prefix + 'ToCp'], points[so.prefix + 'To'])
|
||||
.attr('class', 'dotted note stroke-sm')
|
||||
.attr('marker-start', 'url(#sewTogetherStart)')
|
||||
.attr('marker-end', 'url(#sewTogetherEnd)')
|
||||
.attr('data-text', 'sewTogether')
|
||||
.attr('data-text-class', 'center fill-note text-xs')
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
// More specifically named exports
|
||||
export const sewtogetherPlugin = sewtogether
|
||||
export const pluginSewtogether = sewtogether
|
||||
// Export macros
|
||||
export const sewtogetherMacros = {
|
||||
sewtogether: function (so, { points, paths, Path, complete, scale, sa }) {
|
||||
if (so === false) {
|
||||
delete points.sewtogetherFrom
|
||||
delete points.sewtogetherFromCp
|
||||
delete points.sewtogetherMiddle
|
||||
delete points.sewtogetherTo
|
||||
delete points.sewtogetherHinge
|
||||
delete points.sewtogetherToCp
|
||||
delete paths.sewtogetherSewTogetherHinge
|
||||
delete paths.sewtogetherSewTogether
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
prefix: 'sewtogether',
|
||||
...so,
|
||||
}
|
||||
if (complete) {
|
||||
if (null == so.middle) {
|
||||
so.middle = so.from.shiftFractionTowards(so.to, 0.5)
|
||||
}
|
||||
points[so.prefix + 'From'] = so.from
|
||||
points[so.prefix + 'Middle'] = so.middle
|
||||
points[so.prefix + 'To'] = so.to
|
||||
|
||||
points[so.prefix + 'FromCp'] = points[so.prefix + 'From'].shift(
|
||||
points[so.prefix + 'From'].angle(points[so.prefix + 'Middle']) + 90,
|
||||
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']) / 1.5
|
||||
)
|
||||
points[so.prefix + 'ToCp'] = points[so.prefix + 'To'].shift(
|
||||
points[so.prefix + 'To'].angle(points[so.prefix + 'Middle']) - 90,
|
||||
points[so.prefix + 'To'].dist(points[so.prefix + 'Middle']) / 1.5
|
||||
)
|
||||
|
||||
if (so.hinge) {
|
||||
points[so.prefix + 'Hinge'] = points[so.prefix + 'Middle'].shift(
|
||||
points[so.prefix + 'Middle'].angle(points[so.prefix + 'To']) +
|
||||
Math.abs(
|
||||
points[so.prefix + 'Middle'].angle(points[so.prefix + 'From']) -
|
||||
points[so.prefix + 'Middle'].angle(points[so.prefix + 'To'])
|
||||
) /
|
||||
2 +
|
||||
(sa ? 180 : 0),
|
||||
sa
|
||||
? sa
|
||||
: Math.min(
|
||||
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']),
|
||||
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle'])
|
||||
) / 4
|
||||
)
|
||||
paths[so.prefix + 'SewTogetherHinge'] = new Path()
|
||||
.move(points[so.prefix + 'Middle'])
|
||||
.line(points[so.prefix + 'Hinge'])
|
||||
.attr('marker-start', 'url(#sewTogetherCross)')
|
||||
.attr('class', 'dotted note stroke-sm')
|
||||
}
|
||||
paths[so.prefix + 'SewTogether'] = new Path()
|
||||
.move(points[so.prefix + 'From'])
|
||||
.curve(points[so.prefix + 'FromCp'], points[so.prefix + 'ToCp'], points[so.prefix + 'To'])
|
||||
.attr('class', 'dotted note stroke-sm')
|
||||
.attr('marker-start', 'url(#sewTogetherStart)')
|
||||
.attr('marker-end', 'url(#sewTogetherEnd)')
|
||||
.attr('data-text', 'sewTogether')
|
||||
.attr('data-text-class', 'center fill-note text-xs')
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue