2014-07-14 34 views
0

是否可以指定范围点来处理不同大小的圆以便距离是通过其边而不是中心来计算的?不同大小的圆的范围点

例如,这是我得到:

()表示圈边缘; < ---->代表由rangePoints

( <----)---(-><-)-------(->) 

计算的距离^注意它看起来像中圈更接近最左边的圆圈。相反,我倒要看看以下内容:

(  )<---->()<---->() 

的功能,我使用看起来像:

var y = d3.scale.ordinal() 
    .domain(data.map(function(d) { return d.value})) 
    .rangePoints([0, width]); 

var item = chart.append("g") 
    .selectAll("circle") 
     .data(data) 
    .enter().append("circle") 
    .attr("cy", function(d) { return y(d.value); }) 
+0

这在D3中不受支持,您需要某种封装或自定义实现。 –

回答

1

正如@LarsKotthoff提到的,你会需要一个自定义的规模实施,做这个。

在这种情况下,这将会有点复杂,因为规模不仅需要考虑域中元素的数量,而且还要考虑它们的确切值是什么。基本上,在计算每个元素的位置时,您的比例尺需要考虑每个元素之前占用的空间,并且还包括基于总空间划分的间隔区。

下面是它必须做的:

首先,建立规模,你需要做到以下几点:

  • 查找输出范围跨越的总距离
  • 找到域中每个元素的直径的总和
  • 把这些差异找到残留克可用空间
  • 除以(元素的数量减一)的空格数的剩余空间

这将使您对每个圆之间所需的空间的值。

然后,对于每个元素:

  • 查找前述圆的直径的总和
  • 乘以前述圆
  • 数目的间隔的值添加的总和这些到当前圈的半径

因此,您的比例尺将需要基于索引以及基准。

这是一个相当粗糙的实现,假定域是半径的数组,范围为你输出的端点:

var customPointScale = function() { 
    var domain, 
     range; 
    // returned scale fn takes datum and index 
    function scale(d,i) { 
    var n = domain.length, 
     totalSpan = range[1] - range[0], 
     // loop over the domain to find the sum of the diameters 
     sumDiameters = (function(){ 
      var output = 0; 
      for (var a = 0; a < n; a++) { 
      // add radius * 2 to get diameter 
      output += domain[a] * 2; 
      } 
      return output; 
     })(), 
     remainingSpace = totalSpan - sumDiameters, 
     // there is one fewer space than the number of elements 
     spacer = remainingSpace/(n-1); 

    // loop over the elements that came before to find the distance spanned 
    var distanceSoFar = (function() { 
     var output = 0; 
     for(var a = 0; a < i; a++) { 
     // diameter + spacer, for each element traversed 
     output += (domain[a] * 2) + spacer; 
     } 
     return output; 
    })(); 

    // return the radius plus the distance traversed so far 
    return d + distanceSoFar; 
    } 
    scale.domain = function(_) { 
    if (!arguments.length) return domain; 
    domain = _; 
    return scale; 
    }; 
    scale.range = function(_) { 
    if (!arguments.length) return range; 
    range = _; 
    return scale; 
    }; 
    return scale; 
}; 

下面是一个使用了一些示例数据本实施JSBin。希望有所帮助。

+0

是的,想出了类似的东西,谢谢你。我会将此标记为已接受,因为您在此处有一个工作示例。 – funseiki