Search code examples
csssvgpositionscalecenter

How to "transform: scale()" from the center of the path?


I want to increase the scale of the segments on hover, while keeping their original position what would look like "increasing the stroke width" (what isn't the way it should work, because i want the whole path consist of "actual path")

Somehow they also change position when doing so, it looks like the origin the upscaling is performed from doesn't correspond with the center of the path, but rather the top left corner.

[1] transform-origin: center; isn't what I want to do here because it sets the origin to the center of the image, not to the center of the path.

<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 1500 1500" xmlns="http://www.w3.org/2000/svg" id="logo">
<style type="text/css">
<!-- segments -->
.logo_segment {
fill:#000;
transition: all .2s ease-in-out;
<!-- transform-origin: center; < [1] Doesn't work the way I want to-->
}
.logo_segment:hover {
transform: scale(1.05);
transition: all .2s ease-in-out;
}
</style>
<!-- segments; clockwise, starting left-->
<path stroke="red" stroke-width="5" class="logo_segment" d="m390.56 934.47-3e-3 -369.1-6e-3 6e-3 -300.53-173.36-0.01962 2e-3 -0.002003 715.79h3e-3l300.58-173.35"/>
<path stroke="red" stroke-width="5" class="logo_segment" d="m410.21 531.4 318.07-183.59 2.0982-1.1952-0.02653-345.87 0.00601-0.74104-620.16 357.8-0.67685 0.24497 300.69 173.35"/>
<path stroke="red" stroke-width="5" class="logo_segment" d="m769.58 346.54 320.1 184.8v0.0693l300.57-173.32-0.036-0.0367-619.97-357.68-0.65801-0.36979-0.01 344.55"/>
<path stroke="red" stroke-width="5" class="logo_segment" d="m1109.4 565.35 0.01 369.46v0.01l300.56 173.35 0.053-716.15-0.071-0.0183-300.55 173.35"/>
</svg>
 


Solution

  • You have to calculate the Scale centerpoint (actually a translate) for each of the 6 <path> shapes.

    Use a standard JavaScript Web Component <svg-hexagon> to create all dynamically.

    I leave the animations to you:

    customElements.define("svg-hexagon", class extends HTMLElement {
      connectedCallback() {
        this.innerHTML = `<svg viewBox="0 0 1500 1500">` +
          `<style>path{stroke:red;stroke-width:15;fill:lightgreen}path:hover{fill:gold}</style>` +
          `<g transform="scale(0.8) translate(200 200)"></g></svg>`;
        let paths = this.querySelector("g");
        let xPos = 360;
        for (let i = 0; i < 6; i++) {
          let path = document.createElementNS("http://www.w3.org/2000/svg", "path");
          let pathlocation = `rotate(${i*60} 750 750)`;
          path.setAttribute("transform", pathlocation);
          path.setAttribute("d", `m${xPos} 935 0-369 0 0-301-173 0 0 0 716h0l301-173`);
          paths.append(path);
          path.onmouseenter = (e) => {
            let {left,top,x,y,width,height } = path.getBBox();
            let scale = 1.5;
            let cx = -(x + (width / 2)) * (scale - 1);
            let cy = -(y + (height / 2)) * (scale - 1);
            path.setAttribute("transform",
              `${pathlocation} translate(${cx} ${cy}) scale(${scale})`);
            paths.append(path); // put path on top, there is no z-index in SVG
          }
          path.onmouseleave = (e) => {
            if(!e.ctrlKey) path.setAttribute("transform", pathlocation);
          }
        }
      }
    })
    svg-hexagon {
      width: 180px;
      display: inline-block;
      background: rebeccapurple
    }
    <svg-hexagon></svg-hexagon>
    <svg-hexagon></svg-hexagon>
    <svg-hexagon></svg-hexagon>