I want to be able to drag and drop a group of objects (rect, text, circle, etc.) and get their new x,y position in order to keep them in that new position.
I've checked the documentation for Konva.jS
for dragging a group, but with no luck.
What I did try is I can get the new relative x,y
position for the group (group.attrs.x, group.attrs.y
) but it is not exactly the same as the real position of any of the object inside the group. I've tried to tweak it by incrementing x,y
but still it is different for different size of objects (in case of text with different length).
In the above image, +22
was added to the new x and y respectively that I got from the group using group.attrs.x, group.attrs.y
, but the resulting circle
(dot) is different for two different objects (rect
or text
).
I need to get (near) exact x,y
position of the circle in this case. How can I do it?
I have included here a simple demo for dragging a group of objects, at the drop it is drawing a circle
from the group
's new x,y
positions. And there you can see the difference.
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
var shapesLayer = new Konva.Layer();
var colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];
var groups = [];
for (var i = 0; i < 2; i++) {
var group = new Konva.Group({
draggable: true,
});
var box = new Konva.Rect({
x: i * 200 + 20,
y: i * 180 + 20,
width: 100,
height: 50,
name: colors[i],
fill: colors[i],
stroke: 'black',
strokeWidth: 1,
});
var txt = new Konva.Text({
x:i*200 + 20,
y: i*180 + 20,
text: 'Java',
fontSize: 26
});
var circle = createCircle(i * 200 + 20, i * 180 + 20);
group.add(box);
group.add(txt);
group.add(circle);
groups.push(group);
}
for (let i = 0; i < groups.length; i++) {
let group = groups[i];
console.log("dragging...");
group.on('mouseover', function () {
document.body.style.cursor = 'pointer';
});
group.on('mouseout', function () {
document.body.style.cursor = 'default';
console.log("dropped.");
//-------------------------QUESTION IS HERE-------------------------------
//EN: I can get the group's new coordinates by group.attrs.x, group.attrs.y, but
shapesLayer.add(createCircle(group.attrs.x, group.attrs.y));
// this line is getting the new relative position of the group and creating a new circle but it is far from the real x,y of the original circle inside the group being dragNdropped.
// how can I get the new coordinates of the group child elements?
//UZ: mana shu joyida group drop qilinadi, shunda rect va boshqa objectlarning x,y positionlari kerak.
});
shapesLayer.add(group);
}
function createCircle(posx,posy){
return new Konva.Circle({
x: posx,
y: posy,
radius: 3,
fill: 'red',
stroke: 'red',
strokeWidth: 0,
});
}
stage.add(shapesLayer);
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva@8.3.5/konva.min.js"></script>
<meta charset="utf-8" />
<title>Konva Drag and Drop a Group Demo</title>
</head>
<body>
<div id="container"></div>
<script>
</script>
</body>
</html>
First thing that stands out is you are using mouseout
as the dropped according to the documentation there is a dragend
, I think that is what we should be using on this case:
https://konvajs.org/docs/events/Binding_Events.html
To get the position you are looking for you need to add the group and your rectangle, take a look at the example below, it should all make sense, let me know if you have any questions.
var stage = new Konva.Stage({container: 'container', width: 200, height: 200});
var shapesLayer = new Konva.Layer();
var colors = ['orange', 'green'];
for (var i = 0; i < 2; i++) {
var group = new Konva.Group({ draggable: true });
var box = new Konva.Rect({
x: i * 100 + 20, y: i * 80 + 20,
width: 80, height: 50, fill: colors[i]
});
var circle = createCircle(i * 100 + 20, i * 80 + 20, 5, "blue");
group.add(box);
group.add(circle);
group.on('dragend', dragend);
shapesLayer.add(group);
}
function dragend(evt) {
var rect = evt.target.children[0].attrs
var x = evt.target.attrs.x + rect.x
var y = evt.target.attrs.y + rect.y
shapesLayer.add(createCircle(x, y, 2, rect.fill));
}
function createCircle(x, y, radius, fill) {
return new Konva.Circle({ x, y, radius, fill });
}
stage.add(shapesLayer);
body {
margin: 0;
padding: 0;
}
<script src="https://unpkg.com/konva@8.3.5/konva.min.js"></script>
<div id="container"></div>