Plottable.js 的基础数学 101 散点图

Basic math 101 scatter plot with Plottable.js

如何使用 Plottable.js 制作如下图所示的基本散点图?

样式无所谓,默认的Plottable.js就可以了。

window.onload = function() {
  var coordinates = [
    {
      x:"-5", 
      y:"3"
    }, {
      x:"2", 
      y:"-1,5"
    }, {
      x:"5", 
      y:"2,5"
    }
  ];
  
  var xScale = new Plottable.Scale.Linear();
  var yScale = new Plottable.Scale.Linear();
  var colorScale = new Plottable.Scale.Color("10");

  var xAxis = new Plottable.Axis.Numeric(xScale, "bottom");
  var yAxis = new Plottable.Axis.Numeric(yScale, "left");

  var plot = new Plottable.Plot.Scatter(xScale, yScale)
                      .addDataset(coordinates)
                      .project("x", "", xScale)
                      .project("y", "", yScale)
                      .project("fill", "", colorScale);
  
  var chart = new Plottable.Component.Table([
      [yAxis, plot],
      [null,  xAxis]
  ]);

  chart.renderTo("#my_chart");
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test</title>
    <link rel="stylesheet" href="https://rawgit.com/palantir/plottable/develop/plottable.css">
  </head>
  <body>
    <svg width="100%" height="600" id="my_chart"></svg>
    <script src="https://rawgit.com/mbostock/d3/master/d3.min.js"></script>
    <script src="https://rawgit.com/palantir/plottable/develop/plottable.min.js"></script>
  </body>
</html>

这是我刚整理的 couple examples。第一个是直接 d3 做你所要求的方式。第二个是被黑掉的plottable.js。对于 plottable.js,我找不到将轴定位在他们的 table 系统之外的方法,我不得不求助于手动移动它们。他们使用的 table 系统旨在减轻开发人员手动定位事物的负担。当然,这很好也很容易,除非您想控制放置东西的位置。

这是技巧,在您渲染情节后table:

  // move the axis...
  d3.select(".y-axis")
    .attr('transform',"translate(" + width / 2 + "," + 0 + ")");        
  d3.select(".x-axis")
    .attr("transform", "translate(" + 48 + "," + height / 2 + ")");

请注意,我没有删除 plottable 放入的左侧边距(上面的 48)。这也可能被黑客入侵,但在那一点上,什么是 plottable 无论如何为你提供...

需要注意的是,每个地块的不同外观完全是通过CSS来控制的。

完整的 d3 散点图:

// D3 EXAMPLE
var margin = {
  top: 20,
  right: 20,
  bottom: 20,
  left: 20
},
  width = 500 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom;

var x = d3.scale.linear()
  .range([0, width]);

var y = d3.scale.linear()
  .range([height, 0]);

var xAxis = d3.svg.axis()
  .scale(x)
  .orient("bottom");

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left");

var svg = d3.select("#d3").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

x.domain([-100, 100]);
y.domain([-100, 100]);

svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(" + 0 + "," + height / 2 + ")")
  .call(xAxis);

svg.append("g")
  .attr("class", "y axis")
  .attr("transform", "translate(" + width / 2 + "," + 0 + ")")
  .call(yAxis)
  .append("text");

svg.selectAll(".dot")
  .data(data)
  .enter().append("circle")
  .attr("class", "dot")
  .attr("r", function(d) {
    return d.r;
  })
  .attr("cx", function(d) {
    return x(d.x);
  })
  .attr("cy", function(d) {
    return y(d.y);
  })
  .style("fill", function(d) {
    return d.c;
  });

Plottable.js:

  // PLOTTABLE.JS
  var xScale = new Plottable.Scale.Linear();
  var yScale = new Plottable.Scale.Linear();

  var xAxis = new Plottable.Axis.Numeric(xScale, "bottom");
  var yAxis = new Plottable.Axis.Numeric(yScale, "left");

  var plot = new Plottable.Plot.Scatter(xScale, yScale);
  plot.addDataset(data);

  function getXDataValue(d) {
    return d.x;
  }
  plot.project("x", getXDataValue, xScale);
  function getYDataValue(d) {
    return d.y;
  }
  plot.project("y", getYDataValue, yScale);
  function getRDataValue(d){
    return d.r;
  }
  plot.project("r", getRDataValue);
  function getFillValue(d){
    return d.c;
  }
  plot.project("fill", getFillValue);
  var chart = new Plottable.Component.Table([
                    [yAxis, plot],
                    [null,  xAxis]
                  ]);
  chart.renderTo("#plottable");

  d3.select(".y-axis")
    .attr('transform',"translate(" + width / 2 + "," + 0 + ")");

  d3.select(".x-axis")
    .attr("transform", "translate(" + 48 + "," + height / 2 + ")");

Mark 的想法是正确的 - table 系统本身不支持这种布局,因此您需要对它们的布局方式进行一些手动控制。然而,使用 Plottable API 中有些晦涩的部分,有一种更清晰、更好支持的方式来布置你想要的图表,它不存在轴稍微偏移的问题.

第一个变化是我们将完全停止使用 table 布局引擎,因为它不能做我们想做的事情。相反,我们将把所有组件放在 Component.Group 中。组只是覆盖相同 space 中的组件,而根本不尝试定位它们。

var chart = new Plottable.Component.Group([yAxis, xAxis, plot]);

然后我们将使用在基本(抽象)组件 class 上定义的 alignment and offset methods。我们将 y 轴的 x 对齐方式设置为 "center",将 x 轴的 y 对齐方式设置为 "center" 这会将轴置于图表的中心。

var xAxis = new Plottable.Axis.Numeric(xScale, "bottom").yAlign("center"); var yAxis = new Plottable.Axis.Numeric(yScale, "left").xAlign("center");

我们在这一点上还没有完全完成,因为要真正使轴居中,我们需要将它们向后移动它们自身宽度的一半。宽度只在图表渲染时计算(严格来说是在computeLayout调用中,但那是内部细节),所以我们需要在图表渲染后设置一个偏移量:

chart.renderTo("#plottable"); xAxis.yOffset(xAxis.height()/2); yAxis.xOffset(-yAxis.width()/2);

大家可以看到最终结果here (it's a fork of Mark's plnkr)。请注意,现在轴在图表的中心对齐,因为中心点完全位于 0,0。