Compare commits
11 Commits
ac6020cb8e
...
9f75631d58
Author | SHA1 | Date | |
---|---|---|---|
9f75631d58 | |||
bdb4db100e | |||
e68ebface7 | |||
27e7a11eba | |||
ee5cd5dea5 | |||
55f21bd18e | |||
be5cb2cb12 | |||
d3b9142e4f | |||
21ee690409 | |||
0a56844784 | |||
ee6584a396 |
@ -6,7 +6,6 @@ from api import uploads
|
||||
default_pattern = {
|
||||
'warp': {
|
||||
'shafts': 8,
|
||||
'threads': 100,
|
||||
'threading': [{'shaft': 0}] * 100,
|
||||
'defaultColour': '178,53,111',
|
||||
'defaultSpacing': 1,
|
||||
@ -14,7 +13,6 @@ default_pattern = {
|
||||
},
|
||||
'weft': {
|
||||
'treadles': 8,
|
||||
'threads': 50,
|
||||
'treadling': [{'treadle': 0}] * 50,
|
||||
'defaultColour': '53,69,178',
|
||||
'defaultSpacing': 1,
|
||||
|
@ -62,7 +62,7 @@ def dumps(obj):
|
||||
wif.append('\n[WARP]')
|
||||
wif.append('Units=centimeters')
|
||||
wif.append('Color={0}'.format(get_colour_index(obj['pattern']['colours'], obj['pattern']['warp']['defaultColour'])))
|
||||
wif.append('Threads={0}'.format(obj['pattern']['warp']['threads']))
|
||||
wif.append('Threads={0}'.format(len(obj['pattern']['warp']['threading'])))
|
||||
wif.append('Spacing=0.212')
|
||||
wif.append('Thickness=0.212')
|
||||
|
||||
@ -78,7 +78,7 @@ def dumps(obj):
|
||||
wif.append('\n[WEFT]')
|
||||
wif.append('Units=centimeters')
|
||||
wif.append('Color={0}'.format(get_colour_index(obj['pattern']['colours'], obj['pattern']['weft']['defaultColour'])))
|
||||
wif.append('Threads={0}'.format(obj['pattern']['weft']['threads']))
|
||||
wif.append('Threads={0}'.format(len(obj['pattern']['weft']['treadling'])))
|
||||
wif.append('Spacing=0.212')
|
||||
wif.append('Thickness=0.212')
|
||||
|
||||
@ -151,7 +151,6 @@ def loads(wif_file):
|
||||
while int(x) >= len(draft['warp']['threading']) - 1:
|
||||
draft['warp']['threading'].append({'shaft': 0})
|
||||
draft['warp']['threading'][int(x) - 1] = {'shaft': shaft}
|
||||
draft['warp']['threads'] = len(draft['warp']['threading'])
|
||||
try:
|
||||
warp_colours = config['warp colors']
|
||||
for x in warp_colours:
|
||||
@ -180,7 +179,6 @@ def loads(wif_file):
|
||||
while int(x) >= len(draft['weft']['treadling']) - 1:
|
||||
draft['weft']['treadling'].append({'treadle': 0})
|
||||
draft['weft']['treadling'][int(x) - 1] = {'treadle': shaft}
|
||||
draft['weft']['threads'] = len(draft['weft']['treadling'])
|
||||
try:
|
||||
weft_colours = config['weft colors']
|
||||
for x in weft_colours:
|
||||
|
BIN
web/public/images/docs/editing19.png
Normal file
BIN
web/public/images/docs/editing19.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 302 KiB |
BIN
web/public/images/docs/editing20.png
Normal file
BIN
web/public/images/docs/editing20.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 274 KiB |
@ -91,6 +91,26 @@ 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.
|
||||
|
||||
### 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
|
||||
|
||||
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,8 +8,6 @@ const StyledDrawdown = styled.canvas`
|
||||
border:1px dashed rgb(70,70,70);
|
||||
top: ${props => (props.warp.shafts * 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
|
||||
@ -86,10 +84,12 @@ function Drawdown({ baseSize, warp, weft, tieups }) {
|
||||
}
|
||||
};
|
||||
|
||||
const warpThreads = warp.threading?.length || 0;
|
||||
const weftThreads = weft.treadling?.length || 0;
|
||||
return (
|
||||
<StyledDrawdown ref={drawdownRef} className="drawdown joyride-drawdown"
|
||||
width={warp.threads * baseSize}
|
||||
height={weft.threads * baseSize}
|
||||
width={warpThreads * baseSize}
|
||||
height={weftThreads * baseSize}
|
||||
weft={weft} warp={warp} baseSize={baseSize}
|
||||
/>
|
||||
);
|
||||
|
@ -40,7 +40,7 @@ function Tieups({ cellStyle, warp, weft, tieups, updatePattern, baseSize }) {
|
||||
|
||||
const paintTieups = () => {
|
||||
const canvas = tieupRef.current;
|
||||
const ctx = canvas.getContext('2d');// , { alpha: false });
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Confirm, Select, Segment, Accordion, Grid, Icon, Input, Button, Popup
|
||||
Confirm, Header, Select, Segment, Accordion, Grid, Icon, Input, Button, Popup
|
||||
} from 'semantic-ui-react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
@ -40,6 +40,7 @@ function Tools({ object, pattern, warp, weft, unsaved, saving, baseSize, updateP
|
||||
const [activeDrawers, setActiveDrawers] = useState(['properties', 'drawing', 'palette']);
|
||||
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
||||
const [newColour, setNewColour] = useState('#22194D');
|
||||
const [selectedThreadCount, setSelectedThreadCount] = useState(0);
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
const { objectId, username, projectPath } = useParams();
|
||||
@ -52,6 +53,15 @@ function Tools({ object, pattern, warp, weft, unsaved, saving, baseSize, updateP
|
||||
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) => {
|
||||
dispatch(actions.objects.updateEditor({ tool, colour: editor.colour }));
|
||||
};
|
||||
@ -76,6 +86,27 @@ function Tools({ object, pattern, warp, weft, unsaved, saving, baseSize, updateP
|
||||
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 drawerIsActive = drawer => activeDrawers.indexOf(drawer) > -1;
|
||||
@ -143,8 +174,16 @@ function Tools({ object, pattern, warp, weft, unsaved, saving, baseSize, updateP
|
||||
|
||||
return (
|
||||
<div className="pattern-toolbox joyride-tools">
|
||||
{unsaved &&
|
||||
{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 &&
|
||||
<Segment attached>
|
||||
<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} />
|
||||
</Segment>
|
||||
@ -214,7 +253,9 @@ function Tools({ object, pattern, warp, weft, unsaved, saving, baseSize, updateP
|
||||
<Accordion.Content active={drawerIsActive('drawing')}>
|
||||
<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-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="Select threads" color={editor.tool === 'select' && 'blue'} size="tiny" icon onClick={() => enableTool('select')}><Icon name="i cursor" /></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-point' data-tooltip="Point draw" color={editor.tool === 'point' && 'blue'} size="tiny" icon onClick={() => enableTool('point')}><Icon name="chevron up" /></Button>
|
||||
</Button.Group>
|
||||
|
@ -8,8 +8,9 @@ const StyledWarp = styled.div`
|
||||
right:0px;
|
||||
position: absolute;
|
||||
right: ${props => (props.treadles * props.baseSize) + 20}px;
|
||||
height: ${props => (props.shafts * props.baseSize) + 10}px;
|
||||
width: ${props => (props.threading * props.baseSize) + 10}px;
|
||||
height: ${props => (props.shafts * props.baseSize) + 40}px;
|
||||
width: 100%;
|
||||
cursor: ${props => props.tool === 'insert' ? 'w-resize': 'initial'};
|
||||
.warp-colourway td{
|
||||
border:none;
|
||||
border-top:1px solid rgb(150,150,150);
|
||||
@ -18,6 +19,7 @@ const StyledWarp = styled.div`
|
||||
|
||||
const squares = {};
|
||||
const markers = {};
|
||||
const selectedMarkers = {};
|
||||
let dragging = false;
|
||||
let startShaft = null;
|
||||
let startThread = null;
|
||||
@ -154,18 +156,39 @@ function Warp({ baseSize, cellStyle, warp, weft, updatePattern }) {
|
||||
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 });
|
||||
}
|
||||
};
|
||||
const click = (event) => {
|
||||
if (editor.tool === 'point' || editor.tool === 'straight') {
|
||||
const { thread, shaft } = getThreadShaft(event, warpRef.current);
|
||||
if (editor.tool === 'point' || editor.tool === 'straight') {
|
||||
const newWarp = Object.assign({}, warp);
|
||||
if (thread > warp.threading.length || warp.threading.length - thread < 5) fillUpTo(newWarp, thread + 5);
|
||||
const warpThread = newWarp.threading[thread];
|
||||
warpThread.shaft = warpThread.shaft === shaft ? 0 : shaft;
|
||||
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) => {
|
||||
@ -188,6 +211,22 @@ function Warp({ baseSize, cellStyle, warp, weft, updatePattern }) {
|
||||
markers[size] = 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) => {
|
||||
if (squares[size] && squares[size][colour]) return squares[size][colour];
|
||||
@ -221,9 +260,14 @@ function Warp({ baseSize, cellStyle, warp, weft, updatePattern }) {
|
||||
ctx.strokeStyle = 'rgba(0,0,0,0.3)';
|
||||
ctx.stroke();
|
||||
|
||||
const selectedMarker = getSelectedMarker(baseSize, canvas.height);
|
||||
const marker = getMarker(baseSize);
|
||||
for (let thread = 0; thread < warp.threading.length; thread++) {
|
||||
const shaft = warp.threading[thread].shaft;
|
||||
const marker = getMarker(baseSize);
|
||||
const isSelected = warp.threading[thread].isSelected;
|
||||
if (isSelected) {
|
||||
ctx.drawImage(selectedMarker, canvas.width - ((thread + 1) * baseSize), 0);
|
||||
}
|
||||
ctx.drawImage(marker, canvas.width - ((thread + 1) * baseSize), canvas.height - (shaft * baseSize));
|
||||
const colourSquare = getSquare(baseSize, warp.threading[thread].colour || warp.defaultColour);
|
||||
ctx2.drawImage(colourSquare, canvas.width - ((thread + 1) * baseSize), 0);
|
||||
@ -231,7 +275,7 @@ function Warp({ baseSize, cellStyle, warp, weft, updatePattern }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWarp treadles={weft.treadles} shafts={warp.shafts} baseSize={baseSize}>
|
||||
<StyledWarp treadles={weft.treadles} shafts={warp.shafts} baseSize={baseSize} tool={tool}>
|
||||
<canvas className='warp-colourway joyride-warpColourway' ref={colourwayRef} width={warp.threading.length * baseSize} height={10}
|
||||
style={{
|
||||
position: 'absolute', top: 0, right: 0, height: 10, width: warp.threading.length * baseSize,
|
||||
|
@ -12,6 +12,7 @@ const StyledWeft = styled.div`
|
||||
min-height: 1000px;
|
||||
width: ${props => (props.treadles * props.baseSize)}px;
|
||||
height: ${props => props.threads * props.baseSize}px;
|
||||
cursor: ${props => props.tool === 'insert' ? 's-resize': 'initial'};
|
||||
.weft-colourway{
|
||||
border:none;
|
||||
border-right:1px solid rgb(150,150,150);
|
||||
@ -157,12 +158,18 @@ function Weft({ cellStyle, warp, weft, baseSize, updatePattern }) {
|
||||
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 });
|
||||
}
|
||||
};
|
||||
const click = (event) => {
|
||||
if (editor.tool === 'point' || editor.tool === 'straight') {
|
||||
let { thread, treadle } = getThreadTreadle(event, weftRef.current);
|
||||
if (editor.tool === 'point' || editor.tool === 'straight') {
|
||||
treadle += 1;
|
||||
const newWeft = Object.assign({}, weft);
|
||||
if (thread >= newWeft.treadling.length || newWeft.treadling.length - thread < 5) fillUpTo(newWeft, thread + 5);
|
||||
@ -170,6 +177,21 @@ function Weft({ cellStyle, warp, weft, baseSize, updatePattern }) {
|
||||
weftThread.treadle = weftThread.treadle === treadle ? 0 : treadle;
|
||||
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) => {
|
||||
@ -192,6 +214,22 @@ function Weft({ cellStyle, warp, weft, baseSize, updatePattern }) {
|
||||
markers[size] = 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) => {
|
||||
if (squares[size] && squares[size][colour]) return squares[size][colour];
|
||||
@ -225,29 +263,35 @@ function Weft({ cellStyle, warp, weft, baseSize, updatePattern }) {
|
||||
ctx.strokeStyle = 'rgba(0,0,0,0.3)';
|
||||
ctx.stroke();
|
||||
|
||||
for (let thread = 0; thread < weft.threads; thread++) {
|
||||
const treadle = weft.treadling[thread].treadle;
|
||||
const marker = getMarker(baseSize);
|
||||
const selectedMarker = getSelectedMarker(baseSize, canvas.width);
|
||||
for (let thread = 0; thread < weft.treadling.length; thread++) {
|
||||
const treadle = weft.treadling[thread].treadle;
|
||||
const isSelected = weft.treadling[thread].isSelected;
|
||||
if (isSelected) {
|
||||
ctx.drawImage(selectedMarker, 0, ((thread) * baseSize));
|
||||
}
|
||||
ctx.drawImage(marker, ((treadle - 1) * baseSize), ((thread) * baseSize));
|
||||
const colourSquare = getSquare(baseSize, weft.treadling[thread].colour || weft.defaultColour);
|
||||
ctx2.drawImage(colourSquare, 0, (thread * baseSize));
|
||||
}
|
||||
}
|
||||
|
||||
const threadCount = weft.treadling?.length || 0;
|
||||
return (
|
||||
<StyledWeft baseSize={baseSize} treadles={weft.treadles} shafts={warp.shafts} threads={weft.threads}>
|
||||
<canvas className='weft-colourway' ref={colourwayRef} width={10} height={weft.threads * baseSize}
|
||||
style={{ position: 'absolute', top: 0, right: 0, width: 10, height: weft.threads * baseSize}}
|
||||
<StyledWeft baseSize={baseSize} treadles={weft.treadles} shafts={warp.shafts} threads={threadCount} tool={tool}>
|
||||
<canvas className='weft-colourway' ref={colourwayRef} width={10} height={threadCount * baseSize}
|
||||
style={{ position: 'absolute', top: 0, right: 0, width: 10, height: threadCount * baseSize}}
|
||||
onClick={mouseClickColourway}
|
||||
onMouseDown={mouseDownColourway}
|
||||
onMouseMove={mouseMoveColourway}
|
||||
onMouseUp={mouseUpColourway}
|
||||
onMouseLeave={mouseUpColourway}
|
||||
/>
|
||||
<canvas className='weft-threads joyride-weft' ref={weftRef} width={weft.treadles * baseSize} height={weft.threads * baseSize}
|
||||
<canvas className='weft-threads joyride-weft' ref={weftRef} width={weft.treadles * baseSize} height={threadCount * baseSize}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0, right: 10, height: weft.threads * baseSize, width: weft.treadles * baseSize,
|
||||
top: 0, right: 10, height: threadCount * baseSize, width: weft.treadles * baseSize,
|
||||
borderRadius: 4, boxShadow: '0px 0px 10px rgba(0,0,0,0.15)',
|
||||
}}
|
||||
onClick={click}
|
||||
|
Loading…
Reference in New Issue
Block a user