javascript - 如何在dragmove中将一个组分成两个子组?

标签 javascript kineticjs

我有一个包含多个矩形的组。当我指向该组的一个矩形并拖动它时,我想在该点分离该组并拥有两个子组。我已成功在以下 jsfiddle 示例中完成了一个简单的案例,但是我使用的是 dblclick 事件。发生的情况是,我使用 (var shape = evt.targetNode;) 获取单击的矩形的位置,然后重新创建这两个组。我通过触发 2 个事件来做到这一点。

我的问题是:

  1. 此操作可以通过触发单个事件(dragmove 事件)来完成吗?这样,每当用户开始拖动该组时,根据拖动的方向,该组就会“自动”分离。 更重要的是,我想知道每当用户开始拖动组时,根据拖动的方向,组将“自动”分离。
  2. 对于这个版本,我使用kinetic-v5.0.1.min.js。但是,当我使用最新的kineticjs版本(kinetic-v5.1.0.min.js)时,由于某种原因(var shape = evt.targetNode;)不再工作。我在这里错过了什么吗?

jsfiddle链接: 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();

});

运行示例: http://jsfiddle.net/maik18/tbYLe/16/embedded/result/

最佳答案

  1. 是的,您可以使用 Dragmove 事件将一个组分割为 2 个组:

    • 确定拖动是向左还是向右移动。

    • 将 children 分成 2 组:(1) 应该被拖动的 children ;(2) 应该在初始位置保持静止的 children 。

    • 创建一个新组并将固定子项放入该新组中。

    • 继续拖动原始组中的其他子项(无需创建 2 个新组 - 只需重复使用原始组,因为您已经在拖动它了)。

  2. “使用事件委托(delegate)时,evt.targetNode 已更改为 evt.target”(请参阅​​版本 5.1.0 的更改日志:https://github.com/ericdrowell/KineticJS/wiki/Change-Log)

注意:您可以使用 stage.getIntersection(mousePosition) 来确定鼠标下方的矩形。

这里是带注释的代码和演示: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>

关于javascript - 如何在dragmove中将一个组分成两个子组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23461578/

相关文章:

javascript - 根据其他属性动态限制 TypeScript 中对象属性的类型

javascript - 单击可拖动层顶部时如何获得准确的指针位置?

fiddle 更新后 JavaScript 和 jQuery 无法工作

javascript - 正则表达式选择没有空格的文本有限制

javascript - 附加 html 的不同方式?

javascript - Vuex:无法更改 Action 中深度嵌套的状态数据

javascript - Kinetic.js 在楔形内绘制文本(带旋转)

ios - 如何防止 sceneFunc() 每次都清除上下文?

kineticjs - 无法从保存的 KineticJS Canvas 状态检索图像属性

javascript .replace() 方法无法正常工作