Modify the SVG height using JavaScript and CSS

In my SVG file, I have paths for all the countries in the world. Each country is represented by its own individual path like this:

<path
      inkscape:connector-curvature="0"
      id="PH"
      data-name="Philippines"
      data-id="PH"
      d="m 1684.6,518.6 -0.6,-2.3 -0.8,-3.2 -4.8,-3 0.8,4.9 -3.9,0.2 -0.7,2.8 -4.2,1.7 -2.2,-2.8 -2.8,2.4 -3.4,1.7 -1.9,5.4 1.1,1.9 3.9,-3.6 2.7,0.3 1.5,-2.7 3.8,3 -1.5,3.1 1.9,4.6 6.8,3.7 1.4,-3 -2.1,-4.7 2.4,-3.2 2.5,6.4 1.5,-5.8 -0.6,-3.5 -0.8,-4.3 z m -14.5,-11.8 0,-6.1 -3.6,6.1 0.5,-4.2 -3,0.3 -0.3,4 -1.2,1.8 -1,1.7 3.8,4.4 1.6,-1.9 1.4,-4 1.8,-2.1 z m -30.1,6.1 2.6,-4.4 3.4,-3.5 -1.5,-5.2 -2.4,6.3 -2.9,4.4 -3.8,4 -2.4,4.4 7,-6 z m 17.4,-16...

<path
      inkscape:connector-curvature="0"
      id="PL"
      data-name="Poland"
      data-id="PL"
      d="m 1069.4,228.3 -4.6,-0.1 -0.5,-1.4 -4.8,-1.1 -5.7,2.1 -7.1,2.8 -3.1,1.7 1.4,3.1 -1.2,1.6 2,2.2 1.4,3.3 -0.1,2.1 2.3,3.9 2.4,1.9 3.7,0.6 -0.1,1.7 2.7,1.2 0.6,-1.5 3.4,0.6 0.7,2 3.6,0.3 2.6,3.1 0.3,0.4 1.9,-0.9 2.7,2.2 2.8,-1.3 2.4,0.6 3.4,-0.8 4.9,2.3 1.1,0.4 -1.6,-2.8 3.8,-5.1 2.3,-0.7 0.3,-1.8 -3.1,-5.3 -0.5,-2.7 -1.9,-2.9 2.7,-1.2 -0.3,-2.4 -1.7,-2.3 -0.6,-2.7 -1.4,-1.9 -2.5,-0.6 -8.7,0.1 -5.9,-0.7 z"
      style="fill:#f2f2f2;fill-rule:evenodd" />

To interact with each country using JavaScript, I added an anchor tag before each country:

<a href="#" onclick="SelectCountry('ph');" id='country_ph'> 
   <path
      inkscape:connector-curvature="0"
      id="PH"
      data-name="Philippines"
      data-id="PH"
      d="m 1684.6,518.6 -0.6,-2.3 -0.8,-3.2 -4.8,-3 0.8,4.9 -3.9,0.2 -0.7,2.8 -4.2,1.7 -2.2,-2.8 -2.8,2.4 -3.4,1.7 -1.9,5.4 1.1,1.9 3.9,-3.6 2.7,0.3 1.5,-2.7 3.8,3 -1.5,3.1 1.9,4.6 6.8,3.7 1.4,-3 -2.1,-4.7 2.4,-3.2 2.5,6.4 1.5,-5.8 -0.6,-3.5 -0.8,-4.3 z m -14.5,-11.8 0,-6.1 -3.6,6.1 0.5,-4.2 -3,0.3 -0.3,4 -1.2,1.8 -1,1.7 3.8,4.4 1.6,-1.9 1.4,-4 1.8,-2.1 z m -30.1,6.1 2.6,-4.4 3.4,-3.5 -1.5,-...

   </a>

Then, to handle the click event on a country:

var phCountry = document.getElementById("PH");

function SelectCountry(country)
{
    alert(country);
}

However, I tried to scale the clicked country by adding these lines:

phCountry.setAttribute("height", "100px");

phCountry.style.height = "100px";

I'm new to working with SVG and JavaScript, so I might be approaching this incorrectly. Can anyone help me figure out how to properly implement this? Thank you!

Answer №1

<path> elements do not have a width or height attribute that can be changed directly. Instead, you need to apply a transform to scale the country paths when they are clicked on.

Adding <a> tags to your SVG is unnecessary. Simply attach a click handler to each path element.

Check out the example below for a better understanding:

// Find all <path> elements in the SVG and add a click event listener to each one
document.querySelectorAll("svg path").forEach(function(item) {
  item.addEventListener("click", countryClick);
});

function countryClick(e) {
  // e.target refers to the path that was clicked
  // The classList.toggle("enlarge") will toggle the "enlarge" class on and off with each click
  e.target.classList.toggle("enlarge");
}
.enlarge {
  /* Use the bounds of the path to calculate the transform origin */
  transform-box: fill-box;
  /* Set the origin for scaling at the center of the path bounds */
  transform-origin: 50% 50%;
  /* Scale up by a factor of 2 in both x and y directions */
  transform: scale(2, 2);
}
<svg viewBox="1000 200 800 400">
  <path inkscape:connector-curvature="0"
        id="PH"
        data-name="Philippines"
        data-id="PH"
        d="m 1684.6,518.6 -0.6,-2.3 -0.8,-3.2 -4.8,-3 0.8,4.9 -3.9,0.2 -0.7,2.8 -4.2,1.7 -2.2,-2.8 -2.8,2.4 -3.4,1.7 -1.9,5.4 ... />
  <path inkscape:connector-curvature="0"
        id="PL"
        data-name="Poland"
        data-id="PL"
        d="m 1069.4,228.3 -4.6,-0.1 -0.5,-1.4 -4.8,-1.1 ... />
</svg>

However, there is an additional step that needs to be considered. When you enlarge a country, it might get hidden behind another un-enlarged country due to the draw order of elements in an SVG. To address this, you should also reorder the enlarged country to the front by moving it to the end of the SVG.

In the next example, I've included the necessary code snippet:

// Look for all <path> elements in the SVG and add a click handler to each one
document.querySelectorAll("svg path").forEach(function(item) {
  item.addEventListener("click", countryClick);
});

function countryClick(e) {
  // e.target is the path we clicked on.
  // classList.toggle("enlarge") will cause the "enlarge" class to be added then removed on alternate clicks
  e.target.classList.toggle("enlarge");

  // If we are enlarging, move the path to the end of the SVG
  if (e.target.classList.contains("enlarge")) {
    var svg = e.target.ownerSVGElement;
    svg.appendChild(e.target); // Moves the path to the end of the SVG
  }
}
.enlarge {
  /* Use the bounds of the path to calculate the transform origin */
  transform-box: fill-box;
  /* Set the origin for scaling at the center of the path bounds */
  transform-origin: 50% 50%;
  /* Scale up by a factor of 2 in both x and y directions */
  transform: scale(2, 2);
}
<svg viewBox="1000 200 800 400">
  <path inkscape:connector-curvature="0"
        id="PH"
        data-name="Philippines"
        data-id="PH"
        d="m 1684.6,518.6 -0.6,-2.3 -0.8,-3.2 -4.8,-3 0.8,4.9 -3.9,0.2 -0.7,2.8 -4.2,1.7 -2.2,-2.8 -2.8,2.4 -3.4,1.7 -1.9,5.4 ... />
  <path inkscape:connector-curvature="0"
        id="PL"
        data-name="Poland"
        data-id="PL"
        d="m 1069.4,228.3 -4.6,-0.1 -0.5,-1.4 -4.8,-1.1 ... />
  <path d="M 1100,228 h 30 v 30 h -30 z" fill="#ccaa88"/>
</svg>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Complete Navigation Bar Expands Alongside Drop-down Menu

For my navbar, I am attempting to set a custom breakpoint at 1080px where it switches to a hamburger menu. However, when I click on a dropdown option, the entire navbar expands instead of just the dropdown area. @media (min-width: 1080px){ .navbar-expand- ...

Adjusting image size as you scroll

Hello everyone, I am currently working on coding a website logo that decreases in size as the user scrolls down, similar to the effect seen on this website: . I am relatively new to HTML and was wondering if there are any specific commands or techniques th ...

What's the reason for the align-self: flex-end CSS property not working as expected on a flex div element?

I am trying to align the "Click me" button to the left of the div that contains it. Here is my code: render = () => { return ( <Wrapper> <Body> <span>Title</span> <Desc ...

Refresh the DOM window to load the updated PHP element

I have a dilemma with two separate playlists in a PHP file, each corresponding to a button labeled playlist1 and playlist2. <div class="player"> <?php include ('playlist1.php');?> <?php include ('playlist2.php'); ...

react-webcam npm package for optimizing video size

In my React app, I'm utilizing the npm package react-webcam. The <Webcam /> component is enclosed within a div with a dimension of {width: 100vw, height 100vh} I aim for the video element to adjust to the parent div's size and cover 100% ...

Layout featuring center-aligned fixed-width design with elements stretching across the entire width of the page

How can I create a centered fixed-width layout for my page while also having headings with a background that extends over the whole page, without having to break up the single fixed-width+margin auto div into many separate divs? ...

Invoke a method within an *ngIf statement in Angular 5

Suppose I have the following code snippet: <div *ngIf="item">lorem ipsum</div> Is there a way to trigger a function if the *ngIf condition is true? Perhaps something like this... <div *ngIf="(item) : callFunction() ? ...">lorem ipsum& ...

JavaScript encountered an abrupt cessation of input, catching us off guard

Can someone please help me identify the issue with the JavaScript code below? I encountered an error message stating "Unexpected end of input", but upon reviewing the code, I couldn't find any apparent errors. All my statements seem to be properly ter ...

javascript mysql and php clash when it comes to loading

I am encountering an issue where I cannot fetch data from my phpMyAdmin database using php code when loading the map api that utilizes javascript. Currently, only the map javascript is being loaded. I have valuable data stored in my database and any assis ...

Is there a way to automatically add a div to the window as the user scrolls and then hide the div when they scroll back to the

Seeking assistance with creating a function that will add a 'sticky' class to the menu when the user scrolls down to the middle, and then append a div when the 'sticky' class is present. Currently facing issues where the div keeps appen ...

Dynamic content in CSS horizontal alignment

In a parent div with fixed width, I have dynamically created divs that I want to distribute horizontally without knowing the exact number of elements. I tried using the "Using inline-block and justified text" technique from a CSS Tricks page but it did not ...

Switching between VR/StereoEffect modes in Three.js

The initial scene is functioning well in VR mode, but the challenge lies in switching back to normal mode. var scene = new THREE.Scene() var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 ) camera.position.set(70 ...

Save an HTML5 canvas element as a picture using JavaScript and specify the file extension

Is there a way to save an Html5 canvas element as an image file using Javascript? I've tried using the CanvasToImage library, but it doesn't seem to work for this purpose. You can view my current code on JsFiddle. <div id="canvas_container" ...

Error: Trying to access the 'title' property of an undefined variable in Vue.js

Creating a replica of hackernews by utilizing the axios API. The NewItem.vue component is not receiving any data, resulting in an error — TypeError: Cannot read property 'title' of undefined. Can you identify what's causing this issue in t ...

What are some ways to render a React component when its ID is only determined after making an AJAX call?

Currently, I am working on developing a chat application where a chat message is immediately displayed (using a React component) once the user sends it by hitting the Enter key: https://i.sstatic.net/MJXLd.png https://i.sstatic.net/S6thO.png As shown in ...

Properly setting up a personalized input component in Angular 6

After attempting to create a custom input component with debounce functionality, I decided to follow the advice provided in this helpful suggestion. Although the debounce feature is working, I encountered an issue where the initial value of the input comp ...

Recreating a CSS3 animation for Internet Explorer 9

While I am aware that CSS3 animations do not function properly in IE9 and below, I have managed to create a transition effect for a header that becomes fixed and shrinks in modern browsers with the following CSS: /** This triggers when the viewport is scr ...

I am struggling to link my JS application with a PHP file as it is showing "PHP file not found

I am facing an issue with my JS application. I am unable to send data from jQuery to a PHP file, as I encountered this error message: POST https://magazyn.rob-tech.pl/savesettings.php 404 The app is running on PORT=8080 npm run start and the package.json ...

Issue with fading hover effect on links is not functioning

I recently implemented a fade link hover effect using the code snippet below: a:link {color:#333333; text-decoration: none; -o-transition:.5s; -ms-transition:.5s; -moz-transition:.5s; -webkit-transition:.5s; transition:.5s;} a:visited {color:#FF0033; ...

How can we detect line breaks within a selection using JavaScript?

Apologies for the lack of expertise in the content below, as it is being produced by a designer experimenting with coding :D The goal here is to determine the number of lines selected or highlighted by the cursor. When I mention "lines," I mean what is vi ...