【问题标题】:d3.v3 scatterplot with all circles the same radiusd3.v3 散点图,所有圆的半径相同
【发布时间】:2014-01-21 11:39:12
【问题描述】:

我发现的每个示例都显示所有散点图的半径都是随机的。是否可以让它们都具有相同的尺寸?如果我尝试静态设置半径,所有圆圈都会非常小(我假设默认半径)。但是,如果我在大多数示例中使用 Math.random() ,则会有大大小小的圆圈。我希望所有的圆圈都很大。有没有办法做到这一点?这是使用 Math.random() 形成图形数据的代码 sn-p(由于某种原因,这可以正常工作):

function scatterData(xData, yData) 
{
  var data = [];

  for (var i = 0; i < seismoNames.length; i++) 
  {
    data.push({
      key: seismoNames[i],
      values: []
    });

    var xVals=""+xData[i];
    xVals=xVals.split(",");
    var yVals=""+yData[i];
    yVals=yVals.split(",");

    for (var j = 0; j < xVals.length; j++) 
    {
      data[i].values.push({
        x: xVals[j], 
        y: yVals[j], 
        size: Math.random()
      });

    }
  }

  return data;
}

Math.random() 输出 0 到 1 之间的值,例如 0.164259538891095 和 0.9842195005008699。我已经尝试将这些作为静态值放在“大小”属性中,但不管是什么圆圈总是很小。有什么我想念的吗?

【问题讨论】:

    标签: javascript d3.js scatter-plot nvd3.js


    【解决方案1】:

    半径以像素为单位。如果您将其设置为小于 1 的值,是的,您将有一个非常小的圆圈。大多数使用随机数的示例也使用比例因子。

    如果你想让所有的圆都有一个恒定的半径,你不需要在数据中设置值,只需在添加半径属性时设置即可。

    不确定您查看的是哪些教程,但请从这里开始:https://github.com/mbostock/d3/wiki/Tutorials

    示例“三个小圆圈”很好地逐步说明了您可以用圆圈做的不同事情: http://mbostock.github.io/d3/tutorial/circle.html

    【讨论】:

    • 感谢您的回复!这是我一直在使用的示例:nvd3.org/ghpages/scatter.html。按照您引导我使用的示例并使用 {var circle = d3.select('#my_graph svg').selectAll("circle"); circle.attr("r", 30);} 改变图例圆半径,但不改变图中圆的半径。
    • 啊,您需要指定您使用的是 NVD3 图表方法——这与自己绘制图表非常不同。我将添加另一个答案。
    • @AmeliaBR 看来真正的问题是在发帖者的第六或第七条评论之后才发现的……而且最重要的通常是最后说的……
    • @VividD 坦率地说,考虑到 NVD3 站点和 github 上完全缺乏文档,我可以看到新用户会感到困惑。但这是真的,很多时候第一个障碍是找出问题所在,而所有人都知道它不起作用......
    【解决方案2】:

    更新: NVD3 API 已更改,现在使用 pointSizepointSizeDomain 等,而不仅仅是 size。在没有完整文档的情况下探索当前 API 的其余逻辑仍然适用。


    对于 NVD3 图表,想法是您所做的所有调整都可以通过调用图表函数本身(或其公共组件)上的方法来完成,然后再调用该函数以在特定容器元素中绘制图表。

    例如,在您链接的示例中,图表函数的初始化如下:

     var chart = nv.models.scatterChart()
                   .showDistX(true)
                   .showDistY(true)
                   .color(d3.scale.category10().range());
    
     chart.xAxis.tickFormat(d3.format('.02f'));
     chart.yAxis.tickFormat(d3.format('.02f'));
    

    .showDistX().showDistY() 开启坐标轴中的刻度线分布; .color() 设置要用于不同类别的颜色系列。下一行访问图表中的默认轴对象并将数字格式设置为两位小数。您可以通过单击"Live Code" page 中的散点图选项来使用这些选项。

    不幸的是,NVD3 图表的制造商don't have a complete documentation 还提供了您可以为每个图表设置的所有其他选项。但是,您可以使用 javascript 本身来让您找出可用的方法。

    检查 NVD3.js 图表对象以确定选项

    打开一个加载 d3 和 nvd3 库的网页。他们网站上的live code page 工作正常。然后打开开发人员的控制台命令行(这取决于您的浏览器,如果您还不知道怎么做,请搜索您的帮助页面)。现在,在内存中新建一个 nvd3 散点图函数:

    var testChart = nv.models.scatterChart();
    

    在我的 (Chrome) 控制台上,控制台将打印出您刚刚创建的函数的全部内容。它很有趣,但很长,难以一目了然。而且大部分代码都是封装的,所以你不能轻易改变它。您想知道可以更改哪些属性。因此,在控制台的下一行运行此代码:

    for (keyname in testChart){console.log(keyname + " (" + typeof(testChart[keyname]) + ")");}
    

    控制台现在应该整齐地打印出您可以从该图表函数访问的所有方法和对象的名称。其中一些将有自己的方法和可以访问的对象;通过运行相同的例程来发现它们是什么,但将 testChart 替换为 testChart.propertyName,如下所示:

    for (keyname in testChart.xAxis){console.log(keyname + " (" + typeof(testChart.xAxis[keyname]) + ")");}
    

    回到你的问题。我上面建议的小程序不会按任何顺序对属性名称进行排序,但浏览列表你应该会看到三个与大小相关的选项(这是示例用来设置半径的数据变量)

    • 尺寸(功能)
    • sizeDomain(函数)
    • 大小范围(函数)

    域和范围是D3 scales 使用的术语,所以这给了我关于它们做什么的提示。由于您不想缩放点,所以让我们从仅查看 size 属性开始。如果您在控制台中键入以下内容:

    testChart.size
    

    它应该打印回该函数的代码。对于我们感兴趣的内容而言,它的信息量不是很大,但它确实向我表明 NVD3 遵循 D3 的 getter/setter 格式:如果您调用 .property(value),则将属性设置为该值,但如果您调用 .property() 而不使用任何参数,它将返回该属性的当前值。

    所以要找出默认的size属性是什么,调用不带参数的size()方法:

    testChart.size()
    

    它应该打印出function (d) { return d.size || 1},它告诉我们默认值是一个在数据中查找大小属性的函数,如果它不存在则返回常量 1。更一般地说,它告诉我们size 方法设置的值决定了图表如何从数据中获取 size 值。如果您的数据没有 d.size 属性,则默认值应该给出一个恒定的大小,但为了更好地衡量,您应该在初始化代码中调用 chart.size(1); 来告诉图表函数不要费心尝试从数据中确定大小,只需使用常数值。

    回到实时代码散点图可以测试出来。编辑代码以添加到 size 调用中,如下所示:

     var chart = nv.models.scatterChart()
                   .showDistX(true)
                   .showDistY(true)
                   .color(d3.scale.category10().range())
                   .size(1);
    
     chart.xAxis.tickFormat(d3.format('.02f'));
     chart.yAxis.tickFormat(d3.format('.02f'));
    

    添加额外的调用成功地将所有点设置为相同的大小 - 但该大小绝对不是 1 像素,因此显然正在进行一些缩放。

    获得更大点的第一个猜测是将chart.size(1) 更改为chart.size(100)。然而,什么都没有改变。默认比例显然是根据数据计算它的域,然后输出到标准的大小范围。这就是为什么你不能通过将每个数据元素的大小值设置为 0.99 来获得大圆圈的原因,即使当一些数据为 0.01 而一些数据为 0.99 时这会创建一个大圆圈。显然,如果你想改变输出大小,你也必须在图表上设置.sizeRange() 属性。

    在控制台中调用testChart.sizeRange() 以找出默认值并不是很丰富:默认值为空(不存在)。所以我只是做了一个猜测,与 D3 线性刻度.range() 函数一样,预期的输入是一个由最大值和最小值组成的二元素数组。由于我们想要一个常数,因此最大值和最小值将相同。所以在我更改的实时代码中:

    .size(1);
    

    .size(1).sizeRange([50,50]);
    

    现在发生了一些事情!但是这些点仍然很小:绝对不是 50 像素的半径,它看起来更接近 50 平方像素的面积。在根据数据调整大小时,根据面积计算大小是有意义的,但这意味着要设置一个恒定大小,您需要计算出您想要的近似面积:在示例中,高达 200 的值看起来不错,但值您的选择将取决于图表的大小以及数据点彼此之间的接近程度。

    --ABR

    附:我在您的问题中添加了 NVD3.js 标签;以后在询问有关 NVD3 图表功能的问题时,请务必将其用作您的主要标签。

    【讨论】:

      猜你喜欢
      • 2014-02-01
      • 1970-01-01
      • 2012-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-14
      • 1970-01-01
      • 2018-09-08
      相关资源
      最近更新 更多