Гость
Различайте регионы, нажимая на границы ячеек
Сообщение
Гость » 11 мар 2024, 19:21
В приведенном ниже коде есть проблема с идентификацией областей, заключенных в рамку.
Если я окружу все ячейки «A» периметром, она будет идентифицирована как отдельная область; но если я сначала заключу регион «B», он не будет идентифицирован как отдельный регион.
Код: Выделить всё
const COLOR_PALETTE = ['#FDD', '#DFD', '#DDF', '#FFD', '#DBF', '#BFD', '#FDB', '#BDF'];
const CLICK_DISTANCE_THRESHOLD = 5;
const DATA = [
['A', 'A', 'A', 'B'],
['C', 'C', 'A', 'B'],
['C', 'D', 'B', 'B'],
['C', 'D', 'D', 'D']
];
const $grid = $('#grid');
$grid.append($('')
.append(DATA.map((row, rowIndex) => $('')
.append(row.map((val, colIndex) => $('')
.text(val).data('coords', [rowIndex, colIndex]))))));
$grid.on('click', 'td', onBorderClick);
function onBorderClick(event) {
const $target = $(this);
const rect = this.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
// Determine the closest border and toggle it
if (x < CLICK_DISTANCE_THRESHOLD) {
$target.toggleClass('selected-left');
$target.prev().toggleClass('selected-right');
} else if (x > rect.width - CLICK_DISTANCE_THRESHOLD) {
$target.toggleClass('selected-right');
$target.next().toggleClass('selected-left');
} else if (y < CLICK_DISTANCE_THRESHOLD) {
$target.toggleClass('selected-top');
$target.parent().prev().children().eq($target.index()).toggleClass('selected-bottom');
} else if (y > rect.height - CLICK_DISTANCE_THRESHOLD) {
$target.toggleClass('selected-bottom');
$target.parent().next().children().eq($target.index()).toggleClass('selected-top');
}
distinguishRegions();
}
function distinguishRegions() {
// Clear previous regions
$grid.find('td').css('background-color', '').removeData('region').removeAttr('data-region');
let regionId = 0;
$grid.find('td').each(function() {
const $cell = $(this);
if (!$cell.data('region')) {
regionId++;
floodFill($cell, regionId);
}
});
}
function floodFill($cell, regionId) {
const queue = [$cell];
while (queue.length > 0) {
const $current = queue.shift();
if ($current.length === 0 || $current.data('region')) continue;
$current.data('region', regionId)
.attr('data-region', regionId)
.css('background-color', getRandomColor(regionId));
const [r, c] = $current.data('coords');
const neighbors = [
!$current.hasClass('selected-top') && getCell(r - 1, c),
!$current.hasClass('selected-bottom') && getCell(r + 1, c),
!$current.hasClass('selected-left') && getCell(r, c - 1),
!$current.hasClass('selected-right') && getCell(r, c + 1),
];
queue.push(...neighbors.filter($n => $n && !$n.data('region')));
}
}
function getCell(rowIndex, colIndex) {
return $grid.find(`tr:eq(${rowIndex})`).find(`td:eq(${colIndex})`);
}
function getRandomColor(index) {
return COLOR_PALETTE[index % COLOR_PALETTE.length];
}
Код: Выделить всё
table {
border: 2px solid grey;
border-collapse: collapse;
cursor: pointer;
}
td {
width: 2rem;
height: 2rem;
border: 2px dotted grey;
text-align: center;
}
.selected-left { border-left: 2px solid red; }
.selected-right { border-right: 2px solid red; }
.selected-top { border-top: 2px solid red; }
.selected-bottom { border-bottom: 2px solid red; }
Источник:
https://stackoverflow.com/questions/781 ... ll-borders
1710174079
Гость
В приведенном ниже коде есть проблема с идентификацией областей, заключенных в рамку. Если я окружу все ячейки «A» периметром, она будет идентифицирована как отдельная область; но если я сначала заключу регион «B», он не будет идентифицирован как отдельный регион. [code]const COLOR_PALETTE = ['#FDD', '#DFD', '#DDF', '#FFD', '#DBF', '#BFD', '#FDB', '#BDF']; const CLICK_DISTANCE_THRESHOLD = 5; const DATA = [ ['A', 'A', 'A', 'B'], ['C', 'C', 'A', 'B'], ['C', 'D', 'B', 'B'], ['C', 'D', 'D', 'D'] ]; const $grid = $('#grid'); $grid.append($('') .append(DATA.map((row, rowIndex) => $('') .append(row.map((val, colIndex) => $('') .text(val).data('coords', [rowIndex, colIndex])))))); $grid.on('click', 'td', onBorderClick); function onBorderClick(event) { const $target = $(this); const rect = this.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; // Determine the closest border and toggle it if (x < CLICK_DISTANCE_THRESHOLD) { $target.toggleClass('selected-left'); $target.prev().toggleClass('selected-right'); } else if (x > rect.width - CLICK_DISTANCE_THRESHOLD) { $target.toggleClass('selected-right'); $target.next().toggleClass('selected-left'); } else if (y < CLICK_DISTANCE_THRESHOLD) { $target.toggleClass('selected-top'); $target.parent().prev().children().eq($target.index()).toggleClass('selected-bottom'); } else if (y > rect.height - CLICK_DISTANCE_THRESHOLD) { $target.toggleClass('selected-bottom'); $target.parent().next().children().eq($target.index()).toggleClass('selected-top'); } distinguishRegions(); } function distinguishRegions() { // Clear previous regions $grid.find('td').css('background-color', '').removeData('region').removeAttr('data-region'); let regionId = 0; $grid.find('td').each(function() { const $cell = $(this); if (!$cell.data('region')) { regionId++; floodFill($cell, regionId); } }); } function floodFill($cell, regionId) { const queue = [$cell]; while (queue.length > 0) { const $current = queue.shift(); if ($current.length === 0 || $current.data('region')) continue; $current.data('region', regionId) .attr('data-region', regionId) .css('background-color', getRandomColor(regionId)); const [r, c] = $current.data('coords'); const neighbors = [ !$current.hasClass('selected-top') && getCell(r - 1, c), !$current.hasClass('selected-bottom') && getCell(r + 1, c), !$current.hasClass('selected-left') && getCell(r, c - 1), !$current.hasClass('selected-right') && getCell(r, c + 1), ]; queue.push(...neighbors.filter($n => $n && !$n.data('region'))); } } function getCell(rowIndex, colIndex) { return $grid.find(`tr:eq(${rowIndex})`).find(`td:eq(${colIndex})`); } function getRandomColor(index) { return COLOR_PALETTE[index % COLOR_PALETTE.length]; }[/code] [code]table { border: 2px solid grey; border-collapse: collapse; cursor: pointer; } td { width: 2rem; height: 2rem; border: 2px dotted grey; text-align: center; } .selected-left { border-left: 2px solid red; } .selected-right { border-right: 2px solid red; } .selected-top { border-top: 2px solid red; } .selected-bottom { border-bottom: 2px solid red; }[/code] [code] [/code] Источник: [url]https://stackoverflow.com/questions/78141597/distinguish-regions-by-clicking-on-cell-borders[/url]