svg").remove();var width = $("#svg").width(), height = 700, duration = 500, i = 0;var tree = d3.layout.tree() _d3 v7 tree 收缩">
赞
踩
包含代码点:
效果:
代码:
- //清空SVG中的内容
- d3.select("#svg>svg").remove();
-
- var width = $("#svg").width(),
- height = 700,
- duration = 500,
- i = 0;
-
- var tree = d3.layout.tree()
- .size([width, height])
- .separation(function (a, b) { //获取或设置相邻结点间的间隔(不仅限于兄弟结点)
- if(a.depth == 1 && b.depth == 1){
- return 3;
- }else{
- return (a.parent == b.parent ? 1:2);
- };
- });
-
- //定义布局方向(横向)
- var diagonal = d3.svg.diagonal()
- .projection(function(d) {
- return [d.y, d.x];
- });
-
- // 拖拽及扩大缩放
- var zoom = d3.behavior.zoom()
- .scaleExtent([.5, 3])
- .on('zoom', function () {
- svg.attr("transform", "translate(" + (d3.event.translate[0]+150) +","+ d3.event.translate[1] + ") scale(" + d3.event.scale + ")");
- });
-
- var svg = d3.select("#svg").append("svg")
- .call(zoom) //给svg绑定zoom事件
- .attr("width", width)
- .attr("height", height)
- .append("g")
- .attr("transform", "translate(150, 0)"); // 将图整体下移,以防止顶部节点被遮挡
- //根据数据生成nodes集合
- var nodes = tree.nodes(this.analyzeList);
- //记录现在的位置
- nodes.forEach(function(d){
- d.x0 = d.x;
- d.y0 = d.y;
- });
- //获取node集合的关系集合
- var links = tree.links(nodes);
- links.forEach(function (d) {
- d.target.y = d.target.y+100;
- if(d.source.depth==4 && d.source.children && d.source.children.length>0){ //携带附件
- d.target.y = d.target.y+200;
- };
- });
- //为关系集合设置贝塞尔曲线连接
- var link = svg.selectAll(".link")
- .data(links)
- .enter()
- .append("path")
- .attr("class", "link")
- .attr("d", function(d) {
- let x0 = d.source.x,
- y0 = d.source.y,
- x1 = d.target.x,
- y1 = d.target.y- 55,
- r = y1 - y0;
- return `M ${y0},${x0} C ${y0 + r / 2},${x0} ${y0 + r / 2},${x1} ${y1},${x1}`;
- });
-
- var node = svg.selectAll(".node")
- .data(nodes)
- .enter()
- .append("g")
- .attr("class", "node")
- .attr("transform", function (d) {
- return "translate(" + (d.y-50) + "," + d.x + ")";
- })
- .on("click", nodeClick);
-
- // 绘制矩形与文字
- node.append("rect")
- .attr('width', function(d){
- let width = 0;
- if(d.depth==0 || d.depth==1){
- width = 100;
- }else if(d.children && d.children.length>0){
- width = 15;
- angular.forEach(d.name, function (te) {
- if(/[^A-Za-z0-9]/.test(te)){
- width += 12;
- }else{
- width += 6;
- };
- });
- };
- return (width>100)?100:width;
- })
- .attr('height', function(d){
- return d.depth==0 || d.depth==1?'40':'14';
- })
- .attr('y', function(d){
- return d.depth==0 || d.depth==1?'-20':'-8';
- })
- .attr('x', function(d){
- return d.depth==0 || d.depth==1?'-30':'0';
- })
- .attr('ry', 5)
- .attr('rx', 5)
- .attr('fill', function(d){
- let fill = '';
- if(d.depth==0){
- fill = '#e04a4a';
- }else if(d.depth==1){
- fill = '#c79329';
- }else{
- fill = 'white';
- };
- return fill;
- })
- .attr('stroke', function(d){
- let stroke = '';
- if(d.depth==0){
- stroke = 'red';
- }else if(d.depth==1){
- stroke = '#a57107';
- }else{
- stroke = 'white';
- };
- return stroke;
- })
- .attr('strokeWidth', '2px');
-
- node.append("circle")
- .attr("r", 4.5)
- .attr('fill', function(d){
- let fill = '';
- if(d.depth==0 || d.depth==1){
- fill = 'none';
- }else if(d.click){
- fill = $rootScope.theme.chartColor || '#0073BA';
- }else{
- fill = '#faaa65';
- };
- return fill;
- })
- .attr('stroke', function(d){
- let stroke = '';
- if(d.depth==0 || d.depth==1){
- stroke = 'none';
- }else if(d.click){
- stroke = $rootScope.theme.chartColor || '#0073BA';
- }else{
- stroke = '#faaa65';
- };
- return stroke;
- })
- .attr('strokeWidth', function(d){
- return d.depth==0 || d.depth==1?'0':'2px';
- });
-
- node.append("text")
- .attr('y', function(d){
- return d.depth==0 || d.depth==1?'5':'4';
- })
- .attr("x", function (d) {
- return d.depth==0 || d.depth==1?'20':'10';
- })
- .attr("text-anchor", function(d){
- return d.depth==0 || d.depth==1?'middle':'start';
- })
- .attr('fill', function(d){
- return d.depth==0 || d.depth==1?'white':'';
- })
- .text(function (d) {
- let text = "";
- if(d.children && d.name.length>7){
- text = d.name.slice(0,7)+'...';
- }else{
- text = d.name+(d.key?":":'');
- };
- if(d.click && (d.name == d.key)){
- text = "";
- };
- if(d.parent && d.parent.name == "hash值"){
- text = d.name.slice(0,10) + "...";
- };
- if(d.name == "不同样本Dropper相同文件"){
- text = d.name.slice(0,7) + "...";
- };
- if(d.children){
- text += ' ['+d.children.length+']';
- };
- return text;
- })
- .append("a")
- .attr("class", function (d) {
- return d.click?"click":"noclick";
- })
- .attr("fill", function(d){
- return d.click?($rootScope.theme.chartColor || '#0073BA'):'';
- })
- .text(function (d) {
- return d.key;
- })
- .on("click", function (d) {
- d3.event.stopPropagation();
- if(d.type == 'ip' || d.type == 'domain'){
- $scope.sideBox.query(d3.event, d.key);
- };
- });
-
- node.append("title")
- .text(function (d) {
- let title = d.name;
- if(d.allName) title = d.allName;
- if(d.key && d.key != d.name) title = d.name+":"+d.key;
- return title;
- });
-
- // 节点点击,隐藏或显示子节点
- function nodeClick(d){
- if(d.children || d._children){
- if (d.children){
- d._children = d.children;
- d.children = null;
- }else{
- d.children = d._children;
- d._children = null;
- };
- update(d);
- };
- };
- //更新布局
- function update(source) {
- //计算新树的布局
- var nodes = tree.nodes(self.analyzeList).reverse(),
- links = tree.links(nodes);
- //树的深度这里树d.y。树的宽度最大720,要分四层,所以每层就乘180
- nodes.forEach(function(d) {
- d.y = d.depth * 180;// 树的x,y倒置了,所以这里Y其实是横向的
- });
- links.forEach(function (d) {
- d.target.y = d.target.y+100;
- if(d.source.depth==4 && d.source.children && d.source.children.length>0){ //携带附件
- d.target.y = d.target.y+200;
- };
- });
- //数据连接,根据id绑定数据
- var node = svg.selectAll("g.node")
- .data(nodes, function(d) {
- return d.id //最初新点开的节点都没有id
- || (d.id = ++i); //为没有id的节点添加上ID
- });
- //点击时增加新的子节点
- var nodeEnter = node.enter().append("g")
- .attr("class", "node")
- .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
- .on("click", nodeClick);
- // 绘制矩形与文字
- nodeEnter.append("rect")
- .attr('width', function(d){
- let width = 0;
- if(d.depth==0 || d.depth==1){
- width = 100;
- }else if(d.children && d.children.length>0){
- width = 15;
- angular.forEach(d.name, function (te) {
- if(/[^A-Za-z0-9]/.test(te)){
- width += 12;
- }else{
- width += 6;
- };
- });
- };
- return (width>100)?100:width;
- })
- .attr('height', function(d){
- return d.depth==0 || d.depth==1?'40':'14';
- })
- .attr('y', function(d){
- return d.depth==0 || d.depth==1?'-20':'-8';
- })
- .attr('x', function(d){
- return d.depth==0 || d.depth==1?'-30':'0';
- })
- .attr('ry', 5)
- .attr('rx', 5)
- .attr('fill', function(d){
- let fill = '';
- if(d.depth==0){
- fill = '#e04a4a';
- }else if(d.depth==1){
- fill = '#c79329';
- }else{
- fill = 'white';
- };
- return fill;
- })
- .attr('stroke', function(d){
- let stroke = '';
- if(d.depth==0){
- stroke = 'red';
- }else if(d.depth==1){
- stroke = '#a57107';
- }else{
- stroke = 'white';
- };
- return stroke;
- })
- .attr('strokeWidth', '2px');
-
- nodeEnter.append("circle")
- .attr("r", 4.5)
- .attr('fill', function(d){
- let fill = '';
- if(d.depth==0 || d.depth==1){
- fill = 'none';
- }else if(d.click){
- fill = $rootScope.theme.chartColor || '#0073BA';
- }else{
- fill = '#faaa65';
- };
- return fill;
- })
- .attr('stroke', function(d){
- let stroke = '';
- if(d.depth==0 || d.depth==1){
- stroke = 'none';
- }else if(d.click){
- stroke = $rootScope.theme.chartColor || '#0073BA';
- }else{
- stroke = '#faaa65';
- };
- return stroke;
- })
- .attr('strokeWidth', function(d){
- return d.depth==0 || d.depth==1?'0':'2px';
- });
-
- nodeEnter.append("text")
- .attr('y', function(d){
- return d.depth==0 || d.depth==1?'5':'4';
- })
- .attr("x", function (d) {
- return d.depth==0 || d.depth==1?'20':'10';
- })
- .attr("text-anchor", function(d){
- return d.depth==0 || d.depth==1?'middle':'start';
- })
- .attr('fill', function(d){
- return d.depth==0 || d.depth==1?'white':'';
- })
- .text(function (d) {
- let text = "";
- if(d.children && d.name.length>7){
- text = d.name.slice(0,7)+'...';
- }else{
- text = d.name+(d.key?":":'');
- };
- if(d.click && (d.name == d.key)){
- text = "";
- };
- if(d.parent && d.parent.name == "hash值"){
- text = d.name.slice(0,10) + "...";
- };
- if(d.name == "不同样本Dropper相同文件"){
- text = d.name.slice(0,7) + "...";
- };
- if(d.children){
- text += ' ['+d.children.length+']';
- };
- return text;
- })
- .append("a")
- .attr("class", function (d) {
- return d.click?"click":"noclick";
- })
- .attr("fill", function(d){
- return d.click?($rootScope.theme.chartColor || '#0073BA'):'';
- })
- .text(function (d) {
- return d.key;
- })
- .on("click", function (d) {
- d3.event.stopPropagation();
- if(d.type == 'ip' || d.type == 'domain'){
- $scope.sideBox.query(d3.event, d.key);
- };
- });
-
- nodeEnter.append("title")
- .text(function (d) {
- let title = d.name;
- if(d.allName) title = d.allName;
- if(d.key && d.key != d.name) title = d.name+":"+d.key;
- return title;
- });
- //原有节点更新到新位置
- var nodeUpdate = node.transition()
- .duration(duration)
- .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
- nodeUpdate.select("text")
- .style("fill-opacity", 1);
-
- //折叠节点的子节点收缩回来
- var nodeExit = node.exit().transition()
- .duration(duration)
- .attr("transform", function(d) {
- return "translate(" + source.y + "," + source.x + ")";
- })
- .remove();
- nodeExit.select("circle")
- .attr("r", 1e-6);
- nodeExit.select("text")
- .style("fill-opacity", 1e-6);
- //数据连接,根据目标节点的id绑定数据
- var link = svg.selectAll("path.link")
- .data(links, function(d) { return d.target.id; });
- //增加新连接
- link.enter().insert("path", "g")
- .attr("class", "link")
- .attr("d", function(d) {
- var o = {x: source.x0, y: source.y0};
- return diagonal({source: o, target: o});
- });
- //原有连接更新位置
- link.transition()
- .duration(duration)
- .attr("d", diagonal);
- //折叠的链接,收缩到源节点处
- link.exit().transition()
- .duration(duration)
- .attr("d", function(d) {
- var o = {x: source.x, y: source.y};
- return diagonal({source: o, target: o});
- })
- .remove();
- // 把旧位置存下来,用以过渡
- nodes.forEach(function(d) {
- d.x0 = d.x;
- d.y0 = d.y;
- });
- };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。