0

我是缩放图表(网络图表)的新手,我有几个问题:

  • 我希望能够拖动一个节点并在用户放下它时处理事件。有没有办法做到这一点?我正在查看 onPositionChange 事件,但该事件在拖动过程中会触发多次。无法知道用户何时真正删除了节点。至少我没有找到一种方法来确定这一点。也许我错过了一些东西。
  • 我有一个项目列表,我希望能够将它们拖到图表中并将它们转换为节点。这工作正常,除了当我使用(外部项目的)dragend 事件时,我无法正确设置新创建的节点的 x 和 y 位置。我尝试使用 ClientX 和 ClientY、LayerX 和 LayerY 以及 DragEnd 事件参数提供的其他坐标,但它们都没有将节点定位到释放光标的位置。实现这一目标的最佳方法是什么?

这是我的图表定义:

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
			}
		});

谢谢你。

4

2 回答 2

1

@dpdragnev!我来自 ZoomCharts,所以这是一个权威的答案。:)

  1. 是的,你是对的,我们没有办法说出来。嗯...我可以想到一种方法来实现,但我以前从未尝试过,所以...将事件处理程序附加到 NetChart 的容器元素。将它们附加到pointerup, pointercancel, mouseup, touchend, touchcancel, MSPointerUp, MSPointerCancel。这些都是会中断拖动操作的事件。您可能需要检查哪些也可用,并且只附加到那些。您需要附加到capture阶段,因为 NetChart 将防止冒泡。然后还附加到onPositionChangeNetChart 事件以查看何时开始拖动节点。在onPositoinChange事件检查identifier鼠标事件的字段。这将告诉您哪个指针是拖动的(对于多点触控支持很重要)。所以现在你有一个节点被拖动的事件,一个节点被释放的事件,以及匹配它们的指针标识符。我认为应该工作。
  2. 再次,没有好办法,对不起。但是有一个我们自己用过的技巧。通过查看 NetChart 对象的._impl.scene.centerX._impl.scene.centerY属性,您可以获得场景坐标中图表中心的 x/y 坐标。可以通过.zoom()API 调用完全合法地获得 Zoom。添加一些数学运算,您可以计算出鼠标光标的场景坐标。把你的节点放在那里。请注意,这不是记录在案的方法,并且可以随时停止工作。使用风险自负。
于 2017-04-23T18:41:03.637 回答
0

ZoomCharts 在 1.18.0 (2017-10-05) 版本中为 NetChart 引入了新事件。所有事件都可以在这里找到。

在这里,我准备了一个快速示例,可以将一个节点拖放到其他节点上。在这种情况下,它将在具有方向的节点之间创建链接。

http://jsfiddle.net/cmx907hp/

代码:

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]});
    }
}
于 2018-05-21T13:02:55.280 回答