1

I am stuck on trying to add a simple scale effect on group elements inside an SVG. By hovering over a list item a group element from the SVG should scale-up, however, when doing so it will lose its position in the element since it is using translate.

Any idea on how to tackle this or how I should approach this.

List markup is as follow:

li.active {
  color: red;
}

.round {
  transition: transform .3 ease;
}

.round.active {
  transform: scale(1.3)
}

<ul class="list">
  <li data-number="round1">round 1</li>
  <li data-number="round1-copy">round 2</li>
</ul>

jQuery markup:

    $('.list > li').on('mouseover', function() {
      var _this = $(this),
        dataNumber = _this.data('number');
      _this.addClass('active');
      $('#' + dataNumber).addClass('active')
    });

    $('.list > li').on('mouseleave', function() {
      $(this).removeClass('active');
      $('.round.active').removeClass('active')
    });

A fiddle was set up here.

Any help is much appreciated :)

prettyInPink
  • 3,291
  • 3
  • 21
  • 32

2 Answers2

2

Well, it's not easy to do this by using an inline transform and a scale like you are using.

But based on this explanation about getComputedStyle() and trasnform, you can remove the idea of using a CSS class and use the element computed style, where you get the element current transform value (using getComputedStyle() then a regex to get each value of the matrix).

After getting the value mentioned above, modify the scaleX and scaleY values (those values are the index 0 and 3 of the matrix array), then set the modified matrix back to the element, take a look:

$(function() {
  $('.list > li').on('mouseover', function() {
    var dataNumber = $(this).data('number');
    $(this).addClass('active');
    let roundElem = $('#' + dataNumber)[0];
    adjustTransform(roundElem, 1.3)
  });

  $('.list > li').on('mouseleave', function() {
    $(this).removeClass('active');
    var dataNumber = $(this).data('number');
    let roundElem = $('#' + dataNumber)[0];
    adjustTransform(roundElem, 1)

  });

  function adjustTransform(elem, scale) {
    let trans = getComputedStyle(elem).transform;
    numberPattern = /-?\d+\.?\d+|\d+/g;
    v = trans.match(numberPattern);
    let newMatrix = "matrix(" + scale + ", " + v[1] + "," + v[2] + "," + scale + "," + v[4] + "," + v[5] + ")"
    elem.style.transform = newMatrix
  }

});
li.active {
  color: red;
}

.round {
  transition: transform .3 ease;
}
<ul class="list">
  <li data-number="round1">round 1</li>
  <li data-number="round1-copy">round 2</li>
</ul>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="300px" height="300px" viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
    <title>square</title>
    <desc>Created with Sketch.</desc>
    <defs>
        <rect id="path-1" x="0" y="0" width="300" height="300"></rect>
    </defs>
    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g id="square">
            <g id="rectangle">
                <use fill="#D8D8D8" fill-rule="evenodd" xlink:href="#path-1"></use>
                <rect stroke="#979797" stroke-width="1" x="0.5" y="0.5" width="299" height="299"></rect>
            </g>
            <g id="round1" class="round" transform="translate(119.000000, 119.000000)">
                <g id="number">
                    <circle id="Oval" stroke="#979797" fill="#FFFFFF" cx="31" cy="31" r="31"></circle>
                    <text id="1" font-family="Helvetica-Bold, Helvetica" font-size="20" font-weight="bold" fill="#272A2F">
                        <tspan x="25" y="38">1</tspan>
                    </text>
                </g>
            </g>
            <g id="round1-copy" class="round" transform="translate(181.000000, 57.000000)">
                <g id="number2">
                    <circle id="Oval2" stroke="#979797" fill="#FFFFFF" cx="31" cy="31" r="31"></circle>
                    <text id="2" font-family="Helvetica-Bold, Helvetica" font-size="20" font-weight="bold" fill="#272A2F">
                        <tspan x="25" y="38">2</tspan>
                    </text>
                </g>
            </g>
        </g>
    </g>
</svg>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

this may not be very performatic if you'll have many elements using getComputedStyle on hover

Calvin Nunes
  • 6,376
  • 4
  • 20
  • 48
2

You can simply add another g element and keep your initial code. You can also simplify it since you don't need to toggle a class of li. Consider :hover instead

$(function() {
  $('.list > li').on('mouseover', function() {
    var _this = $(this),
        dataNumber = _this.data('number');
    $('#'+dataNumber).addClass('active')
  });

  $('.list > li').on('mouseleave', function() {
    $('g.active').removeClass('active')
  });

});
li:hover {
  color: red;
}

g {
  transition: transform .3s ease;
  transform-origin:center;
  transform-box:fill-box;
}

g.active {
  transform: scale(1.3);
}
<ul class="list">
  <li data-number="round1">round 1</li>
  <li data-number="round1-copy">round 2</li>
</ul>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="300px" height="300px" viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
    <title>square</title>
    <desc>Created with Sketch.</desc>
    <defs>
        <rect id="path-1" x="0" y="0" width="300" height="300"></rect>
    </defs>
    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g id="square">
            <g id="rectangle">
                <use fill="#D8D8D8" fill-rule="evenodd" xlink:href="#path-1"></use>
                <rect stroke="#979797" stroke-width="1" x="0.5" y="0.5" width="299" height="299"></rect>
            </g>
            <g id="round1">
            <g  class="round" transform="translate(119.000000, 119.000000)">
                <g id="number">
                    <circle id="Oval" stroke="#979797" fill="#FFFFFF" cx="31" cy="31" r="31"></circle>
                    <text id="1" font-family="Helvetica-Bold, Helvetica" font-size="20" font-weight="bold" fill="#272A2F">
                        <tspan x="25" y="38">1</tspan>
                    </text>
                </g>
            </g>
            </g>
            <g id="round1-copy" >
            <g class="round" transform="translate(181.000000, 57.000000)">
                <g id="number2">
                    <circle id="Oval2" stroke="#979797" fill="#FFFFFF" cx="31" cy="31" r="31"></circle>
                    <text id="2" font-family="Helvetica-Bold, Helvetica" font-size="20" font-weight="bold" fill="#272A2F">
                        <tspan x="25" y="38">2</tspan>
                    </text>
                </g>
            </g>
            </g>
        </g>
    </g>
</svg>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

And if you adjust your HTML code you can get rid of the JS part:

li:hover {
  color: red;
}

g {
  transition: transform .3s ease;
  transform-origin:center;
  transform-box:fill-box;
}

.list :last-child {
   list-style:none;
   margin:10px 0 0 -10px;
}
[data-number="round1"]:hover ~ li:last-child svg #round1,
[data-number="round2"]:hover ~ li:last-child svg #round2{
  transform: scale(1.3);
}
<ul class="list">
  <li data-number="round1">round 1</li>
  <li data-number="round2">round 2</li>
  <li>
<svg width="300px" height="300px" viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
    <title>square</title>
    <desc>Created with Sketch.</desc>
    <defs>
        <rect id="path-1" x="0" y="0" width="300" height="300"></rect>
    </defs>
    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g id="square">
            <g id="rectangle">
                <use fill="#D8D8D8" fill-rule="evenodd" xlink:href="#path-1"></use>
                <rect stroke="#979797" stroke-width="1" x="0.5" y="0.5" width="299" height="299"></rect>
            </g>
            <g id="round1">
            <g  class="round" transform="translate(119.000000, 119.000000)">
                <g id="number">
                    <circle id="Oval" stroke="#979797" fill="#FFFFFF" cx="31" cy="31" r="31"></circle>
                    <text id="1" font-family="Helvetica-Bold, Helvetica" font-size="20" font-weight="bold" fill="#272A2F">
                        <tspan x="25" y="38">1</tspan>
                    </text>
                </g>
            </g>
            </g>
            <g id="round2" >
            <g class="round" transform="translate(181.000000, 57.000000)">
                <g id="number2">
                    <circle id="Oval2" stroke="#979797" fill="#FFFFFF" cx="31" cy="31" r="31"></circle>
                    <text id="2" font-family="Helvetica-Bold, Helvetica" font-size="20" font-weight="bold" fill="#272A2F">
                        <tspan x="25" y="38">2</tspan>
                    </text>
                </g>
            </g>
            </g>
        </g>
    </g>
</svg>
</li></ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415