commit
This commit is contained in:
parent
3832e15ff1
commit
44b18c682f
32 changed files with 641 additions and 566 deletions
134
plugins/plugin-annotations/src/bartack.mjs
Normal file
134
plugins/plugin-annotations/src/bartack.mjs
Normal file
|
@ -0,0 +1,134 @@
|
|||
import { version, name } from '../data.mjs'
|
||||
|
||||
// Method that draws the actual bartack
|
||||
const drawBartack = (pointList, { Path }) => {
|
||||
let path = new Path().move(pointList.path1[0])
|
||||
for (const i in pointList.path1) {
|
||||
if (pointList.path1[i]) path = path.line(pointList.path1[i])
|
||||
if (pointList.path2[i]) path = path.line(pointList.path2[i])
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
// Helper method to generate the points to draw on later
|
||||
const getPoints = (path, so) => {
|
||||
let path1 = path.offset(so.width / 2)
|
||||
let path2 = path.offset(so.width / -2)
|
||||
let len = path1.length()
|
||||
let len2 = path2.length()
|
||||
|
||||
// Make sure path1 is always the longest one
|
||||
if (len2 > len) {
|
||||
let tmp = path2
|
||||
path2 = path1
|
||||
path1 = tmp
|
||||
len = len2
|
||||
}
|
||||
|
||||
let points = {
|
||||
path1: [path1.start()],
|
||||
path2: [path2.start()],
|
||||
}
|
||||
let steps = Math.ceil((len / so.width) * so.density)
|
||||
for (let i = 1; i < steps; i++) {
|
||||
points.path1.push(path1.shiftFractionAlong((1 / steps) * i))
|
||||
points.path2.push(path2.shiftFractionAlong((1 / steps) * i))
|
||||
}
|
||||
|
||||
return points
|
||||
}
|
||||
|
||||
const bartackPath = (path, so, props) => (path ? drawBartack(getPoints(path, so), props) : null)
|
||||
|
||||
function createBartack(so, props) {
|
||||
const defaults = {
|
||||
width: 3,
|
||||
length: 15,
|
||||
density: 3,
|
||||
angle: 0,
|
||||
prefix: '',
|
||||
suffix: '',
|
||||
anchor: false,
|
||||
path: false,
|
||||
from: false,
|
||||
to: false,
|
||||
start: 0,
|
||||
end: 1,
|
||||
bartackAlong: false,
|
||||
bartackFractionAlong: false,
|
||||
}
|
||||
so = { ...defaults, ...so }
|
||||
|
||||
const { Path, paths } = props
|
||||
|
||||
// Handle negative angle
|
||||
if (so.angle < 0) so.angle = 360 + (so.angle % -360)
|
||||
|
||||
let guide = false
|
||||
|
||||
if (so.anchor)
|
||||
// Anchor + angle + length
|
||||
guide = new Path().move(so.anchor).line(so.anchor.shift(so.angle, so.length))
|
||||
else if (so.from && so.to)
|
||||
// From to
|
||||
guide = new Path().move(so.from).line(so.to)
|
||||
else if (so.path) {
|
||||
// Along path
|
||||
let start = false
|
||||
let end = false
|
||||
if (so.bartackAlong) guide = so.path.clone()
|
||||
else if (so.bartackFractionAlong) {
|
||||
if (so.start === so.end) return null
|
||||
if (so.start > so.end) {
|
||||
const newEnd = so.start
|
||||
so.start = so.end
|
||||
so.end = newEnd
|
||||
}
|
||||
if (so.start > 0) start = so.path.shiftFractionAlong(so.start)
|
||||
if (so.end < 1) end = so.path.shiftFractionAlong(so.end)
|
||||
if (start && end) guide = so.path.split(start).pop().split(end).shift()
|
||||
else if (start) guide = so.path.split(start).pop()
|
||||
else if (end) guide = so.path.split(end).shift()
|
||||
else guide = so.path.clone()
|
||||
}
|
||||
}
|
||||
|
||||
paths[`${so.prefix}bartack${so.suffix}`] = bartackPath(guide, so, props).attr(
|
||||
'class',
|
||||
'stroke-sm stroke-mark'
|
||||
)
|
||||
|
||||
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)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// More specifically named exports
|
||||
// export const bartackPlugin = bartack
|
||||
// export const pluginBartack = bartack
|
62
plugins/plugin-annotations/src/crossbox.mjs
Normal file
62
plugins/plugin-annotations/src/crossbox.mjs
Normal file
|
@ -0,0 +1,62 @@
|
|||
import { name, version } from '../data.mjs'
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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 cutonfoldPlugin = cutonfold
|
||||
// export const pluginCutonfold = cutonfold
|
71
plugins/plugin-annotations/src/cutonfold.mjs
Normal file
71
plugins/plugin-annotations/src/cutonfold.mjs
Normal file
|
@ -0,0 +1,71 @@
|
|||
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" />
|
||||
</marker>
|
||||
<marker orient="auto" refY="4.0" refX="12.0" id="cutonfoldTo" style="overflow:visible;" markerWidth="12" markerHeight="8">
|
||||
<path class="note fill-note" d="M 12,4 L 0,0 C 2,2 2,6 0,8 z" />
|
||||
</marker>
|
||||
`
|
||||
|
||||
export const cutonfold = {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: (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,
|
||||
}
|
||||
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
|
22
plugins/plugin-annotations/src/index.mjs
Normal file
22
plugins/plugin-annotations/src/index.mjs
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { bartack } from './bartack.mjs'
|
||||
import { crossbox } from './crossbox.mjs'
|
||||
import { cutonfold } from './cutonfold.mjs'
|
||||
import { pleat } from './pleat.mjs'
|
||||
import { sewtogether } from './sewtogether.mjs'
|
||||
|
||||
// Named exports
|
||||
// export bartack
|
||||
export const bartackPlugin = bartack
|
||||
export const pluginBartack = bartack
|
||||
|
||||
export const crossboxPlugin = crossbox
|
||||
export const pluginCrossbox = crossbox
|
||||
|
||||
export const cutonfoldPlugin = cutonfold
|
||||
export const pluginCutonfold = cutonfold
|
||||
|
||||
export const pleatPlugin = pleat
|
||||
export const pluginPleat = pleat
|
||||
|
||||
export const sewtogetherPlugin = sewtogether
|
||||
export const pluginSewtogether = sewtogether
|
76
plugins/plugin-annotations/src/pleat.mjs
Normal file
76
plugins/plugin-annotations/src/pleat.mjs
Normal file
|
@ -0,0 +1,76 @@
|
|||
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 plugin = {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: (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 = plugin
|
||||
// export const pluginPleat = plugin
|
94
plugins/plugin-annotations/src/sewtogether.mjs
Normal file
94
plugins/plugin-annotations/src/sewtogether.mjs
Normal file
|
@ -0,0 +1,94 @@
|
|||
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" />
|
||||
</marker>
|
||||
<marker id="sewTogetherEnd" markerWidth="4" markerHeight="4" orient="auto" refX="4" refY="2">
|
||||
<path class="note stroke-sm" d="M0,0 L4,2 0,4" />
|
||||
</marker>
|
||||
<marker id="sewTogetherCross" markerWidth="4" markerHeight="4" orient="auto" refX="2" refY="2">
|
||||
<path d="M 0,0 L 4,4 M 4,0 L 0,4" class="note stroke-sm"/>
|
||||
</marker>
|
||||
`
|
||||
|
||||
export const plugin = {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: (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 = plugin
|
||||
// export const pluginSewtogether = plugin
|
Loading…
Add table
Add a link
Reference in a new issue