I think I have a solution for you, using .getClientBoundingRect()
of the svg elements and the <rect.selectionBox/>
to find out if your box is overlapping them etc.
Demo - https://codepen.io/Alexander9111/pen/XWJQoPP:

Code:
var svgDrawing = document.getElementById('drawing');
var pointerOrigin;
var point = svgDrawing.createSVGPoint();
var drawRectToSelect
var raster = 10;
$(document).ready(function () {
svgDrawing = document.getElementById('drawing');
svg_rect = svgDrawing.getBoundingClientRect();
console.log("svg_rect", svg_rect);
g = document.getElementById("437");
//svg_children = g.childNodes;
svg_children = g.querySelectorAll("*");
console.log(svg_children);
svgDrawing.addEventListener('pointerdown', e => mouseButtonPressed(e));
svgDrawing.addEventListener('pointerup', e => mouseButtonReleased(e));
svgDrawing.addEventListener('pointermove', e => mouseMove(e));
})
function mouseButtonPressed(evt) {
pointerOrigin = getPointFromEvent(evt);
if(evt.button === 0)
{
drawRectToSelect = d3.select('#drawing')
.append('rect')
.attr("id","temp_selection")
.classed('selectionBox', true)
.attr("x", Math.round(pointerOrigin.x / raster) * raster)
.attr("y", Math.round(pointerOrigin.y / raster) * raster)
.attr("height", raster)
.attr("width", raster);
}
}
function mouseMove(evt) {
if (!drawRectToSelect) { return; }
evt.preventDefault(); //Verschieben der gesamten Seite unterbinden
var pointerPosition = getPointFromEvent(evt);
if (drawRectToSelect) {
drawRectToSelect
.attr("width", Math.round((pointerPosition.x - pointerOrigin.x) / raster) * raster)
.attr("height", Math.round((pointerPosition.y - pointerOrigin.y) / raster) * raster);
}
}
function elementIsInside(el, box){
var result = false;
el_rect = el.getBoundingClientRect();
box_rect = box.getBoundingClientRect();
// console.log("rects_" + el.tagName, el_rect, box_rect)
// console.log("rects_" + el.tagName, el, box)
if (el_rect.right >= box_rect.left && el_rect.right <= box_rect.right
&& el_rect.bottom >= box_rect.top && el_rect.bottom <= box_rect.bottom){
result = true;
} else if (el_rect.left >= box_rect.left && el_rect.left <= box_rect.right
&& el_rect.bottom >= box_rect.top && el_rect.bottom <= box_rect.bottom){
result = true;
} else if (el_rect.right >= box_rect.left && el_rect.right <= box_rect.right
&& el_rect.top >= box_rect.top && el_rect.top <= box_rect.bottom){
result = true;
} else if (el_rect.left >= box_rect.left && el_rect.left <= box_rect.right
&& el_rect.top >= box_rect.top && el_rect.top <= box_rect.bottom){
result = true;
}
// console.log("result_" + el.tagName, result)
return result;
}
function mouseButtonReleased(evt) {
svgDrawing.style.cursor = null;
if (drawRectToSelect) {
const box = document.querySelector('#temp_selection');
for (i=0; i < svg_children.length; i++){
//svg_children[i].classList.add("selected");
console.log(svg_children[i].tagName)
console.log(svg_children[i].className.baseVal)
child_rect = svg_children[i].getBoundingClientRect();
console.log(child_rect);
//calculate elements inside rectangle
if (elementIsInside(svg_children[i], box )){
if (svg_children[i].className.baseVal.includes('selected')){
} else {
svg_children[i].className.baseVal += " selected";
svg_children[i].className.animVal += " selected";
}
} else {
if (svg_children[i].className.baseVal.includes('selected')){
console.log("true")
svg_children[i].className.baseVal = svg_children[i].className.baseVal.replace(" selected"," ");
svg_children[i].className.animVal = svg_children[i].className.animVal.replace(" selected"," ");
console.log(svg_children[i].className.baseVal);
} else {
console.log("false")
console.log(svg_children[i].className.baseVal);
}
}
}
//Delete selection-rectangle
drawRectToSelect.remove();
drawRectToSelect = null;
}
}
function getPointFromEvent(evt) {
if (evt.targetTouches) {
point.x = evt.targetTouches[0].clientX;
point.y = evt.targetTouches[0].clientY;
} else {
point.x = evt.clientX;
point.y = evt.clientY;
}
var invertedSVGMatrix = svgDrawing.getScreenCTM().inverse();
return point.matrixTransform(invertedSVGMatrix);
}
Firstly, you have to pass in the event argument to use it later:
$(document).ready(function () {
svgDrawing = document.getElementById('drawing');
svg_rect = svgDrawing.getBoundingClientRect();
console.log("svg_rect", svg_rect);
g = document.getElementById("437");
//svg_children = g.childNodes;
svg_children = g.querySelectorAll("*");
console.log(svg_children);
svgDrawing.addEventListener('pointerdown', e => mouseButtonPressed(e));
svgDrawing.addEventListener('pointerup', e => mouseButtonReleased(e));
svgDrawing.addEventListener('pointermove', e => mouseMove(e));
})
Then I created a function which tests if the box overlaps at least 1 corner of the element's bounding box:
function elementIsInside(el, box){
var result = false;
el_rect = el.getBoundingClientRect();
box_rect = box.getBoundingClientRect();
// console.log("rects_" + el.tagName, el_rect, box_rect)
// console.log("rects_" + el.tagName, el, box)
if (el_rect.right >= box_rect.left && el_rect.right <= box_rect.right
&& el_rect.bottom >= box_rect.top && el_rect.bottom <= box_rect.bottom){
result = true;
} else if (el_rect.left >= box_rect.left && el_rect.left <= box_rect.right
&& el_rect.bottom >= box_rect.top && el_rect.bottom <= box_rect.bottom){
result = true;
} else if (el_rect.right >= box_rect.left && el_rect.right <= box_rect.right
&& el_rect.top >= box_rect.top && el_rect.top <= box_rect.bottom){
result = true;
} else if (el_rect.left >= box_rect.left && el_rect.left <= box_rect.right
&& el_rect.top >= box_rect.top && el_rect.top <= box_rect.bottom){
result = true;
}
// console.log("result_" + el.tagName, result)
return result;
}
And this gets called from your function (and adds or removes the .selected class):
function mouseButtonReleased(evt) {
svgDrawing.style.cursor = null;
if (drawRectToSelect) {
const box = document.querySelector('#temp_selection');
for (i=0; i < svg_children.length; i++){
//svg_children[i].classList.add("selected");
console.log(svg_children[i].tagName)
console.log(svg_children[i].className.baseVal)
child_rect = svg_children[i].getBoundingClientRect();
console.log(child_rect);
//calculate elements inside rectangle
if (elementIsInside(svg_children[i], box )){
if (svg_children[i].className.baseVal.includes('selected')){
} else {
svg_children[i].className.baseVal += " selected";
svg_children[i].className.animVal += " selected";
}
} else {
if (svg_children[i].className.baseVal.includes('selected')){
console.log("true")
svg_children[i].className.baseVal = svg_children[i].className.baseVal.replace(" selected"," ");
svg_children[i].className.animVal = svg_children[i].className.animVal.replace(" selected"," ");
console.log(svg_children[i].className.baseVal);
} else {
console.log("false")
console.log(svg_children[i].className.baseVal);
}
}
}
//Delete selection-rectangle
drawRectToSelect.remove();
drawRectToSelect = null;
}
}