KineticJS - 带有连接的可拖动形状
Posted
技术标签:
【中文标题】KineticJS - 带有连接的可拖动形状【英文标题】:KineticJS - draggable shape with connections 【发布时间】: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 的新中心。再次感谢您 【参考方案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()
都可以。以上是关于KineticJS - 带有连接的可拖动形状的主要内容,如果未能解决你的问题,请参考以下文章