d3.js共同特征图表 [英] d3.js Common Trait Chart

查看:82
本文介绍了d3.js共同特征图表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




http://jsfiddle.net/NYEaX/1791/

In creating a relationship chart - that shows common traits - I am struggling to create the curved arcs that will match the position of the dots.

What is the best way of plotting these arcs so it dips below the horizon?

   var data = [{
     "userName": "Rihanna",
     "userImage": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSTzjaQlkAJswpiRZByvgsb3CVrfNNLLwjFHMrkZ_bzdPOWdxDE2Q",
     "userDetails": [{
       "Skills & Expertise": [{
         "id": 2,
         "tag": "Javascript"
       }, {
         "id": 3,
         "tag": "Design"
       }],
       "Location": [{
         "id": 0,
         "tag": "London"
       }, {
         "id": 1,
         "tag": "Germany"
       }],
       "Company": [{
         "id": 0,
         "tag": "The Old County"
       }]
     }]
   }, {
     "userName": "Brad",
     "userImage": "https://lh3.googleusercontent.com/-XdASQvEzIzE/AAAAAAAAAAI/AAAAAAAAAls/5vbx7yVLDnc/photo.jpg",
     "userDetails": [{
       "Skills & Expertise": [{
         "id": 0,
         "tag": "JAVA"
       }, {
         "id": 1,
         "tag": "PHP"
       }, {
         "id": 2,
         "tag": "Javascript"
       }],
       "Location": [{
         "id": 0,
         "tag": "London"
       }],
       "Company": [{
         "id": 0,
         "tag": "The Old County"
       }, {
         "id": 1,
         "tag": "Bakerlight"
       }]
     }]
   }]



   var viz = d3.select("#viz")
     .append("svg")
     .attr("width", 600)
     .attr("height", 600)
     .append("g")
     .attr("transform", "translate(40,100)")


   var patternsSvg = viz
     .append('g')
     .attr('class', 'patterns');


   function colores_google(n) {
     var colores_g = ["#f7b363", "#448875", "#c12f39", "#2b2d39", "#f8dd2f"];
     return colores_g[n % colores_g.length];
   }


   function getRadius(d) {
     var count = d.commonTags.split(",").length;
     var ratio = count * 2.3;

     if (count == 1) {
       ratio = 8;
     }

     return ratio;
   }






   //create patterns for user images
   $.each(data, function(index, value) {
     var defs = patternsSvg.append('svg:defs');
     defs.append('svg:pattern')
       .attr('id', index + "-" + value.userName.toLowerCase())
       .attr('width', 1)
       .attr('height', 1)
       .append('svg:image')
       .attr('xlink:href', value.userImage)
       .attr('x', 0)
       .attr('y', 0)
       .attr('width', 75)
       .attr('height', 75);


     console.log(value.userDetails[0]);


   });




   //create common data assement


   var data1 = [{
     "commonLabel": "Groups",
     "commonTags": "test1, test2, test3, test4, test5, test6, test7"
   }, {
     "commonLabel": "Skills & Expertise",
     "commonTags": "test1, test2, test3, test1, test2, test3, test1, test2, test3, test1, test2"
   }, {
     "commonLabel": "Location",
     "commonTags": "test1"
   }, {
     "commonLabel": "Company",
     "commonTags": "test1"
   }]



   //add curved paths
   var distanceBetween = 70;

   var pathStart = -400;

   var path = viz.append("svg:g").selectAll("path")
     .data(data1)

   path
     .enter().append("svg:path")
     .attr("class", function(d) {
       return "link "
     })

   path.attr("d", function(d, i) {
     var sx = 0;
     var tx = 235;

     var sy = 120;
     var ty = 120;


     pathStart += 125;

     var dx = 0;
     var dy = getRadius(d) + (distanceBetween * i) - pathStart;
     var dr = Math.sqrt(dx * dx + dy * dy);

     console.log("dy", dy);

     return "M" + sx + "," + sy + "A" + dr + "," + dr + " 0 0,1 " + tx + "," + ty;
   });
   //add curved paths





   //create circles to hold the user images
   var circle = viz.append("svg:g").selectAll("circle")
     .data(data);

   //enter
   circle
     .enter()
     .append("svg:circle")
     .attr("id", function(d) {
       return d.userName;
     })
     .attr("r", function(d) {
       return "30";
     })
     .attr("cx", function(d, i) {
       return "235" * i;
     })
     .attr("cy", function(d, i) {
       return "120";
     })
     .style("fill", function(d, i) {
       return "url(#" + i + "-" + d.userName.toLowerCase() + ")";
     })


   var distanceBetween = 65;
   var circle = viz.append("svg:g").selectAll("circle")
     .data(data1);

   //enter
   circle
     .enter()
     .append("svg:circle")
     .attr("id", function(d) {
       return d.commonLabel;
     })
     .attr("r", function(d) {
       return getRadius(d);
     })
     .attr("cx", function(d, i) {
       return 125;
     })
     .attr("cy", function(d, i) {
       return distanceBetween * i;
     })
     .style("fill", function(d, i) {
       return colores_google(i);
     });



   var text = viz.append("svg:g").selectAll("g")
     .data(data1)

   text
     .enter().append("svg:g");

   text.append("svg:text")
     .attr("text-anchor", "middle")
     .attr("x", "125")
     .attr("y", function(d, i) {
       return getRadius(d) + 15 + (distanceBetween * i);
     })
     .text(function(d) {
       return d.commonLabel;
     })
     .attr("id", function(d) {
       return "text" + d.commonLabel;
     });



   var counters = viz.append("svg:g").selectAll("g")
     .data(data1)

   counters
     .enter().append("svg:g");

   counters.append("svg:text")
     .attr("text-anchor", "middle")
     .attr("x", "125")
     .attr("y", function(d, i) {
       return ((getRadius(d) / 2) + (distanceBetween * i)) - 3;
     })
     .text(function(d) {
       var count = d.commonTags.split(",").length;
       if (count > 1) {
         return count;
       }
     })
     .attr("id", function(d) {
       return "textcount" + d.commonLabel;
     });

解决方案

Live demo:

http://jsfiddle.net/blackmiaool/p58a0w3h/1/

First of all, you should remove all the magic numbers to keep the code clean and portable.

This one, for example:

pathStart += 125;

How to draw arcs correctly is a math problem. The code is as blow:

path.attr("d", function (d, i) {
    const sx = 0;    
    const sy = height/2;

    const a=width/2;
    const b = ((data1.length-1)/2-i)*distanceBetween;
    const c = Math.sqrt(a * a + b * b);
    const angle=Math.atan(a/b);
    let r;
    if(b===0){
        r=0;
    }else{
        r=1/2*c/Math.cos(angle);//also equals c/b*(c/2)
//  r=c/b*(c/2);
    }

    return `M${sx},${sy} A${r},${r} 0 0,${b>0?1:0} ${width},${height/2}`;
});

And the diagram:

这篇关于d3.js共同特征图表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆