2017-06-02 125 views
0

我正在使用两个圆圈进行d3视觉工作,其中较小的圆圈放置在大圆圈半径的边缘上。这个代码位于这里https://codepen.io/ajblack/pen/KqKpde。我有一个200像素的方块SVG,我将这些圆圈放入,然后我有两个值,uAssets和uAssetsCom,它们指示圆圈的大小。创建的比率,以确保较大的圆使用此代码在200像素的平方拟合:位于大圆半径边缘的D3小圆圈

var ratioToFit = (200/uAssets)/2; 

然后我使用余弦计算大圆的外半径和外结合的SVG之间的距离以45度的角容器:

var key = 100*((1-Math.cos(45*Math.PI/180))/Math.cos(45*Math.PI/180)) 

要放置的小圆圈我计算cxcy属性作为内圆的半径加上这个“关键”。

d3.select("#uAssetComCircle") 
    .attr("cx", function(d){return (d.radius+key);}) 
    .attr("cy", function(d){return (d.radius+key);}) 

这地方靠近较大圆的半径内圆,但它是关于2个像素关闭。我可以用一个硬编码的2像素加到cxcy来弥补这一点,但我觉得我不应该这样做。

我算了算吗?

+0

我相信错误是在“关键”计算。我没有完全追踪它,但尝试将角度从45改为60,并且你会发现它没有做你想做的事 – cmonkey

回答

1

我的解决方案在这里 https://codepen.io/ajblack/pen/qjOqmQ公布。 该实现使用缩放和变换的建议。我遇到的问题是对毕达哥拉斯定理的滥用。我的大圆的半径是100px,我可以用它作为直角三角形的斜边。我知道我希望我的小圆圈以45度角偏移,所以我知道三角形的另外两边将是相同的长度。使用公式a²+b²=c²其中a和b是相同的值,c等于100px减去我的小圆的半径,我可以很容易地解出a和b。

var uAssets = 17; 
var uAssetsCom = 3; 
var scale = d3.scaleLinear() 
.domain([0,uAssets]) 
.range([0,100]); 
d3.select("#uAssetComCircle") 
    .attr("cx", function(d) { 
    return Math.sqrt(Math.pow(100-scale(uAssetsCom),2)/2); 
    }) 
    .attr("cy", function(d) { 
    return Math.sqrt(Math.pow(100-scale(uAssetsCom),2)/2); 
    }); 

成品看起来像这样small circle set inside large circle radius

1

不知道我完全按照你的计算,但这里有一个快速重构,介绍几件事情:

  1. 的译文从SVG
  2. 一D3规模的中心点基地所有的绘图处理从用户坐标到像素坐标的计算。

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script> 
 
    <link rel="stylesheet" href="style.css" /> 
 
    <script src="script.js"></script> 
 
</head> 
 

 
<body> 
 
    <script> 
 
    var uAssets = 17; 
 
    var uAssetsCom = 3; 
 

 
    var svgContainer = d3.select("body").append("svg") 
 
     .attr("width", 200) 
 
     .attr("height", 200) 
 
     .attr('id', 'circleContainer') 
 
     .append("g") 
 
     .attr("transform", "translate(" + 100 + "," + 100 + ")") 
 

 
    var scale = d3.scaleLinear() 
 
     .domain([0,uAssets]) 
 
     .range([0,100]); 
 

 
    var jsonCircles = [{ 
 
     "radius": uAssets, 
 
     "color": "green", 
 
     "id": "uAssetCircle" 
 
    }, { 
 
     "radius": uAssetsCom, 
 
     "color": "purple", 
 
     "id": "uAssetComCircle" 
 
    }]; 
 

 
    var circles = svgContainer.selectAll("circle") 
 
     .data(jsonCircles) 
 
     .enter() 
 
     .append("circle"); 
 

 
    var circleAttributes = circles 
 
     .attr("r", function(d) { 
 
     return scale(d.radius); 
 
     }) 
 
     .attr("id", function(d) { 
 
     return d.id 
 
     }) 
 
     .style("fill", function(d) { 
 
     return d.color; 
 
     }); 
 

 
    d3.select("#uAssetComCircle") 
 
     .attr("cx", function(d) { 
 
     return scale(uAssets) * Math.cos(45 * (Math.PI/180)); 
 
     }) 
 
     .attr("cy", function(d) { 
 
     return scale(uAssets) * Math.sin(45 * (Math.PI/180)); 
 
     }) 
 
    </script> 
 
</body> 
 

 
</html>

+0

为什么你建议使用翻译来将圆圈居中而不是应用'cx'和' cy'properties中心的圆?我一直在使用本主题[链接](http://love2d.org/forums/viewtopic.php?t=2803&p=29282)中描述的方法来计算200像素边界框的拐角和100像素半径圆。该测量是我的代码中的关键值所代表的。 – ablackman93

+0

我能够通过创建一个三角形(大半径 - 较小的半径)并解决两个相等长度的边来解决我的问题。我的'cx'和'cy'测量值是以这种方式计算的。 – ablackman93

+1

@ ablackman93,我将整个绘图区域转换为SVG的中心,因为我使用的trig函数的中心有一个原点。我很高兴你明白了。你应该有足够的信誉*自己回答*你自己的问题;请这样做,并记得在48小时后回来接受它。我很想读它。 – Mark