【问题标题】:KineticJS - draggable shape with connectionsKineticJS - 带有连接的可拖动形状
【发布时间】:2014-07-14 00:31:33
【问题描述】:

我对 KineticJS 还很陌生,并且在可拖动形状(圆形)和一条线(将这个形状与另一个连接起来)方面遇到了问题。 移动可拖动形状后,我无法重绘线条。也许你们中的一个可以给我一个提示。

这是我的代码:

<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="kinetic.js"></script>
<link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300' rel='stylesheet' type='text/css'>
<style type="text/css">
    html, body {
        font-family: 'Open Sans Condensed', Arial, sans-serif;
        font-size: 14px;
        background: #EFEFEF;
        width: 100%;
        height: 100%;
    }

    h1 {
        text-align: center;
        font-size: 30px;
    }

    #canvas {
        display: block;
        background: white;
        border: 1px solid #CCC;
        margin: 50px auto;
        width: 700px;
        height: 500px;
    }
</style>
</head>
<body>


<h1>kinetic.js test</h1>

<div id="canvas"></div>

<script defer="defer">

    /**
     * get circle center coordinates
     *
     * @desc    gets coordinates of circle center
     * @param   shapeId     -   id of circle
     * @returns {object}    -   object with x and y coordinates
     */
    function getCircleCenterCoordinates(shapeId) {

        var shape = getShapeById(shapeId);

        if(typeof shape == 'object') {

            return {x: shape.shape.attrs.x, y: shape.shape.attrs.y}

        }

    }


    /**
     * get shape by id
     *
     * @desc    searches for given shape id and returns the matching
     * @param   shapeId     -   id of the circle
     * @returns {*}
     */
    function getShapeById(shapeId) {

        var result = jQuery.grep(shapes, function(e) { return e.id == shapeId; });

        if(result.length == 1) {

            return result[0];

        } else {

            return null;

        }

    }


    /**
     * draw
     *
     * @desc    draw shapes
     * @retuns  {void}
     */
    function draw() {

        // add shapes to the layer and register event listeners
        for(var i = 0; i < shapes.length; i++) {

            var shapeObj = shapes[i];


            // add shape to layer
            circleLayer.add(shapeObj.shape);

            // register event listeners
            for(var n = 0; n < shapeObj.events.length; n++) {

                var eventObj = shapeObj.events[n];

                shapeObj.shape.on(eventObj.type, eventObj.callback);

            }

            // draw connections
            for(var m = 0; m < shapeObj.connections.length; m++) {

                var connectionObj = shapeObj.connections[m];

                // get ids
                var fromId  = shapeObj.id;
                var toId    = connectionObj.to;

                // check if connection is already drawn
                if(fromId > toId) {

                    // do not draw it again
                    continue;

                }

                // get coordinates
                var fromCoordinatesObj  = getCircleCenterCoordinates(fromId);
                var toCoordinatesObj    = getCircleCenterCoordinates(toId);

                // check coordinates
                if(typeof fromCoordinatesObj != 'object' || typeof toCoordinatesObj != 'object') {

                    // was not able to get valid coordinates
                    continue;

                }

                // update / set line points for this connection
                connectionObj.line.attrs.points = [fromCoordinatesObj.x, fromCoordinatesObj.y, toCoordinatesObj.x, toCoordinatesObj.y];

                // add line to layer
                connectorLayer.add(connectionObj.line);

            }

        }


        // add the layers to the stage
        stage.add(connectorLayer);
        stage.add(circleLayer);

    }


    /**
     * init shapes and layers
     * -------------------------------------------------------------------------------------------------------
     */

    // create stage
    var stage = new Kinetic.Stage({
        container: 'canvas',
        width: 700,
        height: 500
    });


    // create layers
    var circleLayer     = new Kinetic.Layer();
    var connectorLayer  = new Kinetic.Layer();


    // define shapes
    var shapes = [

        {
            id:     1001,
            label:  'me',
            shape:  new Kinetic.Circle({
                x: stage.getWidth() / 2 - 200,
                y: stage.getHeight() / 2 + 100,
                radius: 70,
                fill: '#DDD',
                stroke: '#EFEFEF',
                strokeWidth: 10,
                draggable: true
            }),
            events: [
                {type: 'mouseover', callback: function() { console.log('over 1');}}
            ],
            connections: [
                {to: 2001, line: new Kinetic.Line({stroke: '#333', strokeWidth: 2})},
                {to: 3001, line: new Kinetic.Line({stroke: '#333', strokeWidth: 2})},
                {to: 4001, line: new Kinetic.Line({stroke: '#333', strokeWidth: 2})}
            ]

        },
        {
            id:     2001,
            label:  'you',
            shape:  new Kinetic.Circle({
                x: stage.getWidth() / 2 + 200,
                y: stage.getHeight() / 2 + 100,
                radius: 70,
                fill: '#DDD',
                stroke: '#EFEFEF',
                strokeWidth: 10,
                draggable: true
            }),
            events: [
                {type: 'mouseover', callback: function() { console.log('over 2');}}
            ],
            connections: [
                {to: 1001, line: new Kinetic.Line({stroke: '#333', strokeWidth: 2})},
                {to: 3001, line: new Kinetic.Line({stroke: '#333', strokeWidth: 2})},
                {to: 4001, line: new Kinetic.Line({stroke: '#333', strokeWidth: 2})}
            ]
        },
        {
            id:     3001,
            label:  'her',
            shape:  new Kinetic.Circle({
                x: stage.getWidth() / 2,
                y: stage.getHeight() / 2 - 100,
                radius: 70,
                fill: '#DDD',
                stroke: '#EFEFEF',
                strokeWidth: 10,
                draggable: true
            }),
            events: [
                {type: 'mouseover', callback: function() { console.log('over 3');}}
            ],
            connections: [
                {to: 1001, line: new Kinetic.Line({stroke: '#333', strokeWidth: 2})},
                {to: 2001, line: new Kinetic.Line({stroke: '#333', strokeWidth: 2})}
            ]
        },
        {
            id:     4001,
            label:  'his',
            shape:  new Kinetic.Circle({
                x: 100,
                y: 150,
                radius: 70,
                fill: '#DDD',
                stroke: '#EFEFEF',
                strokeWidth: 10,
                draggable: true
            }),
            events: [
                {type: 'mouseover', callback: function() { console.log('over 4');}},
                {type: 'dragend', callback: function() { console.log(this.getPosition()); console.log(shapes[3]);  }}
            ],
            connections: [
                {to: 1001, line: new Kinetic.Line({stroke: '#333', strokeWidth: 2})},
                {to: 2001, line: new Kinetic.Line({stroke: '#333', strokeWidth: 2})}
            ]
        }

    ];


    // draw shapes
    draw();

</script>

【问题讨论】:

  • 为什么不使用 Kinetic.Group 呢?
  • 你好,Elsa,感谢您的回复!我对 KineticJs 很陌生。检查手册后,它不像我的问题的解决方案。如果我将我的连接线从节点 A 到节点 B 放在一个组中,另一个节点不会知道它,对吗?我只想要一个“粘性”线到节点 A 和 B,当节点 A 或节点 B 移动时,它也会移动。谢谢。
  • 好吧,如果你创建一个组,然后添加任何你想要的节点(例如线和圆圈)并将它们设置为可拖动,当你拖动一个时,整个组将一起移动物品。这就是我理解你到现在为止想要做的事情 :-) 不客气,祝你好运!
  • 啊,现在我明白了,你误解了我的问题:) 我只想移动连接到我移动的圆圈的线。圆圈 A 移动。圆圈 B 和 C 仍处于相同位置。但是从 B 和 C 到 A 的线必须移动到 A 的新中心。再次感谢您

标签: javascript canvas draggable kineticjs


【解决方案1】:

以下是保持 2 个节点与 Kinetic.Line 连接的方法。

  • 创建一个 Kinetic.Line 并设置点以连接您希望连接的 2 个节点。

  • 在您希望连接的 2 个节点上侦听 dragmove 事件。

  • 在拖动任一节点时,重置连接线的点以再次连接到 2 个节点。

这样的……

NodeA.on('dragmove',function(){
    connectorAB.points([NodeA.x(),nodeA.y(),nodeB.x(),nodeB.y()]);
    layer.draw();
});

// same thing for NodeB

【讨论】:

  • 谢谢markE!它几乎可以工作。当我移动我的节点时,线条将按预期绘制,但旧线条仍然出现。我必须清洁层或其他东西吗?我目前只是更新我的 KineticJs 线对象中的点,然后调用 draw() 函数。谢谢
  • 如果圆圈和连接器位于不同的层,则必须更新两个层。无论哪种方式stage.draw() 都可以。
猜你喜欢
  • 2012-09-30
  • 2016-02-17
  • 1970-01-01
  • 2012-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-06
相关资源
最近更新 更多