I have a group which contains a number of rectangles. When I point a rectangle of the group and drag it, I want to separate the group at that point and have two subgroups. I have managed to do a simple case in the following jsfiddle example, however I am using a dblclick event. What happens is that I get the position of the rectangle clicked by using (var shape = evt.targetNode;) and then I recreate the two groups. I am doing this by firing 2 events.
My questions are:
jsfiddle link: http://jsfiddle.net/maik18/tbYLe/16/
group.on('dblclick', function() {
var groups = stage.find('Group');
var rects = stage.find('Rect');
var group1= groups[0].getChildren().slice(0,globalPosition);
var group2= groups[0].getChildren().slice(globalPosition,6);
var newGroup1 = new Kinetic.Group({
x: group1[0].getAbsolutePosition().x,
y: group1[0].getAbsolutePosition().y-40,
draggable:true
});
var newGroup2 = new Kinetic.Group({
x: group2[0].getAbsolutePosition().x-globalPosition*100,
y: group2[0].getAbsolutePosition().y-40,
draggable: true
});
for (var i=0; i < group1.length; i++){
newGroup1.add(group1[i]);
}
for (var i=0; i < group2.length; i++){
newGroup2.add(group2[i]);
}
writeMessage(newGroup2.getChildren()[0].getAbsolutePosition().x);
shapesLayer.add(newGroup1);
shapesLayer.add(newGroup2);
groups[0].getChildren().splice(0,6);
shapesLayer.draw();
groups[0].destroy();
});
running example: http://jsfiddle.net/maik18/tbYLe/16/embedded/result/
Yes, you can use the dragmove event to sub-divide a group into 2 groups:
determine if the drag is moving left or right.
divide the children into 2 groups (1) Children that should be dragged & (2) Children that should should remain stationary at initial position.
create a new group an put the stationary children in that new group.
continue dragging the other children in the original group (no need to create 2 new groups--just reuse the original group since you're already dragging it anyway).
"evt.targetNode has changed to evt.target when using event delegation" (see the change log for version 5.1.0: https://github.com/ericdrowell/KineticJS/wiki/Change-Log)
Note: You can use stage.getIntersection(mousePosition) to determine which rectangle is under the mouse.
Here's annotated code and a Demo: http://jsfiddle.net/m1erickson/8fuPJ/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.1.0.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
// create a stage and a layer
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// make a template group
// all new groups will be a clone of this template group
// this template group knows how to sub-divide its children
var templateGroup=new Kinetic.Group({
draggable:true,
});
//
templateGroup.on('dragstart',function(){
// save the x-coordinate where the mouse started the drag
// this x is used to determine if the drag is right or left
var pos=stage.getPointerPosition();
this.startX=pos.x;
// determine which rectangle is under the mouse
// this rect will be the dividing point between this and a new group
this.dragRect=stage.getIntersection(pos);
// create a new group cloned from the templateGroup
// (the templateGroup has code necessary to divide itself)
if(this.dragRect){
this.newGroup=templateGroup.clone();
this.newGroup.position(this.initialPosition);
this.newGroup.initialPosition=this.initialPosition;
this.isDragging=true;
}
});
//
templateGroup.on('dragmove',function(){
// performance:
// just do this function once
// isDragging will be false if this Fn has already been done once
if(!this.isDragging){return;}
var pos=stage.getPointerPosition();
// performance:
// just return if the drag hasn't gone right or left at least 1 pixel
if(pos.x==this.startX){return;}
// clear the isDragging flag
this.isDragging=false;
// flag indicating whether the mouse moved left or right
var isRight=(pos.x>this.startX);
// get the x coordinate of the rect under the cursor
// this "x" is used to divide the current group in two
var dragRectX=this.dragRect.x();
// an array that will hold children to be move to the new group
var newGroupChildren=[];
// get the children of this group
var children=this.getChildren();
// enumerate all children and add any "non-dragging" rects to
// the array of children to be moved to the new group
children.each(function(child){
if(isRight && child.x()<dragRectX){
newGroupChildren.push(child);
}
if(!isRight && child.x()>dragRectX){
newGroupChildren.push(child);
}
});
// move "stationary" children from this group to the new group
for(var i=0;i<newGroupChildren.length;i++){
newGroupChildren[i].moveTo(this.newGroup);
}
// add the new group to the layer
layer.add(this.newGroup);
// redraw the layer
layer.draw();
});
//
templateGroup.on("dragend",function(){
// store the resting position of this group
// any future new subgroups will be positioned at this position
this.initialPosition=this.position();
});
// add a group to the stage
var group=templateGroup.clone();
group.initialPosition=templateGroup.position();
layer.add(group);
// testing...add 6 boxes to the group
for(var i=0;i<6;i++){
var rect=new Kinetic.Rect({
id:i,
x:i*30+50,
y:100,
width:25,
height:20,
fill:randomColor(),
stroke: 'black',
strokeWidth: 2,
});
group.add(rect);
}
layer.draw();
// utility function to create a random color
function randomColor(){
return('#'+Math.floor(Math.random()*16777215).toString(16));
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Drag a rectangle to create a sub-group</h4>
<div id="container"></div>
</body>
</html>