Darthmaul
Darthmaul

Reputation: 151

Scaling an SVG with complex animation paths

I have this code for an SVG on my page. It's a track and I have a car that scrolls along the path as you go down the page.

<div class="my-svg-container">
<svg viewBox="-220 -219 1250 2212.5" style="
 position: absolute;
" class="my-svg" preserveAspectRatio="xMinYMin meet"><defs>
<style>.cls-1,.cls-10,.cls-11,.cls-12,.cls-13,.cls-14,.cls-15,.cls-16,.cls-17,.cls-3,.cls-4,.cls-5,.cls-6,.cls-7,.cls-8,.cls-9{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{stroke:#2d2d2d;stroke-width:100px;}.cls-10,.cls-11,.cls-12,.cls-13,.cls-14,.cls-15,.cls-16,.cls-17,.cls-4,.cls-5,.cls-6,.cls-7,.cls-8,.cls-9{stroke:#fad000;stroke-width:9px;}.cls-4{stroke-dasharray:12 11.54;}.cls-5{stroke-dasharray:12 10.64;}.cls-6{stroke-dasharray:12 12.26;}.cls-7{stroke-dasharray:12 13.27;}.cls-8{stroke-dasharray:12 12.67;}.cls-9{stroke-dasharray:12 10.99;}.cls-10{stroke-dasharray:12 12.24;}.cls-11{stroke-dasharray:12 13.42;}.cls-12{stroke-dasharray:12 12.63;}.cls-13{stroke-dasharray:12 10.47;}.cls-14{stroke-dasharray:12 11.73;}.cls-15{stroke-dasharray:12 11.95;}.cls-16{stroke-dasharray:12 12.17;}</style>
 <clipPath id="clip-path" transform="translate(4349 2519.5)"><rect class="cls-1" x="-4349" y="-2519.5" width="868.18" height="1964.5"></rect></clipPath></defs><title>Road(whole)</title>
 <g class="cls-2">

 <path id="theMotionPath" class="cls-3" d="M709.08 0.54v306s7,91-106,91h-461s-92-8-92,96v444s-6,78,64,78h606s98-10,98,90v394s5,84-84,84h-522s-90-3-90,90v290" ></path>
 <line class="cls-4" x1="709.08" y1="17.54" x2="709.08" y2="294.23"></line>

 <path class="cls-5" d="M-3640.93-2196.91c-3.89,25-21,69.87-93.68,74.09" transform="translate(4349 2519.5)"></path>
 <line class="cls-6" x1="584.81" y1="397" x2="154.21" y2="397"></line>

 <path class="cls-7" d="M-4226.14-2121.52c-25.35,3.77-67.35,19.56-72.3,82.4" transform="translate(4349 2519.5)"></path>
 <line class="cls-8" x1="50.08" y1="511.67" x2="50.08" y2="924.67"></line>

 <path class="cls-9" d="M-4298.32-1565.54c2.45,21,12.58,54.8,51.94,60.28" transform="translate(4349 2519.5)"></path>
 <line class="cls-10" x1="132.32" y1="1015" x2="707.96" y2="1015"></line>

 <path class="cls-11" d="M-3609.53-1504.15c26.79,2.72,72.47,16.34,78,77" transform="translate(4349 2519.5)"></path>
 <line class="cls-12" x1="818.08" y1="1123.63" x2="818.08" y2="1486.69"></line>

 <path class="cls-13" d="M-3532-1004.08c-3.44,22.94-17.31,62.35-71.73,67.11" transform="translate(4349 2519.5)"></path>
 <line class="cls-14" x1="716.35" y1="1583" x2="223.99" y2="1583"></line>

 <path class="cls-15" d="M-4154.73-934.92c-24.59,4.26-66.45,19.86-71.61,76.46" transform="translate(4349 2519.5)"></path>
 <line class="cls-16" x1="122.13" y1="1691.17" x2="122.13" y2="1950.92"></line>


 <path class="cls-17" d="M-4226.87-562.5
 v6m.13-296
 q-.14,2.93-.13,6
 v6
 m96-96
 h-6
 s-2.23-.07-6,.16
 m533.95-.29q-2.92.14-6,.13
 h-6
 m90-90
 v6
 s.13,2.24,0,6
 m-.09-406
 c.08,2,.12,4,.12,6
 v6
 m-104-96
 h6
 s2.22-.23,6-.27
 m-618,.07
 c1.94.13,3.93.2,6,.2h6m-70-84v6s-.18,2.26-.12,6m.22-456
 q-.11,2.94-.1,6v6m98-102h-6s-2.23-.19-6-.13m473,0q-2.94.09-6,.09
 h-6m112-97v6a57.48,57.48,0,0,1,0,6m0-312v6" transform="translate(4349 2519.5)"></path></g>


 <g class="shakyimage">
 <image speed="2" width="5%" height="5%" x="-65" y="-30" xlink:href="https://cdn3.iconfinder.com/data/icons/cars-28/512/Car_5-512.png" id="dot" ></image>

 </g>
 <g >
 <image width="45%" height="11%" x="423" y="-100" xlink:href="https://cdn0.iconfinder.com/data/icons/gpsmapicons/red/gpsmapicons07.png">
 </g>
 <g >
 <image width="30%" height="10%" x="-66" y="1782.17" xlink:href="https://cdn0.iconfinder.com/data/icons/gpsmapicons/red/gpsmapicons07.png">
 </g>
 </svg>

</div>

This functions very well as-is. My main issue is I have built the page to align with the track. This means that the end of the track perfectly aligns with the last section of the page. The problem is, when you make the page smaller the track shrinks in size.

Currently I have tried doing this:

.my-svg-container{
  display: inline-block;
  position: relative;
  width: 100%;
  padding-bottom: 38.5%; /* depends on svg ratio, for my zebra height/width = 1.2 so padding-bottom = 50% * 1.2 = 60% */

  vertical-align: middle; /* top | middle | bottom ... do what you want */
 }


 .my-svg{ /* svg into : object, img or inline */
   display: block;
   position: absolute;
   top: 0;
   left: 0;
   width: 100%; /* only required for <img /> */
 }

However this seems to have no effect on the responsiveness.

So is it possible to basically make this scale, but retain its position on the page? The height seems to be the main issue; positioning seems to be intact, but the height shrinks so everything isn't aligned any more.

Thanks! Let me know if you need more info

Upvotes: 2

Views: 103

Answers (2)

Paul LeBeau
Paul LeBeau

Reputation: 101820

Try changing your SVG to

preserveAspectRatio="xMinYMin slice"

It should mean that the SVG stays the same height as your content, but that the right hand side of the SVG gets clipped off as the page gets narrower.

If you want both sides (left and right) to get clipped off at the same rate, so the SVG remains centred, then use:

preserveAspectRatio="xMidYMin slice"

Upvotes: 0

Miguel Ventura
Miguel Ventura

Reputation: 10458

You are scaling the SVG image proportionally, which means that when the width changes (to adapt to the page width), the height must also change to keep the image proportions.

In part this is what you want, because scaling the image disregarding proportions would cause your traffic sign or the car to become stretched. On the other hand you want to keep the road height fixed, so here are your alternatives:

Alternative 1 — don't scale the image

This may seem counter to what you're looking for but it's definitely worth considering. You're not scaling the text around which the image revolves, so why scaling the image at all? Just keep both centered with constant size.

Alternative 2 — scale parts of your SVG separately

You can split your SVG into the parts you want with fixed proportion (like the traffic sign and vertical parts of roads) and variable proportion (like horizontal roads). You can use the preserveAspectRatio and viewBox attributes to. There's an example here (works on Chrome but not on current Firefox).

Alternative 3 — scale in discrete steps

If you really want the image to become bigger on a larger display, but don't feel like going through the complexity of alternative 2, you can prepare several SVGs for several width / height ratios and use media queries to display the appropriate one for the appropriate width interval.

Upvotes: 1

Related Questions