HTML画布重叠多边形热图



我有几百个多边形层,我需要知道哪些层重叠,并将重叠区域着色得更暗/更亮,类似于热图。我尝试过属性:"_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();

我开始使用globalAlpha来查看哪些重叠,但在反馈之后,我们确实需要检测与多边形重叠的像素,为此,我们getImageData并分析所有像素以查看多边形内部的像素,在这种情况下,我只是将它们变黑,但我想你可以根据自己的喜好使用其他逻辑来给它们上色。

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>

最新更新