0

我正在尝试修改这个项目的鱼眼,以便我可以使用半径函数来增加鱼眼大小。我的目标是在鼠标周围看到更多更大的细胞。当前实现不支持半径函数。如果我使用圆形而不是比例,我可以使用半径函数。但在这种情况下,我不知道如何使用循环。

无论哪种方式,感谢您的帮助:)

谢谢!

4

1 回答 1

3

圆形鱼眼的半径参数为放大效果设定了界限。相比之下,在尺度/笛卡尔鱼眼中,整个图都被修改了。焦点单元被放大,其他单元根据它们离焦点的距离被压缩。没有边界,压缩继续平滑(逐渐压缩)直到绘图的边缘。见http://bost.ocks.org/mike/fisheye/#cartesian

如果您想要的是靠近焦点的单元格没有被压缩太多(因此您仍然可以有效地比较相邻单元格),那么要更改的参数是失真参数。较低的失真将减少焦点单元的放大量,因此为相邻单元留出更多空间。默认失真参数为 3,您使用的是更高的值,这会增加焦点单元的放大倍率,但会牺牲所有其他参数。

如果更改失真不满意,请尝试使用d3.fisheye.scale(d3.scale.sqrt);更改比例类型 这将改变决定图像放大倍率在您远离焦点时如何变化的功能。(我无法让其他比例类型工作——日志给出错误,并且使用幂比例无法设置指数。)

编辑

经过额外的尝试,我对更改输入比例类型的结果不满意。我误解了这将如何影响它:它不会改变失真的比例函数,而是改变原始数据,因此焦点上方的点与焦点下方的点相比,变化是不同的。您作为鱼眼比例参数提供的比例类型应该是对数据有意义的基础比例类型,并且与鱼眼效果不同。

相反,我尝试了一些自定义代码来将指数添加到计算中。要了解它是如何工作的,首先需要分解原始函数:

鱼眼刻度的原始代码是:

function fisheye(_) {
  var x = scale(_),
      left = x < a,
      range = d3.extent(scale.range()),
      min = range[0],
      max = range[1],
      m = left ? a - min : max - a;
  if (m == 0) m = max - min;
  return a + (left ? -1 : 1) * m * (d + 1) / (d + (m / Math.abs(x - a)));
}

_输入值,scale通常是已设置域和范围的线性标度,a是输出范围内的焦点,d是失真参数。

换句话说:确定在扭曲比例上绘制值的点:

  • 根据默认/未失真比例计算值的范围位置;
  • 计算它与焦点的距离({distance}, Math.abs(x-a));
  • 计算图形边缘与焦点之间的距离({total distance}, m);
  • 返回值从焦点偏移 {total distance} 乘以
    (d + 1) / (d + ({total distance} / {distance}) );
  • 根据该值是低于还是高于焦点进行适当调整。

对于在焦点和未失真比例上图形边缘之间的中间点的输入点,内部分数 {total distance}/{distance} 将等于 2。因此,外部分数将为(d+1)/(d+2)。如果d为 0(无失真),这将等于 1/2,并且输出点也将位于焦点和图形边缘之间的中间。随着失真参数d增加,该分数也增加:在 处d=1,输出点将是从焦点到图形边缘的 2/3;在 处d=2,它将是图边缘的 3/4;等等。

相反,当输入值非常接近焦点时,{distance} 接近于 0,因此内部分数接近无穷大,外部分数接近 0,因此返回的点将非常接近焦点。

最后,当输入值非常接近图的边缘时,{distance}接近{total distance},并且内外分数都会接近1,所以返回的点也会非常接近边缘图的。

我们要保留的最后两个身份。我们只想改变两者之间的关系——随着输入点越来越远离焦点和靠近图形边缘,焦点的偏移量如何变化。更改失真参数会同等地更改近值和远值的失真量。如果您减少失真参数,您也会减少整体放大倍数,因为所有数据仍然必须适合相同的空间。

OP 希望降低焦点附近细胞之间的放大率变化率。减少失真参数可以做到这一点,但只能通过整体降低放大倍率来实现。理想的方法是改变距焦点的距离和失真程度之间 的关系。

我对同一功能的更改代码是:

function fisheye(_) {
    var x = scale(_),
        left = x < a,
        range = d3.extent(scale.range()),
        min = range[0],
        max = range[1],
        m = left ? a - min : max - a,
        dp = Math.pow(d, p);
    if (m == 0) return left? min : max;
    return a + (left ? -1 : 1) *  m  * 
      Math.pow( 
        (dp + 1)
      / (dp + (m / Math.abs(x-a) ) )
      , p);
}

我改变了两件事:我将分数提高(d + 1)/(d + {total distance}/{distance})到一个幂,我还将原始d值替换为它提高到相同的指数 ( dp)。第一个变化是改变关系,第二个只是调整,以便给定的失真参数将具有大致相同的整体放大效果,而不管功率参数如何。

如果分数接近零,则升幂的分数仍然接近零,如果分数接近一,则仍然接近一,因此基本恒等式保持不变。但是,当功率参数小于 1 时,变化率在边缘会变浅,而在中间会变陡。对于大于 1 的功率参数,边缘处的变化率将非常陡峭,而在焦点附近则较浅。

此处示例: http
://codepen.io/AmeliaBR/pen/zHqac 水平鱼眼刻度具有平方根幂函数 ( p = 0.5),而垂直具有平方函数 ( p = 2)。两者都具有相同的未调整失真参数 ( d = 6)。

平方根函数的效果是即使最远的列仍然有一些可见的宽度,但焦点附近的列宽变化是显着的。2 函数的效果是远离焦点的行被压缩到几乎不可见的高度,但焦点上方和下方的行仍然很大。我认为后一个版本实现了@piedpiper 所希望的。

当然,我还为.power鱼眼比例添加了一个函数来设置p参数,并将默认值设置为p1,这将给出与原始鱼眼比例相同的结果。我使用该power方法的名称来区分幂标度exponent方法,如果它们的基础标度(失真之前)具有幂关系,则将使用该方法。

于 2014-02-10T00:30:40.627 回答