Skip to main content

HTML5 Canvas 复杂拖放边界

为了限制使用 Konva 拖拽和放置的节点在区域内的移动,我们可以使用 dragmove 事件来定义节点无法越过的边界。

提示:您可以使用 shape.absolutePosition() 方法来获取/设置节点的绝对位置,而不是相对的 xy

说明: 拖动和放置浅蓝色矩形,观察它被限制在 y = 50 的虚拟边界以下。拖动和放置黄色矩形,观察它被限制在一个虚拟圆形内。

import Konva from 'konva';

const stage = new Konva.Stage({
  container: 'container',
  width: window.innerWidth,
  height: window.innerHeight,
});

const layer = new Konva.Layer();

const blueGroup = new Konva.Group({
x: 30,
y: 70,
draggable: true,
});

// 限制在 y=50 之下
blueGroup.on('dragmove', () => {
blueGroup.y(Math.max(blueGroup.y(), 50));
});

// 限制在圆形内
const yellowGroup = new Konva.Group({
x: stage.width() / 2,
y: 70,
draggable: true,
});

yellowGroup.on('dragmove', () => {
const x = stage.width() / 2;
const y = 70;
const radius = 50;
const pos = yellowGroup.absolutePosition();
const scale = radius / Math.sqrt(Math.pow(pos.x - x, 2) + Math.pow(pos.y - y, 2));

if (scale < 1) {
yellowGroup.x(Math.round((pos.x - x) * scale + x));
yellowGroup.y(Math.round((pos.y - y) * scale + y));
}
});

const blueText = new Konva.Text({
fontSize: 26,
fontFamily: 'Calibri',
text: '限制在下面',
fill: 'black',
padding: 10,
width: 150,
align: 'center',
});

const blueRect = new Konva.Rect({
width: 150,
height: 72,
fill: '#aaf',
stroke: 'black',
strokeWidth: 4,
});

const yellowText = new Konva.Text({
fontSize: 26,
fontFamily: 'Calibri',
text: '限制在圆内',
fill: 'black',
padding: 10,
width: 150,
align: 'center',
});

const yellowRect = new Konva.Rect({
width: 150,
height:72,
fill: 'yellow',
stroke: 'black',
strokeWidth: 4,
});

blueGroup.add(blueRect).add(blueText);
yellowGroup.add(yellowRect).add(yellowText);

layer.add(blueGroup);
layer.add(yellowGroup);
stage.add(layer);