Создание диаграмм с использованием 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>
Другие вопросы по тегам