HTML Тепловая карта перекрытия холста - PullRequest
1 голос
/ 27 апреля 2020

У меня есть несколько сотен полигональных слоев, и мне нужно было знать, какие из них перекрываются, и затенять перекрывающуюся область темнее / ярче, как на тепловой карте. Я пробовал свойство: "_ctx.globalCompositeOperation = 'multiply" ", но это не совсем работает, так как он применяется к каждому слою, а не только к перекрывающимся.

Я не уверен, где Начните с того, какие формулы использовать для исследования чего-то подобного. Я обнаружил, что некоторые библиотеки обрабатывают это как: http://fabricjs.com/intersection, он встроен.

У меня также есть скрипка: https://jsfiddle.net/v6swarb7/2/

       const _canvas = document.getElementById('canvas');
    const _ctx = canvas.getContext("2d");
    const poly1 = [[172.87066184227245, 40.37854538483082], [172.87066184227245, 66.87696924040097], [13.880126229942462, 66.87696924040097], [13.880126229942462, 106.62460502375617], [119.87381413113218, 106.62460502375617], [119.87381413113218, 80.12618116818604], [146.37223798670232, 80.12618116818604], [146.37223798670232, 133.12302699905362], [186.11987377005755, 133.12302699905362], [186.11987377005755, 40.37854538483082], [172.87066184227245, 40.37854538483082]];
    const poly2 = [[13.880126229942462, 66.87696924040097], [13.880126229942462, 106.62460502375617], [119.87381413113218, 106.62460502375617], [119.87381413113218, 66.87696924040097], [13.880126229942462, 66.87696924040097]];
    _ctx.beginPath();
    /* _ctx.globalCompositeOperation = 'multiply'; */
    poly1.map((val, i) => {
        _ctx.lineTo(
            val[0], val[1]
        )
        _ctx.stroke();
    });
    _ctx.closePath();

    _ctx.beginPath();
    poly2.map(val => {
        // this fill would be dynamic, and get gradually darker the more that overlap.
        _ctx.fillStyle = 'red';
        _ctx.lineTo(
            val[0], val[1]
        )
        _ctx.fill();
        _ctx.stroke();
    });
    _ctx.closePath();

1 Ответ

1 голос
/ 27 апреля 2020

Я начал использовать globalAlpha, чтобы посмотреть, что перекрывается, но после обратной связи нам действительно нужно обнаружить пиксели, которые перекрывают многоугольники, для этого мы getImageData и проанализировать все пиксели, чтобы увидеть, которые находятся внутри многоугольников, я просто сделайте их черными в этом случае, но я думаю, вы можете использовать другие логи c, чтобы покрасить их, как вам нравится

const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext("2d");
  ctx.globalAlpha = 0.6

  const poligons = [
    [[89, 9], [13, 9], [13, 76], [98, 36], [89, 9]],
    [[5, 50], [5, 90], [99, 90], [99, 50], [5, 50]]
  ]

  function draw(poly, color) {
    ctx.beginPath();
    poly.map(val => ctx.lineTo(val[0], val[1]));
    ctx.fillStyle = color;
    ctx.fill();
    ctx.stroke();
  }

  function inside(p, vs) {
    var inside = false;
    for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
      var xi = vs[i][0], yi = vs[i][1];
      var xj = vs[j][0], yj = vs[j][1];
      var intersect = ((yi > p[1]) != (yj > p[1])) && (p[0] < (xj - xi) * (p[1] - yi) / (yj - yi) + xi);
      if (intersect) inside = !inside;
    }
    return inside;
  };

  function check_overlap(p) {
    for (x = 0; x < p.width; x++) {
      for (y = 0; y < p.height; y++) {
        let overlap = 0
        for (pol = 0; pol < poligons.length; pol++) {
          if (inside([x, y], poligons[pol]))
            overlap++
        }
        if (overlap >= 2) {
          offset = (p.width * y + x) * 4;
          p.data[offset] = 0;
          p.data[offset + 1] = 0;
          p.data[offset + 2] = 0;

        }
      }
    }
    return p
  }

  draw(poligons[0], 'blue')
  draw(poligons[1], 'red')

  data = ctx.getImageData(0, 0, canvas.width, canvas.height);
  data = check_overlap(data);
  ctx.putImageData(data, 0, 0);
<canvas id="canvas"></canvas>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...