page: 📄 拖拽缩放
This commit is contained in:
parent
28dc17df40
commit
3977b7e410
|
@ -0,0 +1,153 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue';
|
||||
import { useWindowSize } from '@vueuse/core';
|
||||
import Konva from 'konva/lib';
|
||||
|
||||
const { width, height } = useWindowSize();
|
||||
|
||||
const initial = () => {
|
||||
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
|
||||
const layer = new Konva.Layer();
|
||||
|
||||
const rect1 = new Konva.Rect({
|
||||
x: 60,
|
||||
y: 60,
|
||||
width: 100,
|
||||
height: 90,
|
||||
fill: 'red',
|
||||
name: 'rect',
|
||||
draggable: true,
|
||||
});
|
||||
layer.add(rect1);
|
||||
|
||||
const rect2 = new Konva.Rect({
|
||||
x: 180,
|
||||
y: 200,
|
||||
width: 100,
|
||||
height: 200,
|
||||
fill: 'green',
|
||||
name: 'rect',
|
||||
draggable: true,
|
||||
});
|
||||
layer.add(rect2);
|
||||
|
||||
// 添加缩放
|
||||
const tr = new Konva.Transformer();
|
||||
layer.add(tr);
|
||||
tr.nodes([rect1, rect2]);
|
||||
|
||||
const selectionRectangle = new Konva.Rect({
|
||||
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(() => {
|
||||
initial();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="container"></div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
Loading…
Reference in New Issue