So as the title sugests, I am trying to move parts of the SVG to the center of the screen when they are clicked without success.
I don’t have any idea on why this happens as I tried it on a different SVG and it works perfectly.
const svg = document.querySelector("svg");
const paths = document.querySelectorAll("svg path");
const popUp = document.querySelector(".pop");
let selectedPath = null;
function calcCenterMove(element){
/*
X and Y are the current position of the element to be moved (top left corner).
Width and Height are the width and height of the element to be moved.
CX and CY are the X and Y coordinates of the centre of the screen.
*/
var x = element.getBoundingClientRect().x * 2;
var y = element.getBoundingClientRect().y * 2;
var width = element.getBoundingClientRect().width * 2;
var height = element.getBoundingClientRect().height * 2;
var cx = window.innerWidth / 2;
var cy = window.innerHeight / 2;
var xVector = cx-(width/2)-x;
var yVector = cy-(height/2)-y;
return [xVector, yVector];
}
for (const path of paths) {
path.addEventListener("click", (event) => {
if (selectedPath === path) return; // Don't change if clicking the same path again
selectedPath = path;
paths.forEach(otherPath => {
if (otherPath !== selectedPath) {
otherPath.style.opacity = "0.4"
otherPath.style.fill = "lightgray"; // Reduce opacity for unselected paths
otherPath.style.pointerEvents = "none";
}
});
var xAxisMove = calcCenterMove(svg)[0];
var yAxisMove = calcCenterMove(svg)[1];
path.style = "transform: translate("+xAxisMove+"px,"+yAxisMove+"px);";
path.classList.add("selected");
path.style.pointerEvents = "auto";
if (selectedPath != null) {
document.documentElement.addEventListener("click", captureClick, true);
}
});
function captureClick(event) {
if (!event.target.classList.contains("selected")) {
var xAxisMove = calcCenterMove(svg)[0];
var yAxisMove = calcCenterMove(svg)[1];
selectedPath.style = "transform: translate("+-xAxisMove+"px,"+-yAxisMove+"px);";
for (const path of paths) {
path.classList.remove("selected");
path.style.opacity = 1;
path.style.pointerEvents = "auto";
path.style.fill = "gray";
}
selectedPath = null;
document.documentElement.removeEventListener("click", captureClick, true);
}
}
path.addEventListener("mouseenter", (event) => {
const pathId = event.target.id;
popUp.querySelector("p").textContent = `Content for path: ${pathId}`;
const pathRect = event.target.getBoundingClientRect();
popUp.style.top = `${pathRect.top + pathRect.height / 2}px`;
popUp.style.left = `${pathRect.left + pathRect.width / 2}px`;
popUp.style.opacity = 0.8;
});
path.addEventListener("mouseenter", (event) => {
const districtName = event.target.id;
event.target.style.fill = "red";
});
path.addEventListener("mouseleave", () => {
event.target.style.fill = "";
popUp.style.opacity = 0;
});
}
.hoverme {
display: none;
}
body{
background: white;
font-family: 'Open Sans Hebrew', Arial, sans-serif;
text-align: center;
}
.div-svg{
float: right;
}
svg{
position: relative;
height: auto;
}
svg path {
fill: gray;
cursor: pointer;
transition: all 0.3s ease;
}
svg path.selected {
fill: #007bff;
transition: all 0.3s ease;
transform: scale(2);
}
svg path:hover {
fill: rgba(black, 0.3);
.pop {
opacity: 1;
width: 200px;
height: 200px;
}
}
.pop {
pointer-events: none;
position: absolute;
transition: all 0.3s ease;
background-color: lightblue;
}
<div class="div-svg">
<svg width="700" height="700" viewBox="0 0 12969 26674">
<path id="Braga" data-z="32" class="Braga" d="M5329 1730c-66-17-64 0-92 15l-110 113c-121 4-292 156-324 162-42-3-181 2-190-1l-63-42-153 42c-101 28-190 153-246 162-51-1-120-63-171 40-4 70-22 172-11 235-20 5-54 13-72 31l-21 36c-2 67 22 43 26 107l-40 111-33 28-36-11-62-98c-65-6-65 3-114 40-67-40-52-40-108-46l-17-34-39 18 1 73c-47-2-31 4-66-28-40 2-230 40-268 53l-15 35c-82 42-170 47-257 69l65 294v261l66 131v131c58-22 39-9 81-55l27 42c109 12 53-8 132 66l116-33 37 19c30 44 51 107 91 124 77 31 65 60 140 30 45 26 29 11 64 87l-136 68 54 184c22 1 354-18 355-19 43-53 52-56 91-127l199-29 49 55c169 16 391-82 456-69-5 45-7 28 10 72 85-32 174-64 260-95 18-12 31-70 32-70 71-42 91-27 138-55l9-72c200 51 198-5 310 190-62 100 186 171 254 209 28-43 13-30 58-54 34 44 76 73 118 125 13-1 198-149 211-169l33-101c7-14 156-340 157-344 9-53-16-96 14-224l57-58c77 5 27 32 103-17 20-33-6-61 15-92l68 6c18-31 175-267 176-267 47-34 93-52 67-124l-67-130-77-25c-39 47-31 42-60 106-28 5-189 31-190 31-53-16-324-80-356-101-10-157 16-226 65-356-19-23-196-122-214-117-103 32-202 79-336 73 47-93 81-60 123-143 21-42 16-47 19-78 7-67 32-123 89-158-19-156 4-155 96-264l-98-33-163 131-327-66z"/>
<path id= "Porto" cx="50" cy="50" r="40" data-z="33" class="Porto" d="M2979 3657c58-22 39-9 81-55l27 42c109 12 53-8 132 66l116-33 37 19c30 44 51 107 91 124 77 31 65 60 140 30 45 26 29 11 64 87l-136 68 54 184c22 1 354-18 355-19 43-53 52-56 91-127l199-29 49 55c169 16 391-82 456-69-5 45-7 28 10 72 85-32 174-64 260-95 18-12 31-70 32-70 71-42 91-27 138-55l9-72c200 51 198-5 310 190-62 100 186 171 254 209 28-43 13-30 58-54 34 44 76 73 118 125 13-1 198-149 211-169l33-101c16 22 26 37 54 52 45 24 25-8 53 50l-63 72 17 36c22 24 296 61 184 170 8 70 98 202 161 240l-67 180c60 164-59 157-5 260-80 148-101 93-78 206-81-1-47 33-132-15l-63 52c-4 1-330 118-382 134-200 36 0-77-312 49-60 24-159-10-215-29-99-33-95 35-136 75-61-6-43-9-81 9l-80 56c-66-44-124-64-152-46-34 46-183 240-248 197-88-57-84-35-184-62 29 91-23 107 68 163-6 89 13 55-17 111-120-48-33-85-155-107l19-71c-109-48-10-16-110-91-61 62-65 8-143 50 110 52 39 12 47 139-49 42-41 32-112 63l-90-133-33-19c-73 42-75 33-102 107l-76 28c-96-16-95-48-202-36l-32-26-33-130-32-98v-196l-66-196-153-308c-15-180-51-371-108-541v-131l-32-98-66-98-65-195 33-196z"/>
</svg>
</div>
<div class="pop"> <p>This is the pop-up content.</p>
</div>
I followed some of the instructions here text, I managed to make it move A LITTLE to the center but not all the way.
Thank you for your help.
2
Answers
I’m not very sure what you want to achieve. Please try the following:
Put the shape in a symbol with a tight viewBox. In this case:
<symbol id="braga_porto" viewBox="2848 1665 3985 4275">
Use the symbol so that it falls in the original position:
<use href="#braga_porto" x="2848" y="1665" width="3985" height="4275"...
Please compare the values of the x, y width and height attributes with the viewBox of the symbol.
<use>
to 0,0 (the upper left corner of the svg canvas). The use will take the whole width (i.e. 12969). You will need to calculate the height so that it respects the aspect ratio (i.e. 4275 * 12969 / 3985).Please compare the new width of the use with the value of the viewBox of the svg element.
In order to get the values for the tight viewBox of the symbolI’ve used the getBBox() method.
The problem is that each of your shapes starts off with a very large M (move) – which makes the bounding rect very large because the starting point of the draw is about half a screen away from the filled path – you have to compensate for this in your bounding rect calculation (and don’t forget to do the calcs using the viewBox to Width/Height ratio.)