简体   繁体   中英

Scale svg group without changing position

I would like to increase group of elements size when hover it.

I have used transform: scale() CSS property but when I hover object is moving from it's original position

 p { font-family: Lato; } #stops>g:hover { transform: scale(14); cursor: pointer; } 
 <svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 775.43 469.98"> <defs> <style>.cls-1{fill:none;stroke-width:5px;}.cls-1,.cls-2{stroke:#a15256;}.cls-2{fill:#fff;}.cls-3{isolation:isolate;font-size:42.79px;font-family:ArialMT, Arial;}</style> </defs> <title>line</title> <path id="path7" class="cls-1" d="M202,67.72,329.33,215.86" transform="translate(-200.1 -66.09)" /> <path id="path8" class="cls-1" d="M329.35,215.87,449,355" transform="translate(-200.1 -66.09)" /> <path id="path9" class="cls-1" d="M449,355c41.53,51.11,96.22,63.08,117.9,69.28" transform="translate(-200.1 -66.09)" /> <path id="path10" class="cls-1" d="M566.86,424.29C655.43,460.48,977.38,391.48,973,536" transform="translate(-200.1 -66.09)" /> <g id="stops"> <g id="g3670"> <circle class="cls-2" cx="129.24" cy="149.78" r="13.58" /> <text id="text3668" class="cls-3" transform="translate(120.84 114.12)">Station1</text> </g> <g id="g3700"> <circle class="cls-2" cx="248.91" cy="288.93" r="13.58" /> <text id="text3698" class="cls-3" transform="translate(284.5 239)">Station2</text> </g> <g id="g3750"> <circle class="cls-2" cx="366.75" cy="358.2" r="13.58" /> <text id="text3748" class="cls-3" transform="translate(134.96 379.59)">Station3</text> </g> </g> </svg> 

Expected behaviour

I would like to increase text size and station circle ( and fill it ) without changing their position.

It could be done with css, but if I could have recommendation of libraries because I would make animations on the subway line ( trains circulations ) that would be great

In the next demo I'm removing the transformation from the text and I'm adding x and y attributes. The transformation happens when you mouse over the circle. In order to transform the text as well I'm using this selector: #stops g circle:hover + text

Alternatively instead of transformation for the text you could have changed the font size.

 text{ font-family: Lato; font-size:16px; } #stops g circle:hover { transform: scale(2); transform-origin: 50% 50%; transform-box: fill-box; cursor: pointer; } #stops g circle:hover + text{ transform: scale(2); transform-origin: 0% 50%; transform-box: fill-box; cursor: pointer; pointer-events:none; } 
 <svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 775.43 469.98"> <defs> <style>.cls-1{fill:none;stroke-width:5px;}.cls-1,.cls-2{stroke:#a15256;}.cls-2{fill:#fff;}.cls-3{isolation:isolate;font-size:42.79px;font-family:ArialMT, Arial;}</style> </defs> <title>line</title> <path id="path7" class="cls-1" d="M202,67.72,329.33,215.86" transform="translate(-200.1 -66.09)" /> <path id="path8" class="cls-1" d="M329.35,215.87,449,355" transform="translate(-200.1 -66.09)" /> <path id="path9" class="cls-1" d="M449,355c41.53,51.11,96.22,63.08,117.9,69.28" transform="translate(-200.1 -66.09)" /> <path id="path10" class="cls-1" d="M566.86,424.29C655.43,460.48,977.38,391.48,973,536" transform="translate(-200.1 -66.09)" /> <g id="stops"> <g id="g3670"> <circle class="cls-2" cx="129.24" cy="149.78" r="13.58" /> <text id="text3668" class="cls-3" x="145" y="149.78" >Station1</text> </g> <g id="g3700"> <circle class="cls-2" cx="248.91" cy="288.93" r="13.58" /> <text id="text3698" class="cls-3" x="270" y="288.93">Station2</text> </g> <g id="g3750"> <circle class="cls-2" cx="366.75" cy="358.2" r="13.58" /> <text id="text3748" class="cls-3" x="385" y="358.2">Station3</text> </g> </g> </svg> 

The OP is commenting that

The hover should be on gg:hover not g circle:hover

In this case I'm adding a rectangle to the g element. The rectangle is as big as the g's bounding box. Everything in the g element except the rect has pointer-events:none . The transformation happens around the center of the circle.

 text{ font-family: Lato; font-size:16px; } g * {pointer-events:none;} g rect{pointer-events:all;} #stops g{transform: scale(1);} #stops g:hover { transform: scale(2); transform-origin: 129.24px 149.78px; cursor: pointer; } 
 <svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 775.43 469.98"> <defs> <style>.cls-1{fill:none;stroke-width:5px;}.cls-1,.cls-2{stroke:#a15256;}.cls-2{fill:#fff;}.cls-3{isolation:isolate;font-size:42.79px;font-family:ArialMT, Arial;}</style> </defs> <title>line</title> <path id="path7" class="cls-1" d="M202,67.72,329.33,215.86" transform="translate(-200.1 -66.09)" /> <path id="path8" class="cls-1" d="M329.35,215.87,449,355" transform="translate(-200.1 -66.09)" /> <path id="path9" class="cls-1" d="M449,355c41.53,51.11,96.22,63.08,117.9,69.28" transform="translate(-200.1 -66.09)" /> <path id="path10" class="cls-1" d="M566.86,424.29C655.43,460.48,977.38,391.48,973,536" transform="translate(-200.1 -66.09)" /> <g id="stops"> <g id="g3670"> <rect x="115" y="110" width="187" height="52" fill="none" /> <circle class="cls-2" cx="129.24" cy="149.78" r="13.58" /> <text id="text3668" class="cls-3" x="145" y="149.78" >Station1</text> </g> </g> </svg> 

In order to calculate the <g> 's bounding box you can use javascript and the method getBBox() .

In order to better understand what happens please add a fill to the <rect>

You can keep the text transformation if this is what you want.

UPDATE 2

the OP is commenting:

Can you make an example with three dots please ?

Next comes the example. In this case I'm using Javascript to set the size of the rects and the value for the transform-origin of every group. If you need only the markup you can copy it from the inspector. Since the OP commented that they would like to keep the text transformation in this example the text keeps the transformation instead of the x and y attributes.

 let stops = document.querySelector("#stops"); // all the g elements in the stops let gs = stops.querySelectorAll("g"); // for each g in the gs gs.forEach(g=>{ // the rectangle in this g element let thisRect = g.querySelector("rect"); // the circle in this g element let thisCircle = g.querySelector("circle"); // the coords of the circle's center used for the transform-origin let x = thisCircle.getAttribute("cx"); let y = thisCircle.getAttribute("cy"); // the bounding box of the group let bb = g.getBBox(); // set the rect's attributes thisRect.setAttributeNS(null, "x", bb.x); thisRect.setAttributeNS(null, "y", bb.y); thisRect.setAttributeNS(null, "width", bb.width); thisRect.setAttributeNS(null, "height", bb.height); // set the value for the transform-origin for this group g.style.transformOrigin = `${x}px ${y}px`; }) 
 text{ font-family: Lato; font-size:16px; } g * {pointer-events:none;} g rect{pointer-events:all;} #stops g{transform: scale(1);cursor: pointer;} #stops g:hover { transform: scale(2); } 
 <svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 775.43 469.98"> <defs> <style>.cls-1{fill:none;stroke-width:5px;}.cls-1,.cls-2{stroke:#a15256;}.cls-2{fill:#fff;}.cls-3{isolation:isolate;font-size:42.79px;font-family:ArialMT, Arial;}</style> </defs> <title>line</title> <path id="path7" class="cls-1" d="M202,67.72,329.33,215.86" transform="translate(-200.1 -66.09)" /> <path id="path8" class="cls-1" d="M329.35,215.87,449,355" transform="translate(-200.1 -66.09)" /> <path id="path9" class="cls-1" d="M449,355c41.53,51.11,96.22,63.08,117.9,69.28" transform="translate(-200.1 -66.09)" /> <path id="path10" class="cls-1" d="M566.86,424.29C655.43,460.48,977.38,391.48,973,536" transform="translate(-200.1 -66.09)" /> <g id="stops"> <g id="g3670"> <rect fill="none"/> <circle class="cls-2" cx="129.24" cy="149.78" r="13.58" /> <text id="text3668" class="cls-3" transform="translate(145 160)">Station1</text> </g> <g id="g3700"> <rect fill="none"/> <circle class="cls-2" cx="248.91" cy="288.93" r="13.58" /> <text id="text3698" class="cls-3" transform="translate(270 300)">Station2</text> </g> <g id="g3750"> <rect fill="none"/> <circle class="cls-2" cx="366.75" cy="358.2" r="13.58" /> <text id="text3748" class="cls-3" transform="translate(200 400)">Station3</text> </g> </g> </svg> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM