This commit is contained in:
parent
e9e0dab2f8
commit
67c49a26a4
|
@ -27,7 +27,7 @@ const include = [
|
||||||
// 'sortablejs',
|
// 'sortablejs',
|
||||||
// 'swiper/vue',
|
// 'swiper/vue',
|
||||||
// 'mint-filter',
|
// 'mint-filter',
|
||||||
// '@vueuse/core',
|
'@vueuse/core',
|
||||||
// 'vue3-danmaku',
|
// 'vue3-danmaku',
|
||||||
// 'v-contextmenu',
|
// 'v-contextmenu',
|
||||||
// 'vue-pdf-embed',
|
// 'vue-pdf-embed',
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"version":1721175662341}
|
{"version":1721355798048}
|
|
@ -1,153 +1,48 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { useWindowSize } from '@vueuse/core';
|
import { useEventListener, useWindowSize } from '@vueuse/core';
|
||||||
import Konva from 'konva/lib';
|
import Konva from 'konva/lib';
|
||||||
|
import { rect1, rect2, selectionRectangle } from '@/views/select/basic/rect.ts';
|
||||||
|
import { stageEvent } from '@/views/select/basic/stageEvent.ts';
|
||||||
|
import { drawLine } from '@/views/select/basic/line.ts';
|
||||||
|
import { Stage } from 'konva/lib/Stage';
|
||||||
|
import { Layer } from 'konva/lib/Layer';
|
||||||
|
|
||||||
const { width, height } = useWindowSize();
|
const { width, height } = useWindowSize();
|
||||||
|
// let stage, layer;
|
||||||
|
|
||||||
|
const stage = ref<Stage>();
|
||||||
|
const layer = ref<Layer>();
|
||||||
|
const tr = ref();
|
||||||
|
|
||||||
const initial = () => {
|
const initial = () => {
|
||||||
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
|
stage.value = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
|
||||||
const layer = new Konva.Layer();
|
layer.value = new Konva.Layer();
|
||||||
|
stage.value.add(layer.value);
|
||||||
|
|
||||||
const rect1 = new Konva.Rect({
|
drawLine(stage.value, layer.value);
|
||||||
x: 60,
|
|
||||||
y: 60,
|
|
||||||
width: 100,
|
|
||||||
height: 90,
|
|
||||||
fill: 'red',
|
|
||||||
name: 'rect',
|
|
||||||
draggable: true,
|
|
||||||
});
|
|
||||||
layer.add(rect1);
|
|
||||||
|
|
||||||
const rect2 = new Konva.Rect({
|
rect1(layer.value);
|
||||||
x: 180,
|
rect2(layer.value);
|
||||||
y: 200,
|
|
||||||
width: 100,
|
|
||||||
height: 200,
|
|
||||||
fill: 'green',
|
|
||||||
name: 'rect',
|
|
||||||
draggable: true,
|
|
||||||
});
|
|
||||||
layer.add(rect2);
|
|
||||||
|
|
||||||
// 添加缩放
|
// 添加缩放
|
||||||
const tr = new Konva.Transformer();
|
tr.value = new Konva.Transformer();
|
||||||
layer.add(tr);
|
layer.value.add(tr.value);
|
||||||
tr.nodes([rect1, rect2]);
|
|
||||||
|
|
||||||
const selectionRectangle = new Konva.Rect({
|
stageEvent(stage.value, selectionRectangle(layer.value), tr.value);
|
||||||
fill: 'rgba(0,0,255,0.5)',
|
|
||||||
visible: false,
|
|
||||||
// disable events to not interrupt with events
|
|
||||||
listening: false,
|
|
||||||
});
|
|
||||||
layer.add(selectionRectangle);
|
|
||||||
|
|
||||||
let x1 = 0,
|
|
||||||
y1 = 0,
|
|
||||||
x2 = 0,
|
|
||||||
y2 = 0;
|
|
||||||
let selecting = false;
|
|
||||||
stage.on('mousedown touchstart', e => {
|
|
||||||
// do nothing if we mousedown on any shape
|
|
||||||
if (e.target !== stage) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
e.evt.preventDefault();
|
|
||||||
x1 = stage.getPointerPosition()!.x;
|
|
||||||
y1 = stage.getPointerPosition()!.y;
|
|
||||||
x2 = stage.getPointerPosition()!.x;
|
|
||||||
y2 = stage.getPointerPosition()!.y;
|
|
||||||
|
|
||||||
selectionRectangle.width(0);
|
|
||||||
selectionRectangle.height(0);
|
|
||||||
selecting = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
stage.on('mousemove touchmove', e => {
|
|
||||||
// do nothing if we didn't start selection
|
|
||||||
if (!selecting) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
e.evt.preventDefault();
|
|
||||||
x2 = stage.getPointerPosition()!.x;
|
|
||||||
y2 = stage.getPointerPosition()!.y;
|
|
||||||
|
|
||||||
selectionRectangle.setAttrs({
|
|
||||||
visible: true,
|
|
||||||
x: Math.min(x1, x2),
|
|
||||||
y: Math.min(y1, y2),
|
|
||||||
width: Math.abs(x2 - x1),
|
|
||||||
height: Math.abs(y2 - y1),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
stage.on('mouseup touchend', e => {
|
|
||||||
// do nothing if we didn't start selection
|
|
||||||
selecting = false;
|
|
||||||
if (!selectionRectangle.visible()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
e.evt.preventDefault();
|
|
||||||
// update visibility in timeout, so we can check it in click event
|
|
||||||
selectionRectangle.visible(false);
|
|
||||||
let shapes = stage.find('.rect');
|
|
||||||
let box = selectionRectangle.getClientRect();
|
|
||||||
let selected = shapes.filter(shape => Konva.Util.haveIntersection(box, shape.getClientRect()));
|
|
||||||
tr.nodes(selected);
|
|
||||||
});
|
|
||||||
|
|
||||||
// clicks should select/deselect shapes
|
|
||||||
stage.on('click tap', function (e) {
|
|
||||||
// if we are selecting with rect, do nothing
|
|
||||||
if (selectionRectangle.visible()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if click on empty area - remove all selections
|
|
||||||
if (e.target === stage) {
|
|
||||||
tr.nodes([]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do nothing if clicked NOT on our rectangles
|
|
||||||
if (!e.target.hasName('rect')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do we pressed shift or ctrl?
|
|
||||||
const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
|
|
||||||
const isSelected = tr.nodes().indexOf(e.target) >= 0;
|
|
||||||
|
|
||||||
if (!metaPressed && !isSelected) {
|
|
||||||
// if no key pressed and the node is not selected
|
|
||||||
// select just one
|
|
||||||
tr.nodes([e.target]);
|
|
||||||
} else if (metaPressed && isSelected) {
|
|
||||||
// if we pressed keys and node was selected
|
|
||||||
// we need to remove it from selection:
|
|
||||||
const nodes = tr.nodes().slice(); // use slice to have new copy of array
|
|
||||||
// remove node from array
|
|
||||||
nodes.splice(nodes.indexOf(e.target), 1);
|
|
||||||
tr.nodes(nodes);
|
|
||||||
} else if (metaPressed && !isSelected) {
|
|
||||||
// add the node into selection
|
|
||||||
const nodes = tr.nodes().concat([e.target]);
|
|
||||||
tr.nodes(nodes);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
stage.add(layer);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initial();
|
initial();
|
||||||
|
useEventListener(window, 'resize', function () {
|
||||||
|
stage.value?.width(width.value);
|
||||||
|
stage.value?.height(height.value);
|
||||||
|
|
||||||
|
// tr.value.forceUpdate();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="container"></div>
|
<div id="container"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { Stage } from 'konva/lib/Stage';
|
||||||
|
import { Layer } from 'konva/lib/Layer';
|
||||||
|
import Konva from 'konva/lib';
|
||||||
|
|
||||||
|
export const drawLine = (stage: Stage, layer: Layer) => {
|
||||||
|
const xSnaps = Math.round(stage.width() / 50);
|
||||||
|
const ySnaps = Math.round(stage.height() / 50);
|
||||||
|
const cellWidth = stage.width() / xSnaps;
|
||||||
|
const cellHeight = stage.height() / ySnaps;
|
||||||
|
|
||||||
|
for (let i = 0; i < xSnaps; i++) {
|
||||||
|
const xLine = new Konva.Line({
|
||||||
|
x: i * cellWidth,
|
||||||
|
points: [0, 0, 0, stage.height()],
|
||||||
|
stroke: '#96e04d',
|
||||||
|
strokeWidth: 1,
|
||||||
|
id: 'line',
|
||||||
|
});
|
||||||
|
layer.add(xLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < ySnaps; i++) {
|
||||||
|
layer.add(
|
||||||
|
new Konva.Line({
|
||||||
|
y: i * cellHeight,
|
||||||
|
points: [0, 0, stage.width(), 0],
|
||||||
|
stroke: '#96e04d',
|
||||||
|
strokeWidth: 1,
|
||||||
|
id: 'line',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { Layer } from 'konva/lib/Layer';
|
||||||
|
import Konva from 'konva/lib';
|
||||||
|
|
||||||
|
export const rect1 = (parent: Layer) => {
|
||||||
|
const rect = new Konva.Rect({
|
||||||
|
x: 60,
|
||||||
|
y: 60,
|
||||||
|
width: 100,
|
||||||
|
height: 90,
|
||||||
|
fill: 'red',
|
||||||
|
name: 'rect',
|
||||||
|
draggable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
parent.add(rect);
|
||||||
|
return rect;
|
||||||
|
};
|
||||||
|
export const rect2 = (parent: Layer) => {
|
||||||
|
const rect = new Konva.Rect({
|
||||||
|
x: 180,
|
||||||
|
y: 200,
|
||||||
|
width: 100,
|
||||||
|
height: 200,
|
||||||
|
fill: 'green',
|
||||||
|
name: 'rect',
|
||||||
|
draggable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
parent.add(rect);
|
||||||
|
return rect;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const selectionRectangle = (layer: Layer) => {
|
||||||
|
const selectionRectangle = new Konva.Rect({
|
||||||
|
fill: 'rgba(0,0,255,0.5)',
|
||||||
|
visible: false,
|
||||||
|
listening: false,
|
||||||
|
});
|
||||||
|
layer.add(selectionRectangle);
|
||||||
|
return selectionRectangle;
|
||||||
|
};
|
|
@ -0,0 +1,93 @@
|
||||||
|
import Konva from 'konva/lib';
|
||||||
|
import { Stage } from 'konva/lib/Stage';
|
||||||
|
import { Rect } from 'konva/lib/shapes/Rect';
|
||||||
|
import { Transformer } from 'konva/lib/shapes/Transformer';
|
||||||
|
|
||||||
|
export const stageEvent = (stage: Stage, selectionRectangle: Rect, tr: Transformer) => {
|
||||||
|
let x1 = 0,
|
||||||
|
y1 = 0,
|
||||||
|
x2 = 0,
|
||||||
|
y2 = 0;
|
||||||
|
let selecting = false;
|
||||||
|
stage.on('mousedown touchstart', e => {
|
||||||
|
e.evt.preventDefault();
|
||||||
|
|
||||||
|
x1 = stage.getPointerPosition()!.x;
|
||||||
|
y1 = stage.getPointerPosition()!.y;
|
||||||
|
x2 = stage.getPointerPosition()!.x;
|
||||||
|
y2 = stage.getPointerPosition()!.y;
|
||||||
|
|
||||||
|
selectionRectangle.width(0);
|
||||||
|
selectionRectangle.height(0);
|
||||||
|
selecting = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
stage.on('mousemove touchmove', e => {
|
||||||
|
if (!selecting) return;
|
||||||
|
e.evt.preventDefault();
|
||||||
|
|
||||||
|
x2 = stage.getPointerPosition()!.x;
|
||||||
|
y2 = stage.getPointerPosition()!.y;
|
||||||
|
|
||||||
|
selectionRectangle.setAttrs({
|
||||||
|
visible: true,
|
||||||
|
x: Math.min(x1, x2),
|
||||||
|
y: Math.min(y1, y2),
|
||||||
|
width: Math.abs(x2 - x1),
|
||||||
|
height: Math.abs(y2 - y1),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
stage.on('mouseup touchend', e => {
|
||||||
|
selecting = false;
|
||||||
|
if (!selectionRectangle.visible()) return;
|
||||||
|
e.evt.preventDefault();
|
||||||
|
|
||||||
|
// update visibility in timeout, so we can check it in click event
|
||||||
|
selectionRectangle.visible(false);
|
||||||
|
let shapes = stage.find('.rect');
|
||||||
|
let box = selectionRectangle.getClientRect();
|
||||||
|
let selected = shapes.filter(shape => Konva.Util.haveIntersection(box, shape.getClientRect()));
|
||||||
|
tr.nodes(selected);
|
||||||
|
});
|
||||||
|
|
||||||
|
// clicks should select/deselect shapes
|
||||||
|
stage.on('click tap', function (e) {
|
||||||
|
// if we are selecting with rect, do nothing
|
||||||
|
if (selectionRectangle.visible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if click on empty area - remove all selections
|
||||||
|
if (e.target === stage) {
|
||||||
|
tr.nodes([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do nothing if clicked NOT on our rectangles
|
||||||
|
if (!e.target.hasName('rect')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do we pressed shift or ctrl?
|
||||||
|
const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
|
||||||
|
const isSelected = tr.nodes().indexOf(e.target) >= 0;
|
||||||
|
|
||||||
|
if (!metaPressed && !isSelected) {
|
||||||
|
// if no key pressed and the node is not selected
|
||||||
|
// select just one
|
||||||
|
tr.nodes([e.target]);
|
||||||
|
} else if (metaPressed && isSelected) {
|
||||||
|
// if we pressed keys and node was selected
|
||||||
|
// we need to remove it from selection:
|
||||||
|
const nodes = tr.nodes().slice(); // use slice to have new copy of array
|
||||||
|
// remove node from array
|
||||||
|
nodes.splice(nodes.indexOf(e.target), 1);
|
||||||
|
tr.nodes(nodes);
|
||||||
|
} else if (metaPressed && !isSelected) {
|
||||||
|
// add the node into selection
|
||||||
|
const nodes = tr.nodes().concat([e.target]);
|
||||||
|
tr.nodes(nodes);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
Loading…
Reference in New Issue