ReyJust
ReyJust

Reputation: 57

CSS transform scale function moving SVG item position automatically

I am working on a navigation bar in a circle format split in 5.All the elements are SVGs. It really look like a pie chart.While hovering one part, i would like to scale the svg element to the exterior. As i am trying to use scale with this, the element just translate itself further and do the scale effect.I'm not sure but i think it is a problem of overlapping css element? Anyway if someone could help me with this how to tell the part to stay at the same place and then scale bigger, or do i need to manually re-translate the element at the correct place? Thanks, here is a represatation:

#group-part-1>text {
    visibility: hidden;
  }

  #group-part-1:hover text {
    visibility: visible;
  }

  #group-part-2>text {
    visibility: hidden;
  }

  #group-part-2:hover text {
    visibility: visible;
  }

  #group-part-3>text {
    visibility: hidden;
  }

  #group-part-3:hover text {
    visibility: visible;
  }

  #group-part-4>text {
    visibility: hidden;
  }

  #group-part-4:hover text {
    visibility: visible;
  }

  #group-part-5>text {
    visibility: hidden;
  }

  #group-part-5:hover text {
    visibility: visible;
  }

  #part-1:hover {
    fill: red;
    transform: scale(1.2);
  }

  #part-2:hover {
    fill: green;
    transform: scale(1.2);
  }

  #part-3:hover {
    fill: purple;
  }

  #part-4:hover {
    fill: orange;
  }

  #part-5:hover {
    fill: blue;
  }
<svg width="210" height="297" viewBox="0 0 210 297" fill="none" xmlns="http://www.w3.org/2000/svg">
  <g id="example">
    <g id="group-part-5">
      <path id="part-5"
        d="M156.393 107.998C159.608 118.055 159.557 128.873 156.247 138.899C152.936 148.926 146.536 157.647 137.964 163.813L108.768 123.223L156.393 107.998Z"
        fill="black" stroke="black" stroke-width="0.0132292" />
      <text x="160" y="150" fill="black">Project</text>
    </g>
    <g id="group-part-4">
      <path id="part-4"
        d="M137.963 163.813C129.391 169.979 119.087 173.272 108.529 173.222C97.9698 173.171 87.6979 169.78 79.1853 163.532L108.768 123.223L137.963 163.813Z"
        fill="#1A1A1A" stroke="black" stroke-width="0.0132292" />
      <text x="90" y="200" fill="black">About</text>
    </g>

    <g id="group-part-3">
      <path id="part-3"
        d="M79.2054 163.547C70.6897 157.304 64.3689 148.526 61.1491 138.469C57.9293 128.413 57.9756 117.596 61.2815 107.568L108.768 123.223L79.2054 163.547Z"
        fill="#333333" stroke="black" stroke-width="0.0132292" />
      <text x="10" y="150" fill="black">Contact</text>
    </g>

    <g id="group-part-2">
      <path id="part-2"
        d="M61.2928 107.534C64.606 97.508 71.008 88.7885 79.5814 82.625C88.1547 76.4615 98.4593 73.1703 109.018 73.2231L108.768 123.223L61.2928 107.534Z"
        fill="#4D4D4D" stroke="black" stroke-width="0.0132292" />
      <text x="25" y="75" fill="black">Home</text>
    </g>

    <g id="group-part-1">
      <path id="part-1"
        d="M108.941 73.2228C119.5 73.2594 129.776 76.6378 138.297 82.8738C146.818 89.1097 153.146 97.8831 156.374 107.937L108.768 123.223L108.941 73.2228Z"
        fill="#666666" stroke="black" stroke-width="0.0132292" />
      <text x="150" y="75" fill="black">Work</text>
    </g>
</svg>

thanks 

Upvotes: 0

Views: 965

Answers (1)

enxaneta
enxaneta

Reputation: 33064

This is the way I would do it:

  1. the svg element is centered around the point {x:0,y:0}: viewBox="-105 -105 210 210"

  2. I calculate the points for the arc in base of the angle of the wedge and the radius of the circle

  3. In this example I'm rotating the text too so I'm putting both the wedge and the text in the same group (#group_part5) and I'm transforming the group on mouse over: transform: translate(10px, 0) scale(1.2);

  4. I'm wrapping everything in a different group (#example) and I'm rotating this group to the needed position.

//the angle for the circle wedge
let angle = 2*Math.PI/5;
//the radius of the circle wedge
let r = 60;
//calculate the points for the arc
let p1 = {x:r*Math.cos(-angle/2),
          y:r*Math.sin(-angle/2)};

let p2 = {x:r*Math.cos(angle/2),
          y:r*Math.sin(angle/2)};
//build the d attribute
let d = `M0,0L${p1.x},${p1.y}A${r},${r} 0 0 1 ${p2.x},${p2.y} z`;
//set the d attribute of the path
part5.setAttribute("d",d);
svg {
  border: solid;
}

#example {
  transform: rotate(36deg);
}

#group_part5:hover {
  fill: red;
  transform: translate(10px, 0) scale(1.2);
}

#group_part5:hover text {
  fill: black;
}
<svg width="210" viewBox="-105 -105 210 210">
  <g id="example">
    <g id="group_part5">
      <path id="part5" d="" />
      <text fill="none" x="30">Project</text>
    </g>
  </g>
</svg>

Observation: If you don't want to use javascript you can take the d attribute for the path from the inspector.

UPDATE

The OP is commenting

The only thing is that the 'origin' top-left corner is moving, i want it to stay at the same place as well as the borders, the border only need to be longer and the circle exterior border further

If I understand you correctly in the previous demo please replace transform: translate(10px, 0) scale(1.2); with transform: scale(1.2);

If this is what you need there is a simpler way to do this: instead or scaling the wedge you can add a wide stroke - the same color as the fill - like in the following demo:

Please take a look:

svg {
  border: solid;
}

#example {
  transform: rotate(36deg);
}

#group_part5:hover {
  fill: red;
  /*transform: translate(10px, 0) scale(1.2);*/
}

#group_part5:hover path:nth-of-type(2){stroke:red;}

#group_part5:hover text {
  fill: black;
}
<svg width="210" viewBox="-105 -105 210 210">
  <g id="example">
    <g id="group_part5">
      <path id="part5" d="M0,0L48.54101966249685,-35.26711513754839A60,60 0 0 1 48.54101966249685,35.26711513754839 z"></path>
      <path d="M48.54101966249685,-35.26711513754839A60,60 0 0 1 48.54101966249685,35.26711513754839" fill="none" stroke-width="10"></path>
      <text fill="none" x="30">Project</text>
    </g>
  </g>
</svg>

Upvotes: 1

Related Questions