Compare commits
No commits in common. "9f75631d582b11f0ab85f98f18cf348b61749bf3" and "ac6020cb8eb3a7ab82beb5f17c689b2ee1415ccd" have entirely different histories.
9f75631d58
...
ac6020cb8e
@ -6,6 +6,7 @@ from api import uploads
|
|||||||
default_pattern = {
|
default_pattern = {
|
||||||
'warp': {
|
'warp': {
|
||||||
'shafts': 8,
|
'shafts': 8,
|
||||||
|
'threads': 100,
|
||||||
'threading': [{'shaft': 0}] * 100,
|
'threading': [{'shaft': 0}] * 100,
|
||||||
'defaultColour': '178,53,111',
|
'defaultColour': '178,53,111',
|
||||||
'defaultSpacing': 1,
|
'defaultSpacing': 1,
|
||||||
@ -13,6 +14,7 @@ default_pattern = {
|
|||||||
},
|
},
|
||||||
'weft': {
|
'weft': {
|
||||||
'treadles': 8,
|
'treadles': 8,
|
||||||
|
'threads': 50,
|
||||||
'treadling': [{'treadle': 0}] * 50,
|
'treadling': [{'treadle': 0}] * 50,
|
||||||
'defaultColour': '53,69,178',
|
'defaultColour': '53,69,178',
|
||||||
'defaultSpacing': 1,
|
'defaultSpacing': 1,
|
||||||
|
@ -62,7 +62,7 @@ def dumps(obj):
|
|||||||
wif.append('\n[WARP]')
|
wif.append('\n[WARP]')
|
||||||
wif.append('Units=centimeters')
|
wif.append('Units=centimeters')
|
||||||
wif.append('Color={0}'.format(get_colour_index(obj['pattern']['colours'], obj['pattern']['warp']['defaultColour'])))
|
wif.append('Color={0}'.format(get_colour_index(obj['pattern']['colours'], obj['pattern']['warp']['defaultColour'])))
|
||||||
wif.append('Threads={0}'.format(len(obj['pattern']['warp']['threading'])))
|
wif.append('Threads={0}'.format(obj['pattern']['warp']['threads']))
|
||||||
wif.append('Spacing=0.212')
|
wif.append('Spacing=0.212')
|
||||||
wif.append('Thickness=0.212')
|
wif.append('Thickness=0.212')
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ def dumps(obj):
|
|||||||
wif.append('\n[WEFT]')
|
wif.append('\n[WEFT]')
|
||||||
wif.append('Units=centimeters')
|
wif.append('Units=centimeters')
|
||||||
wif.append('Color={0}'.format(get_colour_index(obj['pattern']['colours'], obj['pattern']['weft']['defaultColour'])))
|
wif.append('Color={0}'.format(get_colour_index(obj['pattern']['colours'], obj['pattern']['weft']['defaultColour'])))
|
||||||
wif.append('Threads={0}'.format(len(obj['pattern']['weft']['treadling'])))
|
wif.append('Threads={0}'.format(obj['pattern']['weft']['threads']))
|
||||||
wif.append('Spacing=0.212')
|
wif.append('Spacing=0.212')
|
||||||
wif.append('Thickness=0.212')
|
wif.append('Thickness=0.212')
|
||||||
|
|
||||||
@ -151,6 +151,7 @@ def loads(wif_file):
|
|||||||
while int(x) >= len(draft['warp']['threading']) - 1:
|
while int(x) >= len(draft['warp']['threading']) - 1:
|
||||||
draft['warp']['threading'].append({'shaft': 0})
|
draft['warp']['threading'].append({'shaft': 0})
|
||||||
draft['warp']['threading'][int(x) - 1] = {'shaft': shaft}
|
draft['warp']['threading'][int(x) - 1] = {'shaft': shaft}
|
||||||
|
draft['warp']['threads'] = len(draft['warp']['threading'])
|
||||||
try:
|
try:
|
||||||
warp_colours = config['warp colors']
|
warp_colours = config['warp colors']
|
||||||
for x in warp_colours:
|
for x in warp_colours:
|
||||||
@ -179,6 +180,7 @@ def loads(wif_file):
|
|||||||
while int(x) >= len(draft['weft']['treadling']) - 1:
|
while int(x) >= len(draft['weft']['treadling']) - 1:
|
||||||
draft['weft']['treadling'].append({'treadle': 0})
|
draft['weft']['treadling'].append({'treadle': 0})
|
||||||
draft['weft']['treadling'][int(x) - 1] = {'treadle': shaft}
|
draft['weft']['treadling'][int(x) - 1] = {'treadle': shaft}
|
||||||
|
draft['weft']['threads'] = len(draft['weft']['treadling'])
|
||||||
try:
|
try:
|
||||||
weft_colours = config['weft colors']
|
weft_colours = config['weft colors']
|
||||||
for x in weft_colours:
|
for x in weft_colours:
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 302 KiB |
Binary file not shown.
Before Width: | Height: | Size: 274 KiB |
@ -91,26 +91,6 @@ To begin, select the **colour** tool, click a colour from the **palette**, and t
|
|||||||
|
|
||||||
As you paint, you'll notice the drawdown update to show your new colours.
|
As you paint, you'll notice the drawdown update to show your new colours.
|
||||||
|
|
||||||
### Selecting and deleting threads
|
|
||||||
|
|
||||||
You can delete threads from the warp and weft.
|
|
||||||
|
|
||||||
First, enable the **select** tool from the toolbox. Once selected, you can click on individual threads, or click and drag along the warp or weft, in order to select threads.
|
|
||||||
|
|
||||||
Once you have threads selected, a button will display to allow you to delete the selected threads.
|
|
||||||
|
|
||||||
![Deleting threads](/images/docs/editing19.png)
|
|
||||||
|
|
||||||
### Inserting threads
|
|
||||||
|
|
||||||
Threads can be inserted at any point along the warp or weft.
|
|
||||||
|
|
||||||
To do so, select the **insert** tool from the toolbox and then click on the thread that you'd like to shift leftwards along the warp or downwards along the weft.
|
|
||||||
|
|
||||||
You'll be asked how many threads you'd like to insert before completing the process.
|
|
||||||
|
|
||||||
![Inserting threads](/images/docs/editing20.png)
|
|
||||||
|
|
||||||
### Configuring your pattern
|
### Configuring your pattern
|
||||||
|
|
||||||
You can rename and adjust the number of **treadles** and **shafts** your pattern uses in the **properties** menu. This information can be changed at any time.
|
You can rename and adjust the number of **treadles** and **shafts** your pattern uses in the **properties** menu. This information can be changed at any time.
|
||||||
|
@ -8,6 +8,8 @@ const StyledDrawdown = styled.canvas`
|
|||||||
border:1px dashed rgb(70,70,70);
|
border:1px dashed rgb(70,70,70);
|
||||||
top: ${props => (props.warp.shafts * props.baseSize) + 20}px;
|
top: ${props => (props.warp.shafts * props.baseSize) + 20}px;
|
||||||
right: ${props => (props.weft.treadles * props.baseSize) + 20}px;
|
right: ${props => (props.weft.treadles * props.baseSize) + 20}px;
|
||||||
|
height: ${props => props.weft.threads * props.baseSize}px;
|
||||||
|
width: ${props => props.warp.threads * props.baseSize}px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Cache
|
// Cache
|
||||||
@ -84,12 +86,10 @@ function Drawdown({ baseSize, warp, weft, tieups }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const warpThreads = warp.threading?.length || 0;
|
|
||||||
const weftThreads = weft.treadling?.length || 0;
|
|
||||||
return (
|
return (
|
||||||
<StyledDrawdown ref={drawdownRef} className="drawdown joyride-drawdown"
|
<StyledDrawdown ref={drawdownRef} className="drawdown joyride-drawdown"
|
||||||
width={warpThreads * baseSize}
|
width={warp.threads * baseSize}
|
||||||
height={weftThreads * baseSize}
|
height={weft.threads * baseSize}
|
||||||
weft={weft} warp={warp} baseSize={baseSize}
|
weft={weft} warp={warp} baseSize={baseSize}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -40,7 +40,7 @@ function Tieups({ cellStyle, warp, weft, tieups, updatePattern, baseSize }) {
|
|||||||
|
|
||||||
const paintTieups = () => {
|
const paintTieups = () => {
|
||||||
const canvas = tieupRef.current;
|
const canvas = tieupRef.current;
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');// , { alpha: false });
|
||||||
|
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Confirm, Header, Select, Segment, Accordion, Grid, Icon, Input, Button, Popup
|
Confirm, Select, Segment, Accordion, Grid, Icon, Input, Button, Popup
|
||||||
} from 'semantic-ui-react';
|
} from 'semantic-ui-react';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
@ -40,7 +40,6 @@ function Tools({ object, pattern, warp, weft, unsaved, saving, baseSize, updateP
|
|||||||
const [activeDrawers, setActiveDrawers] = useState(['properties', 'drawing', 'palette']);
|
const [activeDrawers, setActiveDrawers] = useState(['properties', 'drawing', 'palette']);
|
||||||
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
||||||
const [newColour, setNewColour] = useState('#22194D');
|
const [newColour, setNewColour] = useState('#22194D');
|
||||||
const [selectedThreadCount, setSelectedThreadCount] = useState(0);
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { objectId, username, projectPath } = useParams();
|
const { objectId, username, projectPath } = useParams();
|
||||||
@ -53,15 +52,6 @@ function Tools({ object, pattern, warp, weft, unsaved, saving, baseSize, updateP
|
|||||||
return { project, editor: state.objects.editor };
|
return { project, editor: state.objects.editor };
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!pattern) return;
|
|
||||||
const { warp, weft } = pattern;
|
|
||||||
let selected = 0;
|
|
||||||
selected += warp?.threading?.filter(t => t.isSelected)?.length;
|
|
||||||
selected += weft?.treadling?.filter(t => t.isSelected)?.length;
|
|
||||||
setSelectedThreadCount(selected);
|
|
||||||
}, [pattern]);
|
|
||||||
|
|
||||||
const enableTool = (tool) => {
|
const enableTool = (tool) => {
|
||||||
dispatch(actions.objects.updateEditor({ tool, colour: editor.colour }));
|
dispatch(actions.objects.updateEditor({ tool, colour: editor.colour }));
|
||||||
};
|
};
|
||||||
@ -86,27 +76,6 @@ function Tools({ object, pattern, warp, weft, unsaved, saving, baseSize, updateP
|
|||||||
updatePattern({ weft: { ...weft, treadles: parseInt(event.target.value, 10) || 1 } });
|
updatePattern({ weft: { ...weft, treadles: parseInt(event.target.value, 10) || 1 } });
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteSelectedThreads = () => {
|
|
||||||
const sure = window.confirm('Really delete the selected threads?');
|
|
||||||
if (!sure) return;
|
|
||||||
const newWarp = Object.assign({}, pattern.warp);
|
|
||||||
const newWeft = Object.assign({}, pattern.weft);
|
|
||||||
if (pattern?.warp?.threading) {
|
|
||||||
newWarp.threading = newWarp.threading.filter(t => !t.isSelected);
|
|
||||||
}
|
|
||||||
if (pattern?.weft?.treadling) {
|
|
||||||
newWeft.treadling = newWeft.treadling.filter(t => !t.isSelected);
|
|
||||||
}
|
|
||||||
updatePattern({ warp: newWarp, weft: newWeft });
|
|
||||||
}
|
|
||||||
const deselectThreads = () => {
|
|
||||||
const newWarp = Object.assign({}, pattern.warp);
|
|
||||||
const newWeft = Object.assign({}, pattern.weft);
|
|
||||||
newWarp.threading = newWarp?.threading?.map(t => ({ ...t, isSelected: undefined }));
|
|
||||||
newWeft.treadling = newWeft?.treadling?.map(t => ({ ...t, isSelected: undefined }));
|
|
||||||
updatePattern({ warp: newWarp, weft: newWeft });
|
|
||||||
}
|
|
||||||
|
|
||||||
const onZoomChange = zoom => updatePattern({ baseSize: zoom || 10 });
|
const onZoomChange = zoom => updatePattern({ baseSize: zoom || 10 });
|
||||||
|
|
||||||
const drawerIsActive = drawer => activeDrawers.indexOf(drawer) > -1;
|
const drawerIsActive = drawer => activeDrawers.indexOf(drawer) > -1;
|
||||||
@ -174,16 +143,8 @@ function Tools({ object, pattern, warp, weft, unsaved, saving, baseSize, updateP
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="pattern-toolbox joyride-tools">
|
<div className="pattern-toolbox joyride-tools">
|
||||||
{selectedThreadCount > 0 &&
|
|
||||||
<Segment attached="top">
|
|
||||||
<Header>{selectedThreadCount} threads selected</Header>
|
|
||||||
<Button basic onClick={deselectThreads}>De-select all</Button>
|
|
||||||
<Button color='orange' onClick={deleteSelectedThreads}>Delete threads</Button>
|
|
||||||
</Segment>
|
|
||||||
}
|
|
||||||
|
|
||||||
{unsaved &&
|
{unsaved &&
|
||||||
<Segment attached>
|
<Segment attached="top">
|
||||||
<Button fluid color="teal" icon="save" content="Save pattern" onClick={() => saveObject(/*this.refs.canvas*/)} loading={saving}/>
|
<Button fluid color="teal" icon="save" content="Save pattern" onClick={() => saveObject(/*this.refs.canvas*/)} loading={saving}/>
|
||||||
<Button style={{marginTop: 5}} fluid icon='refresh' content='Undo changes' onClick={revertChanges} />
|
<Button style={{marginTop: 5}} fluid icon='refresh' content='Undo changes' onClick={revertChanges} />
|
||||||
</Segment>
|
</Segment>
|
||||||
@ -253,9 +214,7 @@ function Tools({ object, pattern, warp, weft, unsaved, saving, baseSize, updateP
|
|||||||
<Accordion.Content active={drawerIsActive('drawing')}>
|
<Accordion.Content active={drawerIsActive('drawing')}>
|
||||||
<Button.Group fluid>
|
<Button.Group fluid>
|
||||||
<Button className='joyride-pan' data-tooltip="Pan (drag to move) pattern" color={editor.tool === 'pan' && 'blue'} size="tiny" icon onClick={() => enableTool('pan')}><Icon name="move" /></Button>
|
<Button className='joyride-pan' data-tooltip="Pan (drag to move) pattern" color={editor.tool === 'pan' && 'blue'} size="tiny" icon onClick={() => enableTool('pan')}><Icon name="move" /></Button>
|
||||||
<Button data-tooltip="Select threads" color={editor.tool === 'select' && 'blue'} size="tiny" icon onClick={() => enableTool('select')}><Icon name="i cursor" /></Button>
|
<Button className='joyride-colour' data-tooltip="Paint selected colour" color={editor.tool === 'colour' && 'blue'} size="tiny" icon onClick={() => enableTool('colour')}><Icon name="paint brush" /></Button>
|
||||||
<Button data-tooltip="Insert threads" color={editor.tool === 'insert' && 'blue'} size="tiny" icon onClick={() => enableTool('insert')}><Icon name="plus" /></Button>
|
|
||||||
<Button className='joyride-colour' data-tooltip="Apply thread colour" color={editor.tool === 'colour' && 'blue'} size="tiny" icon onClick={() => enableTool('colour')}><Icon name="paint brush" /></Button>
|
|
||||||
<Button className='joyride-straight' data-tooltip="Straight draw" color={editor.tool === 'straight' && 'blue'} size="tiny" icon onClick={() => enableTool('straight')}>/ /</Button>
|
<Button className='joyride-straight' data-tooltip="Straight draw" color={editor.tool === 'straight' && 'blue'} size="tiny" icon onClick={() => enableTool('straight')}>/ /</Button>
|
||||||
<Button className='joyride-point' data-tooltip="Point draw" color={editor.tool === 'point' && 'blue'} size="tiny" icon onClick={() => enableTool('point')}><Icon name="chevron up" /></Button>
|
<Button className='joyride-point' data-tooltip="Point draw" color={editor.tool === 'point' && 'blue'} size="tiny" icon onClick={() => enableTool('point')}><Icon name="chevron up" /></Button>
|
||||||
</Button.Group>
|
</Button.Group>
|
||||||
|
@ -8,9 +8,8 @@ const StyledWarp = styled.div`
|
|||||||
right:0px;
|
right:0px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: ${props => (props.treadles * props.baseSize) + 20}px;
|
right: ${props => (props.treadles * props.baseSize) + 20}px;
|
||||||
height: ${props => (props.shafts * props.baseSize) + 40}px;
|
height: ${props => (props.shafts * props.baseSize) + 10}px;
|
||||||
width: 100%;
|
width: ${props => (props.threading * props.baseSize) + 10}px;
|
||||||
cursor: ${props => props.tool === 'insert' ? 'w-resize': 'initial'};
|
|
||||||
.warp-colourway td{
|
.warp-colourway td{
|
||||||
border:none;
|
border:none;
|
||||||
border-top:1px solid rgb(150,150,150);
|
border-top:1px solid rgb(150,150,150);
|
||||||
@ -19,7 +18,6 @@ const StyledWarp = styled.div`
|
|||||||
|
|
||||||
const squares = {};
|
const squares = {};
|
||||||
const markers = {};
|
const markers = {};
|
||||||
const selectedMarkers = {};
|
|
||||||
let dragging = false;
|
let dragging = false;
|
||||||
let startShaft = null;
|
let startShaft = null;
|
||||||
let startThread = null;
|
let startThread = null;
|
||||||
@ -156,39 +154,18 @@ function Warp({ baseSize, cellStyle, warp, weft, updatePattern }) {
|
|||||||
if (y > hY || y <= lY) yDirection = 0 - yDirection;
|
if (y > hY || y <= lY) yDirection = 0 - yDirection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (editor.tool === 'select') {
|
|
||||||
while (x <= hX && x >= lX) {
|
|
||||||
newWarp.threading[x].isSelected = true;
|
|
||||||
x += xDirection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updatePattern({ warp: newWarp });
|
updatePattern({ warp: newWarp });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const click = (event) => {
|
const click = (event) => {
|
||||||
const { thread, shaft } = getThreadShaft(event, warpRef.current);
|
|
||||||
if (editor.tool === 'point' || editor.tool === 'straight') {
|
if (editor.tool === 'point' || editor.tool === 'straight') {
|
||||||
|
const { thread, shaft } = getThreadShaft(event, warpRef.current);
|
||||||
const newWarp = Object.assign({}, warp);
|
const newWarp = Object.assign({}, warp);
|
||||||
if (thread > warp.threading.length || warp.threading.length - thread < 5) fillUpTo(newWarp, thread + 5);
|
if (thread > warp.threading.length || warp.threading.length - thread < 5) fillUpTo(newWarp, thread + 5);
|
||||||
const warpThread = newWarp.threading[thread];
|
const warpThread = newWarp.threading[thread];
|
||||||
warpThread.shaft = warpThread.shaft === shaft ? 0 : shaft;
|
warpThread.shaft = warpThread.shaft === shaft ? 0 : shaft;
|
||||||
updatePattern({ warp: newWarp });
|
updatePattern({ warp: newWarp });
|
||||||
}
|
}
|
||||||
if (editor.tool === 'select') {
|
|
||||||
const newWarp = Object.assign({}, warp);
|
|
||||||
const warpThread = newWarp.threading[thread];
|
|
||||||
warpThread.isSelected = !warpThread.isSelected;
|
|
||||||
updatePattern({ warp: newWarp });
|
|
||||||
}
|
|
||||||
if (editor.tool === 'insert') {
|
|
||||||
const number = parseInt(prompt('Enter a number of threads to insert before this point.'));
|
|
||||||
if (number && number > 0) {
|
|
||||||
const newThreads = [...new Array(number)].map(() => ({ shaft: 0 }));
|
|
||||||
const newWarp = Object.assign({}, warp);
|
|
||||||
newWarp.threading?.splice(thread, 0, ...newThreads);
|
|
||||||
updatePattern({ warp: newWarp });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fillUpTo = (w, limit) => {
|
const fillUpTo = (w, limit) => {
|
||||||
@ -211,22 +188,6 @@ function Warp({ baseSize, cellStyle, warp, weft, updatePattern }) {
|
|||||||
markers[size] = m_canvas;
|
markers[size] = m_canvas;
|
||||||
return m_canvas;
|
return m_canvas;
|
||||||
};
|
};
|
||||||
const getSelectedMarker = (size, height) => {
|
|
||||||
const m_canvas = document.createElement('canvas');
|
|
||||||
m_canvas.width = baseSize + 1;
|
|
||||||
m_canvas.height = height;
|
|
||||||
const mc = m_canvas.getContext('2d');
|
|
||||||
mc.fillStyle = 'rgb(233,245,248)';
|
|
||||||
mc.fillRect(0, 1, baseSize, height);
|
|
||||||
mc.moveTo(0, 0);
|
|
||||||
mc.lineTo(baseSize+1, 0);
|
|
||||||
mc.lineTo(baseSize+1, height);
|
|
||||||
mc.lineTo(0, height);
|
|
||||||
mc.lineTo(0, 0);
|
|
||||||
mc.strokeStyle = 'rgb(99,184,205)';
|
|
||||||
mc.stroke();
|
|
||||||
return m_canvas;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSquare = (size, colour) => {
|
const getSquare = (size, colour) => {
|
||||||
if (squares[size] && squares[size][colour]) return squares[size][colour];
|
if (squares[size] && squares[size][colour]) return squares[size][colour];
|
||||||
@ -260,14 +221,9 @@ function Warp({ baseSize, cellStyle, warp, weft, updatePattern }) {
|
|||||||
ctx.strokeStyle = 'rgba(0,0,0,0.3)';
|
ctx.strokeStyle = 'rgba(0,0,0,0.3)';
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
const selectedMarker = getSelectedMarker(baseSize, canvas.height);
|
|
||||||
const marker = getMarker(baseSize);
|
|
||||||
for (let thread = 0; thread < warp.threading.length; thread++) {
|
for (let thread = 0; thread < warp.threading.length; thread++) {
|
||||||
const shaft = warp.threading[thread].shaft;
|
const shaft = warp.threading[thread].shaft;
|
||||||
const isSelected = warp.threading[thread].isSelected;
|
const marker = getMarker(baseSize);
|
||||||
if (isSelected) {
|
|
||||||
ctx.drawImage(selectedMarker, canvas.width - ((thread + 1) * baseSize), 0);
|
|
||||||
}
|
|
||||||
ctx.drawImage(marker, canvas.width - ((thread + 1) * baseSize), canvas.height - (shaft * baseSize));
|
ctx.drawImage(marker, canvas.width - ((thread + 1) * baseSize), canvas.height - (shaft * baseSize));
|
||||||
const colourSquare = getSquare(baseSize, warp.threading[thread].colour || warp.defaultColour);
|
const colourSquare = getSquare(baseSize, warp.threading[thread].colour || warp.defaultColour);
|
||||||
ctx2.drawImage(colourSquare, canvas.width - ((thread + 1) * baseSize), 0);
|
ctx2.drawImage(colourSquare, canvas.width - ((thread + 1) * baseSize), 0);
|
||||||
@ -275,7 +231,7 @@ function Warp({ baseSize, cellStyle, warp, weft, updatePattern }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWarp treadles={weft.treadles} shafts={warp.shafts} baseSize={baseSize} tool={tool}>
|
<StyledWarp treadles={weft.treadles} shafts={warp.shafts} baseSize={baseSize}>
|
||||||
<canvas className='warp-colourway joyride-warpColourway' ref={colourwayRef} width={warp.threading.length * baseSize} height={10}
|
<canvas className='warp-colourway joyride-warpColourway' ref={colourwayRef} width={warp.threading.length * baseSize} height={10}
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute', top: 0, right: 0, height: 10, width: warp.threading.length * baseSize,
|
position: 'absolute', top: 0, right: 0, height: 10, width: warp.threading.length * baseSize,
|
||||||
|
@ -12,7 +12,6 @@ const StyledWeft = styled.div`
|
|||||||
min-height: 1000px;
|
min-height: 1000px;
|
||||||
width: ${props => (props.treadles * props.baseSize)}px;
|
width: ${props => (props.treadles * props.baseSize)}px;
|
||||||
height: ${props => props.threads * props.baseSize}px;
|
height: ${props => props.threads * props.baseSize}px;
|
||||||
cursor: ${props => props.tool === 'insert' ? 's-resize': 'initial'};
|
|
||||||
.weft-colourway{
|
.weft-colourway{
|
||||||
border:none;
|
border:none;
|
||||||
border-right:1px solid rgb(150,150,150);
|
border-right:1px solid rgb(150,150,150);
|
||||||
@ -158,18 +157,12 @@ function Weft({ cellStyle, warp, weft, baseSize, updatePattern }) {
|
|||||||
if (x > hX || x <= lX) xDirection = 0 - xDirection;
|
if (x > hX || x <= lX) xDirection = 0 - xDirection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (editor.tool === 'select') {
|
|
||||||
while (y <= hY && y >= lY) {
|
|
||||||
newWeft.treadling[y - 1].isSelected = true;
|
|
||||||
y += yDirection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updatePattern({ weft: newWeft });
|
updatePattern({ weft: newWeft });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const click = (event) => {
|
const click = (event) => {
|
||||||
let { thread, treadle } = getThreadTreadle(event, weftRef.current);
|
|
||||||
if (editor.tool === 'point' || editor.tool === 'straight') {
|
if (editor.tool === 'point' || editor.tool === 'straight') {
|
||||||
|
let { thread, treadle } = getThreadTreadle(event, weftRef.current);
|
||||||
treadle += 1;
|
treadle += 1;
|
||||||
const newWeft = Object.assign({}, weft);
|
const newWeft = Object.assign({}, weft);
|
||||||
if (thread >= newWeft.treadling.length || newWeft.treadling.length - thread < 5) fillUpTo(newWeft, thread + 5);
|
if (thread >= newWeft.treadling.length || newWeft.treadling.length - thread < 5) fillUpTo(newWeft, thread + 5);
|
||||||
@ -177,21 +170,6 @@ function Weft({ cellStyle, warp, weft, baseSize, updatePattern }) {
|
|||||||
weftThread.treadle = weftThread.treadle === treadle ? 0 : treadle;
|
weftThread.treadle = weftThread.treadle === treadle ? 0 : treadle;
|
||||||
updatePattern({ weft: newWeft });
|
updatePattern({ weft: newWeft });
|
||||||
}
|
}
|
||||||
if (editor.tool === 'select') {
|
|
||||||
const newWeft = Object.assign({}, weft);
|
|
||||||
const weftThread = newWeft.treadling[thread - 1];
|
|
||||||
weftThread.isSelected = !weftThread.isSelected;
|
|
||||||
updatePattern({ weft: newWeft });
|
|
||||||
}
|
|
||||||
if (editor.tool === 'insert') {
|
|
||||||
const number = parseInt(prompt('Enter a number of threads to insert above this point.'));
|
|
||||||
if (number && number > 0) {
|
|
||||||
const newThreads = [...new Array(number)].map(() => ({ treadle: 0 }));
|
|
||||||
const newWeft = Object.assign({}, weft);
|
|
||||||
newWeft.treadling?.splice(thread - 1, 0, ...newThreads);
|
|
||||||
updatePattern({ weft: newWeft });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fillUpTo = (weft, limit) => {
|
const fillUpTo = (weft, limit) => {
|
||||||
@ -214,22 +192,6 @@ function Weft({ cellStyle, warp, weft, baseSize, updatePattern }) {
|
|||||||
markers[size] = m_canvas;
|
markers[size] = m_canvas;
|
||||||
return m_canvas;
|
return m_canvas;
|
||||||
};
|
};
|
||||||
const getSelectedMarker = (size, width) => {
|
|
||||||
const m_canvas = document.createElement('canvas');
|
|
||||||
m_canvas.width = width + 1;
|
|
||||||
m_canvas.height = baseSize;
|
|
||||||
const mc = m_canvas.getContext('2d');
|
|
||||||
mc.fillStyle = 'rgb(233,245,248)';
|
|
||||||
mc.fillRect(0, 1, width, baseSize);
|
|
||||||
mc.moveTo(0, 0);
|
|
||||||
mc.lineTo(width+1, 0);
|
|
||||||
mc.lineTo(width+1, baseSize);
|
|
||||||
mc.lineTo(0, baseSize);
|
|
||||||
mc.lineTo(0, 0);
|
|
||||||
mc.strokeStyle = 'rgb(99,184,205)';
|
|
||||||
mc.stroke();
|
|
||||||
return m_canvas;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSquare = (size, colour) => {
|
const getSquare = (size, colour) => {
|
||||||
if (squares[size] && squares[size][colour]) return squares[size][colour];
|
if (squares[size] && squares[size][colour]) return squares[size][colour];
|
||||||
@ -263,35 +225,29 @@ function Weft({ cellStyle, warp, weft, baseSize, updatePattern }) {
|
|||||||
ctx.strokeStyle = 'rgba(0,0,0,0.3)';
|
ctx.strokeStyle = 'rgba(0,0,0,0.3)';
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
const marker = getMarker(baseSize);
|
for (let thread = 0; thread < weft.threads; thread++) {
|
||||||
const selectedMarker = getSelectedMarker(baseSize, canvas.width);
|
|
||||||
for (let thread = 0; thread < weft.treadling.length; thread++) {
|
|
||||||
const treadle = weft.treadling[thread].treadle;
|
const treadle = weft.treadling[thread].treadle;
|
||||||
const isSelected = weft.treadling[thread].isSelected;
|
const marker = getMarker(baseSize);
|
||||||
if (isSelected) {
|
|
||||||
ctx.drawImage(selectedMarker, 0, ((thread) * baseSize));
|
|
||||||
}
|
|
||||||
ctx.drawImage(marker, ((treadle - 1) * baseSize), ((thread) * baseSize));
|
ctx.drawImage(marker, ((treadle - 1) * baseSize), ((thread) * baseSize));
|
||||||
const colourSquare = getSquare(baseSize, weft.treadling[thread].colour || weft.defaultColour);
|
const colourSquare = getSquare(baseSize, weft.treadling[thread].colour || weft.defaultColour);
|
||||||
ctx2.drawImage(colourSquare, 0, (thread * baseSize));
|
ctx2.drawImage(colourSquare, 0, (thread * baseSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const threadCount = weft.treadling?.length || 0;
|
|
||||||
return (
|
return (
|
||||||
<StyledWeft baseSize={baseSize} treadles={weft.treadles} shafts={warp.shafts} threads={threadCount} tool={tool}>
|
<StyledWeft baseSize={baseSize} treadles={weft.treadles} shafts={warp.shafts} threads={weft.threads}>
|
||||||
<canvas className='weft-colourway' ref={colourwayRef} width={10} height={threadCount * baseSize}
|
<canvas className='weft-colourway' ref={colourwayRef} width={10} height={weft.threads * baseSize}
|
||||||
style={{ position: 'absolute', top: 0, right: 0, width: 10, height: threadCount * baseSize}}
|
style={{ position: 'absolute', top: 0, right: 0, width: 10, height: weft.threads * baseSize}}
|
||||||
onClick={mouseClickColourway}
|
onClick={mouseClickColourway}
|
||||||
onMouseDown={mouseDownColourway}
|
onMouseDown={mouseDownColourway}
|
||||||
onMouseMove={mouseMoveColourway}
|
onMouseMove={mouseMoveColourway}
|
||||||
onMouseUp={mouseUpColourway}
|
onMouseUp={mouseUpColourway}
|
||||||
onMouseLeave={mouseUpColourway}
|
onMouseLeave={mouseUpColourway}
|
||||||
/>
|
/>
|
||||||
<canvas className='weft-threads joyride-weft' ref={weftRef} width={weft.treadles * baseSize} height={threadCount * baseSize}
|
<canvas className='weft-threads joyride-weft' ref={weftRef} width={weft.treadles * baseSize} height={weft.threads * baseSize}
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 0, right: 10, height: threadCount * baseSize, width: weft.treadles * baseSize,
|
top: 0, right: 10, height: weft.threads * baseSize, width: weft.treadles * baseSize,
|
||||||
borderRadius: 4, boxShadow: '0px 0px 10px rgba(0,0,0,0.15)',
|
borderRadius: 4, boxShadow: '0px 0px 10px rgba(0,0,0,0.15)',
|
||||||
}}
|
}}
|
||||||
onClick={click}
|
onClick={click}
|
||||||
|
Loading…
Reference in New Issue
Block a user