Refactored tool system
This commit is contained in:
parent
8d42e6536f
commit
0e7b797a9d
18 changed files with 529 additions and 435 deletions
|
@ -1,434 +0,0 @@
|
|||
<style>
|
||||
.ide {
|
||||
width: 100vw;
|
||||
height: calc(100vh - 50px);
|
||||
display: grid;
|
||||
grid-template-columns: 300px 1fr 300px;
|
||||
}
|
||||
|
||||
.ide-left, .ide-mid, .ide-right {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ide-left {
|
||||
border-right: var(--border-1);
|
||||
}
|
||||
|
||||
.ide-right {
|
||||
border-left: var(--border-1);
|
||||
}
|
||||
|
||||
.ide-mid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: none;
|
||||
}
|
||||
|
||||
canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
import pkg from 'paper';
|
||||
const { paper } = pkg;
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import EditButton from '$lib/page/EditButton.svelte';
|
||||
import Color from './Color.svelte';
|
||||
import { Group } from "paper/dist/paper-core";
|
||||
import { group_outros } from "svelte/internal";
|
||||
|
||||
let tools = [
|
||||
'edit',
|
||||
'pan',
|
||||
'select',
|
||||
'group',
|
||||
'ungroup',
|
||||
'resize',
|
||||
'rotate',
|
||||
'deleter',
|
||||
'node',
|
||||
'up',
|
||||
'down',
|
||||
'import',
|
||||
'export',
|
||||
]
|
||||
|
||||
let mode = 'edit';
|
||||
let colorType = 'stroke';
|
||||
|
||||
let fillColor = '#446699ff';
|
||||
let strokeColor = '#000000ff';
|
||||
|
||||
let darkStroke = '#d8d8d8';
|
||||
let white = 'white';
|
||||
|
||||
let nodeDist = 25;
|
||||
let grabDist = 15;
|
||||
|
||||
let color = strokeColor;
|
||||
let stroke = 12;
|
||||
|
||||
let origin = new paper.Point([0,0]);
|
||||
|
||||
let viewGroup, innerGroup, canvas, mainPath, lastPoint, file, files, download;
|
||||
|
||||
let importFile = () => {
|
||||
file.click();
|
||||
}
|
||||
|
||||
let getBase64 = (filee) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(filee);
|
||||
reader.onload = e => {
|
||||
let preview = e.target.result;
|
||||
paper.project.importSVG(preview, function (item) {
|
||||
innerGroup.addChild(item);
|
||||
recurseChild(innerGroup);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
let exportFile = () => {
|
||||
var data = new Blob(['<svg>' + innerGroup.exportSVG({asString: true}) + '</svg>'], {type: 'image/svg'});
|
||||
|
||||
var url = window.URL.createObjectURL(data);
|
||||
|
||||
download.href = url;
|
||||
download.click();
|
||||
}
|
||||
|
||||
let setMode = (modeSet) => {
|
||||
if (modeSet)
|
||||
mode = modeSet;
|
||||
|
||||
if (mode == 'group') {
|
||||
group();
|
||||
} else if (mode == 'ungroup') {
|
||||
ungroup();
|
||||
} else if (mode == 'import') {
|
||||
importFile();
|
||||
} else if (mode == 'export') {
|
||||
exportFile();
|
||||
} else if (mode == 'deleter') {
|
||||
deleter();
|
||||
} else if (mode == 'up') {
|
||||
layerUp();
|
||||
} else if (mode == 'down') {
|
||||
layerDown();
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
let setColorMode = (modeSet) => {
|
||||
if (modeSet)
|
||||
colorType = modeSet;
|
||||
|
||||
color = (modeSet == 'stroke') ? strokeColor : fillColor;
|
||||
|
||||
return colorType;
|
||||
}
|
||||
|
||||
let setColor = ([colorIn, strokeIn]) => {
|
||||
color = colorIn;
|
||||
stroke = strokeIn / 5;
|
||||
|
||||
if (colorType == 'stroke') {
|
||||
strokeColor = color
|
||||
} else {
|
||||
fillColor = color;
|
||||
}
|
||||
|
||||
if (!paper.project || !paper.project.selectedItems) return;
|
||||
|
||||
paper.project.selectedItems.forEach(item => {
|
||||
if (colorType == 'stroke') {
|
||||
item.strokeColor = color
|
||||
} else {
|
||||
item.fillColor = color;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let initPath = () => {
|
||||
mainPath = new paper.Path();
|
||||
|
||||
mainPath.strokeColor = strokeColor;
|
||||
mainPath.fillColor = fillColor;
|
||||
mainPath.strokeWidth = stroke;
|
||||
mainPath.strokeCap = 'butt';
|
||||
mainPath.strokeJoin = 'bevel';
|
||||
|
||||
innerGroup.addChild(mainPath);
|
||||
|
||||
recurseChild(innerGroup);
|
||||
|
||||
}
|
||||
|
||||
let mouseDown = (event) => {
|
||||
if (mode == 'edit') {
|
||||
initPath();
|
||||
}
|
||||
}
|
||||
|
||||
let layerDown = () => {
|
||||
paper.project.selectedItems.reverse().forEach(item => {
|
||||
item.sendToBack();
|
||||
})
|
||||
};
|
||||
|
||||
let layerUp = () => {
|
||||
paper.project.selectedItems.forEach(item => {
|
||||
item.bringToFront();
|
||||
})
|
||||
};
|
||||
|
||||
let group = () => {
|
||||
var group = new paper.Group(paper.project.selectedItems);
|
||||
innerGroup.addChild(group);
|
||||
};
|
||||
|
||||
let ungroup = () => {
|
||||
paper.project.selectedItems.forEach(item => {
|
||||
if (!item.children || item.className != 'Group' || item == innerGroup) return;
|
||||
item.selected = false;
|
||||
item.children.forEach(child => {
|
||||
innerGroup.addChild(child);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
let deleter = () => {
|
||||
paper.project.selectedItems.forEach(item => {
|
||||
console.log(item);
|
||||
item.remove();
|
||||
})
|
||||
}
|
||||
|
||||
let mouseDownInner = (event) => {
|
||||
event.stopPropagation();
|
||||
|
||||
console.log(event.target);
|
||||
|
||||
var target = event.target;
|
||||
|
||||
while (target.parent != innerGroup) {
|
||||
target = target.parent;
|
||||
}
|
||||
|
||||
console.log(target);
|
||||
|
||||
if (mode == 'select') {
|
||||
target.selected = !target.selected;
|
||||
} else if (mode == 'node') {
|
||||
var nearestPoint = target.getNearestPoint(event.point);
|
||||
|
||||
if (nearestPoint.getDistance(event.point) > nodeDist) return;
|
||||
|
||||
target.segments.forEach(segment => {
|
||||
segment.selected = false;
|
||||
});
|
||||
|
||||
let closestPoint = target.segments[0];
|
||||
let closestDist = 10000;
|
||||
|
||||
target.segments.forEach(segment => {
|
||||
let dist = segment.point.getDistance(nearestPoint);
|
||||
if (dist < closestDist) {
|
||||
closestDist = dist;
|
||||
closestPoint = segment.point;
|
||||
}
|
||||
});
|
||||
|
||||
let newPoint;
|
||||
|
||||
if (nearestPoint.getDistance(closestPoint) > grabDist) {
|
||||
newPoint = target.divideAt(target.getLocationOf(nearestPoint));
|
||||
} else {
|
||||
newPoint = closestPoint;
|
||||
}
|
||||
|
||||
newPoint.selected = true;
|
||||
} else if (mode == 'resize' || mode == 'rotate') {
|
||||
target.selected = !target.selected;
|
||||
target.bounds.selected = target.selected;
|
||||
}
|
||||
}
|
||||
|
||||
let mouseDrag = (event) => {
|
||||
if (mode == 'pan') {
|
||||
viewGroup.position = viewGroup.position.add(event.delta);
|
||||
} else if (mode == 'edit') {
|
||||
lastPoint = event.point;
|
||||
|
||||
mainPath.add(event.point);
|
||||
} else if (mode == 'select' || mode == 'node') {
|
||||
paper.project.selectedItems.forEach(item => {
|
||||
if ((mode == 'select' && item.parent != innerGroup)) return;
|
||||
|
||||
if (mode == 'node') {
|
||||
if (item.className == 'Path') {
|
||||
item.segments.forEach(segment => {
|
||||
if (segment.selected)
|
||||
segment.point = segment.point.add(event.delta)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
item.position = item.position.add(event.delta)
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
} else if (mode == 'resize') {
|
||||
paper.project.selectedItems.forEach(item => {
|
||||
var nearestPoint = event.point;
|
||||
|
||||
if (!item.bounds.selected) return;
|
||||
|
||||
let seg = [
|
||||
item.bounds.topLeft,
|
||||
item.bounds.topRight,
|
||||
item.bounds.bottomLeft,
|
||||
item.bounds.bottomRight,
|
||||
item.bounds.topCenter,
|
||||
item.bounds.bottomCenter,
|
||||
item.bounds.leftCenter,
|
||||
item.bounds.rightCenter
|
||||
];
|
||||
|
||||
let segOpp = [
|
||||
item.bounds.bottomRight,
|
||||
item.bounds.bottomLeft,
|
||||
item.bounds.topRight,
|
||||
item.bounds.topLeft,
|
||||
item.bounds.bottomCenter,
|
||||
item.bounds.topCenter,
|
||||
item.bounds.rightCenter,
|
||||
item.bounds.leftCenter
|
||||
]
|
||||
|
||||
let closestPoint = seg[0];
|
||||
let closestDist = 10000;
|
||||
let i = -1;
|
||||
|
||||
seg.forEach((segment,index) => {
|
||||
let dist = segment.getDistance(nearestPoint);
|
||||
if (dist < closestDist) {
|
||||
closestDist = dist;
|
||||
closestPoint = segOpp[index];
|
||||
i = index;
|
||||
}
|
||||
});
|
||||
|
||||
if (closestDist < nodeDist) {
|
||||
var signX = (i == 1 || i == 3 || i == 7) ? 1 : -1;
|
||||
var signY = (i == 1 || i == 0 || i == 4) ? -1 : 1;
|
||||
if (i > 5) {
|
||||
item.scale(1 + signX * event.delta.x / item.bounds.width, 1, closestPoint);
|
||||
} else if (i > 3) {
|
||||
item.scale(1, 1 + signY * event.delta.y / item.bounds.height, closestPoint);
|
||||
} else {
|
||||
item.scale(1 + signX * event.delta.x / item.bounds.width, 1 + signY * event.delta.y / item.bounds.height, closestPoint);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (mode == 'rotate') {
|
||||
paper.project.selectedItems.forEach(item => {
|
||||
if (!item.bounds.selected) return;
|
||||
var rotAngle = event.point.subtract(item.bounds.center).angle - event.point.add(event.delta).subtract(item.bounds.center).angle;
|
||||
item.rotate(-rotAngle);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mouseUp = (event) => {
|
||||
if (mode == 'edit') {
|
||||
if (mainPath.lastSegment.point.getDistance(mainPath.firstSegment.point) < nodeDist) {
|
||||
mainPath.closePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mouseDragInner = (event) => {
|
||||
|
||||
}
|
||||
|
||||
let recurseChild = (parent) => {
|
||||
if (!parent.children || parent.children.length == 0) {
|
||||
parent.onMouseDrag = mouseDragInner;
|
||||
parent.onDoubleClick = mouseDownInner;
|
||||
return;
|
||||
} else {
|
||||
parent.onMouseDrag = () => {};
|
||||
parent.onDoubleClick = () => {};
|
||||
}
|
||||
|
||||
parent.children.forEach(child => {
|
||||
if (child == parent) return;
|
||||
recurseChild(child);
|
||||
})
|
||||
}
|
||||
|
||||
let initView = () => {
|
||||
let rect = new paper.Rectangle(0,0,480,360);
|
||||
|
||||
let path = new paper.Path.Rectangle(rect);
|
||||
path.fillColor = 'white';
|
||||
|
||||
let pathOut = new paper.Path.Rectangle(rect);
|
||||
|
||||
pathOut.strokeColor = darkStroke;
|
||||
pathOut.strokeWidth = '3';
|
||||
|
||||
innerGroup = new paper.Group([]);
|
||||
|
||||
viewGroup = new paper.Group([path,innerGroup,pathOut]);
|
||||
|
||||
/*paper.project.importSVG("/logo.svg", function (item) {
|
||||
innerGroup.addChild(item);
|
||||
recurseChild(innerGroup);
|
||||
})*/
|
||||
|
||||
viewGroup.onMouseDrag = mouseDrag;
|
||||
viewGroup.onMouseDown = mouseDown;
|
||||
viewGroup.onMouseUp = mouseUp;
|
||||
}
|
||||
|
||||
|
||||
onMount(() => {
|
||||
if (!canvas) return;
|
||||
|
||||
paper.setup(canvas);
|
||||
|
||||
initView();
|
||||
initPath();
|
||||
|
||||
console.log(paper.view);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div class='ide'>
|
||||
<div class='ide-left'>
|
||||
{#each tools as tool}
|
||||
<EditButton bindMode={setMode} modeIn={mode} mode={tool} />
|
||||
{/each}
|
||||
</div>
|
||||
<div class='ide-mid'>
|
||||
<canvas class='canvas' resize bind:this={canvas}></canvas>
|
||||
</div>
|
||||
<div class='ide-right'>
|
||||
<EditButton bindMode={setColorMode} modeIn={colorType} mode={'stroke'} />
|
||||
<EditButton bindMode={setColorMode} modeIn={colorType} mode={'fill'} />
|
||||
<Color bindColor={setColor} color={color} />
|
||||
<input type="file" style="display:none" bind:files on:change={() => getBase64(files[0])} bind:this={file}>
|
||||
<a download="export.svg" bind:this={download} hidden></a>
|
||||
</div>
|
||||
</div>
|
266
src/lib/vector/Env.svelte
Normal file
266
src/lib/vector/Env.svelte
Normal file
|
@ -0,0 +1,266 @@
|
|||
<style>
|
||||
.ide {
|
||||
width: 100vw;
|
||||
height: calc(100vh - 50px);
|
||||
display: grid;
|
||||
grid-template-columns: 300px 1fr 300px;
|
||||
}
|
||||
|
||||
.ide-left, .ide-mid, .ide-right {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ide-left {
|
||||
border-right: var(--border-1);
|
||||
}
|
||||
|
||||
.ide-right {
|
||||
border-left: var(--border-1);
|
||||
}
|
||||
|
||||
.ide-mid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: none;
|
||||
}
|
||||
|
||||
canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
import pkg from 'paper';
|
||||
const { paper } = pkg;
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import EditButton from '$lib/page/EditButton.svelte';
|
||||
import Color from './Color.svelte';
|
||||
import { Group } from "paper/dist/paper-core";
|
||||
import { group_outros } from "svelte/internal";
|
||||
|
||||
let tools = [
|
||||
'edit',
|
||||
'pan',
|
||||
'select',
|
||||
'group',
|
||||
'ungroup',
|
||||
'resize',
|
||||
'rotate',
|
||||
'deleter',
|
||||
'node',
|
||||
'up',
|
||||
'down',
|
||||
'import',
|
||||
'export',
|
||||
]
|
||||
|
||||
let toolData = {};
|
||||
|
||||
tools.forEach(async tool => {
|
||||
toolData[tool] = await import(`./tools/${tool}.js`);
|
||||
})
|
||||
|
||||
|
||||
let viewGroup, canvas, mainPath, lastPoint, file, files, download, settings;
|
||||
|
||||
let darkStroke = '#000000';
|
||||
|
||||
let mode = 'edit';
|
||||
|
||||
settings = {
|
||||
colorType: 'stroke',
|
||||
|
||||
fill: {
|
||||
color: '#446699ff',
|
||||
stroke: '#000000ff'
|
||||
},
|
||||
|
||||
color: '#000000ff',
|
||||
|
||||
stroke: 12,
|
||||
|
||||
innerGroup: null,
|
||||
|
||||
viewGroup: null,
|
||||
|
||||
mainPath: null,
|
||||
|
||||
nodeDist: 45,
|
||||
|
||||
grabDist: 15,
|
||||
|
||||
doc: {
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
let getBase64 = (filee) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(filee);
|
||||
reader.onload = e => {
|
||||
let preview = e.target.result;
|
||||
paper.project.importSVG(preview, function (item) {
|
||||
settings.innerGroup.addChild(item);
|
||||
recurseChild(settings.innerGroup);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
let execFunc = (obj, val, args) => {
|
||||
obj = obj.toolData;
|
||||
if (obj[val]) {
|
||||
let result = obj[val]({
|
||||
...args,
|
||||
...settings,
|
||||
delta: args.delta,
|
||||
point: args.point,
|
||||
target: args.target,
|
||||
selectedItems: paper.project.selectedItems
|
||||
});
|
||||
settings = result || settings;
|
||||
recurseChild(settings.innerGroup);
|
||||
}
|
||||
}
|
||||
|
||||
let origin = new paper.Point([0,0]);
|
||||
|
||||
|
||||
let setMode = (modeSet) => {
|
||||
if (modeSet)
|
||||
mode = modeSet;
|
||||
|
||||
execFunc(toolData[mode],'run',[])
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
let setColorMode = (modeSet) => {
|
||||
if (modeSet)
|
||||
settings.colorType = modeSet;
|
||||
|
||||
color = (modeSet == 'stroke') ? settings.fill.stroke : settings.fill.color;
|
||||
|
||||
return settings.colorType;
|
||||
}
|
||||
|
||||
let setColor = ([colorIn, strokeIn]) => {
|
||||
settings.color = colorIn;
|
||||
settings.stroke = strokeIn / 5;
|
||||
|
||||
if (settings.colorType == 'stroke') {
|
||||
settings.fill.stroke = settings.color
|
||||
} else {
|
||||
settings.fill.color = settings.color;
|
||||
}
|
||||
|
||||
if (!paper.project || !paper.project.selectedItems) return;
|
||||
|
||||
paper.project.selectedItems.forEach(item => {
|
||||
if (settings.colorType == 'stroke') {
|
||||
item.strokeColor = settings.color
|
||||
} else {
|
||||
item.fillColor = settings.color;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let mouseEvent = (type) => {
|
||||
return (event) => {
|
||||
execFunc(toolData[mode],type,event);
|
||||
}
|
||||
}
|
||||
|
||||
let mouseEventInner = (type) => {
|
||||
return (event) => {
|
||||
event.stopPropagation();
|
||||
|
||||
var target = event.target;
|
||||
|
||||
while (target.parent != settings.innerGroup && target.parent != settings.viewGroup && target.parent) {
|
||||
target = target.parent;
|
||||
}
|
||||
|
||||
event.target = target;
|
||||
|
||||
execFunc(toolData[mode],type,event);
|
||||
}
|
||||
}
|
||||
|
||||
let recurseChild = (parent) => {
|
||||
if (!parent.children || parent.children.length == 0) {
|
||||
parent.onMouseDrag = mouseEventInner('mouseDragInner');
|
||||
parent.onDoubleClick = mouseEventInner('doubleClickInner');
|
||||
return;
|
||||
} else {
|
||||
parent.onMouseDrag = () => {};
|
||||
parent.onDoubleClick = () => {};
|
||||
}
|
||||
|
||||
parent.children.forEach(child => {
|
||||
if (child == parent) return;
|
||||
recurseChild(child);
|
||||
})
|
||||
}
|
||||
|
||||
let initView = () => {
|
||||
let rect = new paper.Rectangle(0,0,480,360);
|
||||
|
||||
let path = new paper.Path.Rectangle(rect);
|
||||
path.fillColor = 'white';
|
||||
|
||||
let pathOut = new paper.Path.Rectangle(rect);
|
||||
|
||||
pathOut.strokeColor = darkStroke;
|
||||
pathOut.strokeWidth = '3';
|
||||
|
||||
settings.innerGroup = new paper.Group([]);
|
||||
|
||||
settings.viewGroup = new paper.Group([path,settings.innerGroup,pathOut]);
|
||||
|
||||
/*paper.project.importSVG("/logo.svg", function (item) {
|
||||
innerGroup.addChild(item);
|
||||
recurseChild(innerGroup);
|
||||
})*/
|
||||
|
||||
settings.viewGroup.onMouseDrag = mouseEvent('mouseDrag');
|
||||
settings.viewGroup.onMouseDown = mouseEvent('mouseDown');
|
||||
settings.viewGroup.onMouseUp = mouseEvent('mouseUp');
|
||||
}
|
||||
|
||||
|
||||
onMount(() => {
|
||||
if (!canvas) return;
|
||||
|
||||
paper.setup(canvas);
|
||||
|
||||
initView();
|
||||
|
||||
console.log(paper.view);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div class='ide'>
|
||||
<div class='ide-left'>
|
||||
{#each tools as tool}
|
||||
<EditButton bindMode={setMode} modeIn={mode} mode={tool} />
|
||||
{/each}
|
||||
</div>
|
||||
<div class='ide-mid'>
|
||||
<canvas class='canvas' resize bind:this={canvas}></canvas>
|
||||
</div>
|
||||
<div class='ide-right'>
|
||||
<EditButton bindMode={setColorMode} modeIn={settings.colorType} mode={'stroke'} />
|
||||
<EditButton bindMode={setColorMode} modeIn={settings.colorType} mode={'fill'} />
|
||||
<Color bindColor={setColor} color={settings.color} />
|
||||
<input type="file" style="display:none" bind:files on:change={() => getBase64(files[0])} bind:this={settings.doc.file}>
|
||||
<a download="export.svg" bind:this={settings.doc.download} hidden></a>
|
||||
</div>
|
||||
</div>
|
10
src/lib/vector/tools/deleter.js
Normal file
10
src/lib/vector/tools/deleter.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
let toolData = {
|
||||
run: ({ selectedItems }) => {
|
||||
selectedItems.forEach(item => {
|
||||
item.remove();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
10
src/lib/vector/tools/down.js
Normal file
10
src/lib/vector/tools/down.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
let toolData = {
|
||||
run: ({ selectedItems }) => {
|
||||
selectedItems.reverse().forEach(item => {
|
||||
item.sendToBack();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
38
src/lib/vector/tools/edit.js
Normal file
38
src/lib/vector/tools/edit.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
import pkg from 'paper';
|
||||
const { paper } = pkg;
|
||||
|
||||
let lastPoint;
|
||||
|
||||
let toolData = {
|
||||
mouseDown: (settings) => {
|
||||
let { innerGroup, mainPath, fill, stroke } = settings;
|
||||
mainPath = new paper.Path();
|
||||
|
||||
mainPath.strokeColor = fill.stroke;
|
||||
mainPath.fillColor = fill.color;
|
||||
|
||||
mainPath.strokeWidth = stroke;
|
||||
mainPath.strokeCap = 'butt';
|
||||
mainPath.strokeJoin = 'bevel';
|
||||
|
||||
innerGroup.addChild(mainPath);
|
||||
|
||||
settings.mainPath = mainPath;
|
||||
return settings;
|
||||
|
||||
},
|
||||
|
||||
mouseDrag: ( {mainPath, point}) => {
|
||||
lastPoint = point;
|
||||
|
||||
mainPath.add(point);
|
||||
},
|
||||
|
||||
mouseUp: ( {mainPath, nodeDist }) => {
|
||||
if (mainPath.lastSegment.point.getDistance(mainPath.firstSegment.point) < nodeDist) {
|
||||
mainPath.closePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
13
src/lib/vector/tools/export.js
Normal file
13
src/lib/vector/tools/export.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
let toolData = {
|
||||
run: ({ innerGroup, doc }) => {
|
||||
var data = new Blob(['<svg>' + innerGroup.exportSVG({asString: true}) + '</svg>'], {type: 'image/svg'});
|
||||
|
||||
var url = window.URL.createObjectURL(data);
|
||||
|
||||
doc.download.href = url;
|
||||
doc.download.click();
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
12
src/lib/vector/tools/group.js
Normal file
12
src/lib/vector/tools/group.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
import pkg from 'paper';
|
||||
const { paper } = pkg;
|
||||
|
||||
let toolData = {
|
||||
run: ({ selectedItems, innerGroup }) => {
|
||||
var group = new paper.Group(selectedItems);
|
||||
innerGroup.addChild(group);
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
7
src/lib/vector/tools/import.js
Normal file
7
src/lib/vector/tools/import.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
let toolData = {
|
||||
run: ({ doc }) => {
|
||||
doc.file.click();
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
45
src/lib/vector/tools/node.js
Normal file
45
src/lib/vector/tools/node.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
let toolData = {
|
||||
doubleClickInner: (event) => {
|
||||
var nearestPoint = event.target.getNearestPoint(event.point);
|
||||
|
||||
if (nearestPoint.getDistance(event.point) > event.nodeDist) return;
|
||||
|
||||
event.target.segments.forEach(segment => {
|
||||
segment.selected = false;
|
||||
});
|
||||
|
||||
let closestPoint = event.target.segments[0];
|
||||
let closestDist = 10000;
|
||||
|
||||
event.target.segments.forEach(segment => {
|
||||
let dist = segment.point.getDistance(nearestPoint);
|
||||
if (dist < closestDist) {
|
||||
closestDist = dist;
|
||||
closestPoint = segment.point;
|
||||
}
|
||||
});
|
||||
|
||||
let newPoint;
|
||||
|
||||
if (nearestPoint.getDistance(closestPoint) > event.grabDist) {
|
||||
newPoint = event.target.divideAt(event.target.getLocationOf(nearestPoint));
|
||||
} else {
|
||||
newPoint = closestPoint;
|
||||
}
|
||||
|
||||
newPoint.selected = true;
|
||||
},
|
||||
|
||||
mouseDrag : ( {selectedItems, delta} ) => {
|
||||
selectedItems.forEach(item => {
|
||||
if (item.className == 'Path') {
|
||||
item.segments.forEach(segment => {
|
||||
if (segment.selected)
|
||||
segment.point = segment.point.add(delta)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
7
src/lib/vector/tools/pan.js
Normal file
7
src/lib/vector/tools/pan.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
let toolData = {
|
||||
mouseDrag: ( { viewGroup, delta } ) => {
|
||||
viewGroup.position = viewGroup.position.add(delta);
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
64
src/lib/vector/tools/resize.js
Normal file
64
src/lib/vector/tools/resize.js
Normal file
|
@ -0,0 +1,64 @@
|
|||
let toolData = {
|
||||
doubleClickInner: ({ target }) => {
|
||||
target.selected = !target.selected;
|
||||
target.bounds.selected = target.selected;
|
||||
},
|
||||
|
||||
mouseDrag: ( {selectedItems, point, delta, nodeDist} ) => {
|
||||
selectedItems.forEach(item => {
|
||||
var nearestPoint = point;
|
||||
|
||||
if (!item.bounds.selected) return;
|
||||
|
||||
|
||||
let seg = [
|
||||
item.bounds.topLeft,
|
||||
item.bounds.topRight,
|
||||
item.bounds.bottomLeft,
|
||||
item.bounds.bottomRight,
|
||||
item.bounds.topCenter,
|
||||
item.bounds.bottomCenter,
|
||||
item.bounds.leftCenter,
|
||||
item.bounds.rightCenter
|
||||
];
|
||||
|
||||
let segOpp = [
|
||||
item.bounds.bottomRight,
|
||||
item.bounds.bottomLeft,
|
||||
item.bounds.topRight,
|
||||
item.bounds.topLeft,
|
||||
item.bounds.bottomCenter,
|
||||
item.bounds.topCenter,
|
||||
item.bounds.rightCenter,
|
||||
item.bounds.leftCenter
|
||||
]
|
||||
|
||||
let closestPoint = seg[0];
|
||||
let closestDist = 10000;
|
||||
let i = -1;
|
||||
|
||||
seg.forEach((segment,index) => {
|
||||
let dist = segment.getDistance(nearestPoint);
|
||||
if (dist < closestDist) {
|
||||
closestDist = dist;
|
||||
closestPoint = segOpp[index];
|
||||
i = index;
|
||||
}
|
||||
});
|
||||
|
||||
if (closestDist < nodeDist) {
|
||||
var signX = (i == 1 || i == 3 || i == 7) ? 1 : -1;
|
||||
var signY = (i == 1 || i == 0 || i == 4) ? -1 : 1;
|
||||
if (i > 5) {
|
||||
item.scale(1 + signX * delta.x / item.bounds.width, 1, closestPoint);
|
||||
} else if (i > 3) {
|
||||
item.scale(1, 1 + signY * delta.y / item.bounds.height, closestPoint);
|
||||
} else {
|
||||
item.scale(1 + signX * delta.x / item.bounds.width, 1 + signY * delta.y / item.bounds.height, closestPoint);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
16
src/lib/vector/tools/rotate.js
Normal file
16
src/lib/vector/tools/rotate.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
let toolData = {
|
||||
doubleClickInner: ({ target }) => {
|
||||
target.selected = !target.selected;
|
||||
target.bounds.selected = target.selected;
|
||||
},
|
||||
|
||||
mouseDrag: ( {selectedItems, point, delta} ) => {
|
||||
selectedItems.forEach(item => {
|
||||
if (!item.bounds.selected) return;
|
||||
var rotAngle = point.subtract(item.bounds.center).angle - point.add(delta).subtract(item.bounds.center).angle;
|
||||
item.rotate(-rotAngle);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
16
src/lib/vector/tools/select.js
Normal file
16
src/lib/vector/tools/select.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
let toolData = {
|
||||
doubleClickInner: ({ target }) => {
|
||||
target.selected = !target.selected;
|
||||
},
|
||||
|
||||
mouseDragInner: ( {selectedItems, delta, innerGroup} ) => {
|
||||
selectedItems.forEach(item => {
|
||||
if ((item.parent != innerGroup)) return;
|
||||
|
||||
item.position = item.position.add(delta)
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
14
src/lib/vector/tools/ungroup.js
Normal file
14
src/lib/vector/tools/ungroup.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
let toolData = {
|
||||
run: ({ selectedItems, innerGroup }) => {
|
||||
selectedItems.forEach(item => {
|
||||
if (!item.children || item.className != 'Group' || item == innerGroup) return;
|
||||
item.selected = false;
|
||||
item.children.forEach(child => {
|
||||
innerGroup.addChild(child);
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
10
src/lib/vector/tools/up.js
Normal file
10
src/lib/vector/tools/up.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
let toolData = {
|
||||
run: ({ selectedItems }) => {
|
||||
selectedItems.forEach(item => {
|
||||
item.bringToFront();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { toolData };
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import Env from '$lib/ide/Env.svelte'
|
||||
import Env from '$lib/vector/Env.svelte'
|
||||
</script>
|
||||
|
||||
<Env />
|
Loading…
Reference in a new issue