dpdragnev
dpdragnev

Reputation: 2111

ZoomCharts drag and drop

I am new to zoom charts (net charts) and I have a couple of questions:

Here is my chart definition:

this.chart = new ZoomCharts.NetChart({
			container: chartContainer,
			area: {
				height: null,
				style: { fillColor: "rgba(14,33,40,0.9)" }
			},
			data: {
				preloaded: {
					"nodes": this.nodes,
					"links": this.links
				}
			},
			events: {
				onRightClick: function (event: any, args: any) {
					//set up the customer context menu
					event.preventDefault();
				},
				onHoverChange: function (event: any, args: any) {
					var content = "";
					if (args.hoverNode) {
						content = args.hoverNode.data.description;
					}
					infoElementVisible = !!content;
					infoElement.innerHTML = content;
					//delay the showing
					if (infoElementVisible) {
						setTimeout(() => {
							infoElement.style.display = infoElementVisible ? "block" : "none";
						}, 1000);
					} else {
						infoElement.style.display = infoElementVisible ? "block" : "none";
					}			
				}
			},
			style: {
				nodeStyleFunction: function (node: any) {
					if (node.selected) {
						node.lineColor = "yellow";
						node.lineWidth = 3;
						node.radius = node.radius * 1.5;
					} else {
						node.lineColor = null;
						node.lineWidth = 0;
					}

					node.userLock = true;
					node.label = node.data.name;
					if (node.data.auras == "Selection GNQ") {
						node.fillColor = "darkorange";
					} else {
						node.fillColor = "cyan";
					}
				},
				linkStyleFunction: function (link: any) {
					link.fromDecoration = "circle";
					link.toDecoration = "arrow";
					link.radius = 5;
				},
				node: {
					radius: 50,
					imageCropping: true,
					shadowBlur: 15,
					shadowColor: "#262626",
					fillColor: "rgba(44,233,233,0.8)"
				},
				nodeHovered: {
					shadowColor: "white",
					shadowBlur: 15,
				},
				nodeLabelScaleBase: 25,
				nodeSelected: {
					lineColor: null
				},
				selection: {
					fillColor: null,
					lineColor: null
				},
				nodeFocused: {
					shadowColor: "yellow",
					shadowBlur: 15
				},
				nodeLabel: {
					textStyle: { font: '24px Arial' }
				}
			},
			theme: ZoomCharts.NetChart.themes.dark,
			layout: {
				mode: 'static',
				nodeSpacing: 100
			}
		});

Thank you.

Upvotes: 0

Views: 285

Answers (2)

Eizens
Eizens

Reputation: 46

ZoomCharts introduced new events for NetChart with 1.18.0 (2017-10-05) release. All the events can be found here.

Here I have prepared a quick example where it is possible to drag and drop a node over the other nodes. In this case it would create a link between nodes with direction.

http://jsfiddle.net/cmx907hp/

Code:

var ndata = {
        "nodes":[
            {"id":"n1", "loaded":true, "style":{"label":"Node1", "fillColor":"rgba(236,46,46,0.8)"}, "x":0, "y":0, "locked": true},
            {"id":"n2", "loaded":true, "style":{"label":"Node2", "fillColor":"rgba(47,195,47,0.8)" }, "x":200, "y":50},
            {"id":"n3", "loaded":true, "style":{"labeL":"Node3", "fillColor":"rgba(28,124,213,0.8)" }, "x":100, "y":100},
            {"id":"n4", "loaded":true, "style":{"labeL":"Node4", "fillColor":"rgba(236,46,46,1)" }, "x":250, "y":250, "locked": true}
        ],
        "links":[
            {"id":"l1","from":"n1", "to":"n2"}
        ]
    };



    var chart = new NetChart({
        container: document.getElementById("demo"),
        area: { height: $(window).height() - 120 },
        data: { preloaded: ndata },
        events: {
            onClick: function(e, args) {
                console.log("click", args);
            },
            onPointerDown: function(e, args) {
                console.log("down", args);
            },
            onPointerUp: function(e, args) {
                console.log("up", args);
                if(args.clickNode) {
                    var node = args.clickNode;
                    var onodes = getOverlappingNodes(node);
                    connectNodes(node, onodes);
                }
            },
            onPointerDrag: function(e, args) {
                console.log("drag", args);
            },
            onPointerMove: function(e, args) {
                //this is basically onMouseMove, but originally was named like this.
            }
        },
        navigation: {
          //  mode: "showall"
        }
    });


    function getOverlappingNodes(node) {
    if(!node) return;

    var found = [];
    var dim = chart.getNodeDimensions(node);

    var x = x1 = dim.x;
    var y = y1 = dim.y;
    var radius = dim.radius;

    //get all nodes:
    var nodes = chart.nodes();
    for (var i = 0; i < nodes.length; i++) {
        var obj = nodes[i];
        //skip dragged node itself.
        if(obj.id === node.id) {
            continue;
        }
        var odim = chart.getNodeDimensions(obj);
        var x0 = odim.x;
        var y0 = odim.y;

        var m = Math.sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)) < radius;
        if(m) {
            found.push(obj);
        }
    }
    return found;
}


function connectNodes(node, onodes) {
    for (var i = 0; i < onodes.length; i++) {
        var onode = onodes[i];

        var link = {"id": "link-" + node.id + "-" + onode.id,"from": node.id, "to": onode.id, style: {"toDecoration": "arrow"}}
        chart.addData({nodes:[],links: [link]});
    }
}

Upvotes: 0

Vilx-
Vilx-

Reputation: 107012

Hi @dpdragnev! I'm from ZoomCharts, so this is kind of an authoritative answer. :)

  1. Yes, you're right, we don't have a way of telling that. Hmm... I can think of one hack to get there, but I've never tried that before, so... Attach event handlers to the container element of NetChart. Attach them to pointerup, pointercancel, mouseup, touchend, touchcancel, MSPointerUp, MSPointerCancel. These are all events that will interrupt a drag operation. You'll probably need to check which ones are available too and only attach to those. You need to attach to the capture phase, because NetChart will prevent bubbling. Then also attach to the onPositionChange event of NetChart to see when a node drag is starting. In the onPositoinChange event check the identifier field of the mouse event. That will tell you which pointer is the one dragging (important for multi-touch support). So now you have an event when a node is being dragged, and an event when a node is being released, and the pointer identifier to match them up. Should work, I think.
  2. Again, no good way, sorry. But there's a hack we've used ourselves. By looking at the ._impl.scene.centerX and ._impl.scene.centerY properties of your NetChart object you can get the x/y coordinates of the center of the chart in scene coordinates. Zoom can be obtained perfectly legally with a .zoom() API call. Add some math and you can figure out the scene coordinates of your mouse cursor. Put your node there. Note that this is NOT a documented approach and can stop working at any time. Use at your own risk.

Upvotes: 1

Related Questions