D3js V4 - Как увеличить матрицу диаграммы рассеяния - PullRequest
0 голосов
/ 29 сентября 2018

Я новичок, использующий js и d3.Как я могу увеличить матрицу диаграммы рассеяния?

Что я сделал,

  • Я использовал svg, чтобы показать матрицу диаграммы рассеяния, следуя примеру https://bl.ocks.org/Fil/6d9de24b31cb870fed2e6178a120b17d
  • Поскольку производительность была слишком плохой, когда записи превышали 10 тысяч, а размер матрицы составлял 10 * 10, я изменил рисование точек с помощью canvas
  • Оси используют svg, а точки рисуют с помощью canvas
  • Даже если на рисование диаграммы холстом уходит некоторое время, страница не будет зависать при отображении матрицы 10 * 10 на 10 тысячах записей

Я не уверен, что это формальный способсделать это.С другой стороны, я хочу увеличить эту диаграмму, но я понятия не имею, как я могу это сделать.

Насколько я понимаю,

  • Оси разбиваются на несколько частей в соответствии сномер матрицы, например 10, включая ось x и ось y
  • Если я хочу изменить масштаб каждой ячейки матрицы, например ячейку в строке 0 и столбце 0, , как я могу это сделать? Я просто устал с d3.event.transform.rescaleX/rescaleY, чтобы перемасштабировать оси, это похоже на работу, но как я могу сделать на холсте, , как я могу перерисовать действительные точки?
  • С другой стороны, если я хочу увеличить только всю диаграмму, а не одну ячейку (это означает, что если я нажму на ячейку (0,0), эта ячейка будет увеличиваться до тех пор, пока не заполнит всю диаграмму, и другие ячейки не будутвидно), как я могу это сделать? Я использовал модал, чтобы показать масштабированный большой SVG на viewBox="0 0 ' + width * scalar + ' ' + height, Есть ли другой способ показать изображение в большом формате?

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>

Спасибо за помощь

...