D3js V4-如何缩放散点图矩阵图

时间:2018-09-29 02:44:31

标签: javascript d3.js canvas scatter-plot

我是使用js和d3的新生。如何缩放散点图矩阵图?

我做了什么

  • 按照示例https://bl.ocks.org/Fil/6d9de24b31cb870fed2e6178a120b17d
  • ,我使用svg显示了散点图矩阵
  • 由于当记录超过1万条且矩阵大小为10 * 10时性能太差,所以我用画布更改了点绘制
  • 轴正在使用svg,而点是由画布绘制的
  • 即使花一些时间用画布绘制图表,当运行10 * 10矩阵超过1万条记录时,页面也不会挂起或缩放

我不确定这是否是正式的方式。 另一方面,我想放大此图表,但我不知道该怎么做。

据我了解

  • 根据矩阵的数量,轴分为几部分,例如10,包括x轴和y轴
  • 如果我想重新缩放每个矩阵单元格(例如第0行和第0列的单元格),我该怎么做?我只是厌倦了d3.event.transform.rescaleX/rescaleY来重新缩放轴,这似乎可行,但是我该如何在画布上进行操作,如何获取有效点以重绘?
  • 另一方面,如果我只想缩放整个图表而不是单个单元格(也就是说,如果我单击单元格(0,0),则此单元格将一直缩放直到填满整个图表,其他单元格将看不见),我该怎么做??我使用模式显示viewBox="0 0 ' + width * scalar + ' ' + height缩放后的大型svg,还有其他方法可以显示大尺寸的图像吗?< / strong>

draw_spm = function(data) {
  var width = 700, traits = d3.keys(data[0]),
      domain = {}, n = traits.length,
      pointRadius = 1;

  var size = width / n,
      padding = size / 10;

  var x = d3.scaleLinear().range([padding / 2, size - padding / 2]),
      y = d3.scaleLinear().range([size - padding / 2, padding / 2]);

  var x_axis = d3.axisBottom().scale(x).ticks(6),
      y_axis = d3.axisLeft().scale(y).ticks(6);

  traits.forEach(function(t) {
    domain[t] = d3.extent(data, function(d) { return d[t]; });
  });

  x_axis.tickSize(size * n);
  y_axis.tickSize(-size * n);

  var zoom = d3.zoom()
      .on('zoom', zoomed);

  var svg = d3.select('#spm-svg')
      .attr('class', 'plot svg-scatterplot')
      .attr('width', size * n + 4*padding)
      .attr('height', size * n + 4*padding)
    .append('g')
      .attr('transform', 'translate('+4*padding+','+padding/2+')');

  var x_axis_svg = svg.selectAll('.x.axis')
      .data(traits)
    .enter().append('g')
      .attr('class', 'x axis')
      .attr('transform', function(d, i) { return 'translate('+size*i+',0)'; })
      .each(function(d) { x.domain(domain[d]); d3.select(this).call(x_axis); });

  var y_axis_svg = svg.selectAll('.y.axis')
      .data(traits)
    .enter().append('g')
      .attr('class', 'y axis')
      .attr('transform', function(d, i) { return 'translate(0,'+size*i+')'; })
      .each(function(d) { y.domain(domain[d]); d3.select(this).call(y_axis); });

  var canvas = d3.select('#spm-canvas')
      .attr('width', size*n+4*padding)
      .attr('height', size*n+4*padding)
      .style('transform', 'translate('+4*padding+','+padding/2+')');

  var ctx = canvas.node().getContext('2d');
  ctx.fillStyle = 'steelblue';

  var cell = svg.selectAll('.cell')
      .data(cross(traits, traits))
    .enter().append('g')
      .attr('class', 'cell')
      .attr('transform', function(d) {
        return 'translate(' + d.i*size + ',' + d.j*size + ')';
      })
      .each(draw);

  canvas.call(zoom).on('dblclick.zoom', null);

  function draw(p) {
    var cell = d3.select(this);

    ctx.resetTransform();
    ctx.transform(1, 0, 0, 1, p.i*size+4*padding, p.j*size+padding/2);
    x.domain(domain[p.x]);
    y.domain(domain[p.y]);

    function draw_point(d) {
      ctx.beginPath();
      ctx.arc(x(d[p.x]), y(d[p.y]), pointRadius, 0, 2*Math.PI);
      ctx.closePath();
      ctx.fill();
      ctx.stroke();
    }

    cell.append('rect')
       .attr('class', 'frame')
       .attr('x', padding / 2)
       .attr('y', padding / 2)
       .attr('width', size - padding)
       .attr('height', size - padding);

    data.forEach(function(d) {
      draw_point(d);
    });
  }

  function zoomed() {
    // how to do this?
  };
  
  function cross(a, b) {
    var c = [], n = a.length, m = b.length, i, j;
    for (i = -1; ++i < n;)
      for (j = -1; ++j < m;)
        c.push({x: a[i], i: i, y: b[j], j: j});
    return c;
  }
};

cols = ['x0','x1','x2','x3','x4'];

function _data() {
  var d = {};
  for (var i = 0; i < cols.length; i++) {
    d[cols[i]] = Math.floor(Math.random() * 10000);
  }
  return d;
}

var data = [];
for (var i = 0; i < 1000; i++) {
  data[i] = _data();
}

draw_spm(data);
.svg-scatterplot .axis,.frame {shape-rendering:crispEdges;}
.svg-scatterplot .axis line {stroke:#ddd;}
.svg-scatterplot .axis path {display:none;}
.svg-scatterplot .cell text {font-weight:bold;text-transform: capitalize;fill: black;}
.svg-scatterplot .frame {fill:none;stroke:#aaa;}
.svg-scatterplot circle {fill-opacity:.7;}
.svg-scatterplot circle.hidden {fill:#ccc !important;}
.svg-scatterplot .extent {fill:#000;fill-opacity:.125;stroke:#fff;}

.plot {position: absolute;}
#spm-canvas {z-index: 2;}
#spm-svg {z-index: 1;}
<script src="https://d3js.org/d3.v4.min.js"></script>

<svg id="spm-svg" class="plot"></svg>
<canvas id="spm-canvas" class="plot"></canvas>

感谢您的帮助

0 个答案:

没有答案