Создание диаграмм с использованием KineticJS
Я работаю над простым редактором диаграмм с использованием KineticJS. Я хотел бы использовать два отдельных холста для области палитры (которая содержит несколько Kinetic.Groups, представляющих различные узлы сети, которые я мог бы создать), и область диаграмм, где я могу добавлять узлы из палитры с помощью перетаскивания, а затем добавить соединения между различными узлами в качестве конкретных точек привязки. У меня возникают проблемы с вычислением процесса перетаскивания с холста палитры (стационарного) Kinetic.Groups на другой холст, содержащий область построения диаграмм. Я предполагаю, что мне нужно запустить событие dragstart для объектов палитры (хотя я не хочу, чтобы они сами перетаскивались), а затем сделать что-то вроде создания непрозрачной копии объекта палитры, которую можно перетаскивать и, наконец, упал в область построения диаграмм (с полной непрозрачностью).
Можно ли перетаскивать группы за пределы границ постановочных холстов? Может быть, мне нужно сгенерировать изображение, когда я начинаю перетаскивать его из палитры, перетаскивать это изображение поверх, а затем создавать другую группу при перетаскивании в область построения диаграмм.
Знает ли кто-нибудь о каких-либо примерах, которые могут указывать мне правильное направление, или кто может предложить некоторое понимание (даже код) необходимого процесса. Я искал примеры KineticJS, но не могу найти достаточно, чтобы заставить меня работать.
1 ответ
Вот один из способов перетаскивания узлов из исходной палитры в группу назначения:
Скрипка: http://jsfiddle.net/m1erickson/xtVyL/
Узлы сети представлены маленькими значками (которые на самом деле являются небольшими кинетическими объектами изображения).
Пользователь может перетащить любой значок из исходной палитры в любую группу назначения.
Группы - это только определенные области на холсте, но они могут быть Kinetc.Groups для большей гибкости.
Во время события dragend в целевой группе создается новая дублирующаяся копия перетаскиваемого значка.
После завершения события dragend исходный значок палитры автоматически перемещается из вновь созданного дубликата значка, который можно перетаскивать вокруг целевой группы (но не за пределами этой группы).
Вот код и скрипка: http://jsfiddle.net/m1erickson/xtVyL/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.5.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// image loader
var imageURLs=[];
var imagesOK=0;
var imgs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackru/tempPC.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackru/tempServer.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackru/tempRouter.png");
loadAllImages();
function loadAllImages(callback){
for (var i = 0; i < imageURLs.length; i++) {
var img = new Image();
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK==imageURLs.length ) {
start();
}
};
img.src = imageURLs[i];
}
}
// top icon positions
var nextIconX=20;
var nextIconY=20;
// define groups
var groups=[];
groups.push({x:0,y:100,w:175,h:250,fill:"skyblue"});
groups.push({x:175,y:100,w:175,h:250,fill:"cornsilk"});
// add boundary info to each group
// draw colored rect to show group area
for(var i=0;i<groups.length;i++){
var g=groups[i];
g.left=g.x;
g.right=g.x+g.w;
g.top=g.y;
g.bottom=g.y+g.h;
var rect=new Kinetic.Rect({
x:g.x,
y:g.y,
width:g.w,
height:g.h,
fill:g.fill,
stroke:"gray"
});
layer.add(rect);
}
// hittest for each group
function groupHit(x,y){
for(var i=0;i<groups.length;i++){
var g=groups[i];
if(x>g.left && x<g.right && y>g.top && y<g.bottom){return(i);}
}
return(-1);
}
function start(){
makePaletteIcon(imgs[0]);
makePaletteIcon(imgs[1]);
makePaletteIcon(imgs[2]);
layer.draw();
}
function makePaletteIcon(img){
// make an icon that stays in the pallette tray
var fixedIcon=newImage(nextIconX,nextIconY,img,false);
layer.add(fixedIcon);
// make an icon that is dragged from the tray to a group
var dragIcon=makeDraggableIcon(nextIconX,nextIconY,img);
layer.add(dragIcon);
// calc the next icon position
nextIconX+=(img.width+20);
}
function makeDraggableIcon(x,y,img){
var i=newImage(x,y,img,true);
//
i.trayX=x;
i.trayY=y;
//
i.setOpacity(0.50);
i.on("dragend",function(){
var x=this.getX();
var y=this.getY();
// if this pallette icon was not dropped in a group
// put the icon back in the tray and return
var hit=groupHit(x,y);
if(hit==-1){
this.setPosition(this.trayX,this.trayY);
return;
}
// add a copy of this icon to the drop group
var component=newImage(x,y,this.getImage(),true);
// set drag limits
var group=groups[hit];
component.maxDragLeft=group.left;
component.maxDragRight=group.right;
component.maxDragTop=group.top;
component.maxDragBottom=group.bottom;
// limit component dragging to inside the assigned group
component.setDragBoundFunc(function(pos) {
var xx=pos.x;
var yy=pos.y;
var w=this.getWidth();
var h=this.getHeight();
if(pos.x<this.maxDragLeft){xx=this.maxDragLeft;}
if(pos.x+w>this.maxDragRight){xx=this.maxDragRight-w;}
if(pos.y<this.maxDragTop){yy=this.maxDragTop;}
if(pos.y+h>this.maxDragBottom){yy=this.maxDragBottom-h;}
return{ x:xx, y:yy };
});
layer.add(component);
// move the dragIcon back into the pallette tray
this.setPosition(this.trayX,this.trayY);
layer.draw();
});
return(i);
}
// make a new Kinetic.Image
function newImage(x,y,img,isDraggable){
var i=new Kinetic.Image({
image:img,
x: x,
y: y,
width: img.width,
height: img.height,
draggable:isDraggable
});
return(i);
}
}); // end $(function(){});
</script>
</head>
<body>
<p>Drag any icon from top into blue or yellow group</p>
<div id="container"></div>
</body>
</html>