Umieszczanie i animacja ilustracji SVG

W tym artykule poznasz sposoby umieszczenia SVG na stronie. Każdy z przedstawionych sposobów ma zalety i wady. Od Ciebie będzie zależało, który najbardziej pasuje do Twoich potrzeb.

Ten artykuł jest wpisem gościnnym. Uważasz, że znasz bardzo dobrze jakiś temat związany z Web Developmentem i chciałbyś się podzielić wiedzą? Napisz na kontakt@devcorner.pl.

Pomysł na napisanie tego artykułu wziął się z ostatniego konkursu na stronie kodu.je, w którym brałem udział. W konkursie chodziło o dodanie animacji do obrazka wektorowego.

Rysunek, na którym będziemy eksperymentować:

twarz SVG

<svg width="66mm" height="76mm" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="whole_head" class="whole_head">
      <g id="hair" class="hair" fill="#696969">
        <ellipse cx="117.3616" cy="81.931541" rx="14.079614" ry="9.354911"/>
        <ellipse cx="136.5439" cy="89.869041" rx="11.150298" ry="9.354911"/>
        <ellipse cx="101.20311" cy="90.152534" rx="11.244791" ry="9.354911"/>
        <ellipse cx="118.49554" cy="109.99628" rx="32.505955" ry="29.387648"/>
      </g>
        <ellipse id="head" class="head" cx="118.22363" cy="119.34193" fill="#ffa07a" rx="28.051781" ry="28.981661" stroke="#fefefe" stroke-linejoin="bevel" stroke-opacity=".992157" stroke-width=".6"/>
        <path id="nose" class="nose"
          d="m117.94196 111.21102 4.27249-.18063c.51778-.0219.95223.37733.97412.8951l.53624 12.68397c.0219.51779-.41937.76857-.89509.97412-.98594.42602-1.89141.9192-4.27251.18063-.49497-.15353-.95222-.37732-.97411-.8951l-.53624-12.68396c-.0219-.51778.37732-.95224.8951-.97413z"
        fill="#ff8c00"/>
        <g id="eye_left" class="eye_left">
          <ellipse  cx="107.10901" cy="110.98846" rx="3.071056" ry="2.882069"/>
          <ellipse cx="108.12805" cy="109.98856" fill="#fff" rx=".622318" ry=".577937"/>
        </g>
        <g id="eye_right" class="eye_right">
          <ellipse cx="131.06325" cy="110.75223" rx="3.071056" ry="2.882069"/>
          <ellipse cx="132.08414" cy="109.8378" fill="#fff" rx=".622318" ry=".577937"/>
        </g>
        <ellipse id="ear" class="ear" cx="88.733475" cy="120.53528" fill="#ffa07a" rx="4.276312" ry="6.88219"/>
        <clipPath id="a">
        <path
          d="m78.415859 168.45174c-.000003 1.6237-2.998049 2.93996-5.618104 2.93996s-5.098381-1.31626-5.098386-2.93996c-.000006-1.54626 2.941889-4.6081 4.727059-2.9311.122528.11511.555395.17884.680357-.009 1.451949-2.18095 5.309079 1.31627 5.309074 2.93997z"/></clipPath>
        <path id="mouth" class="mouth" d="m109.74802 132.61397c7.40427.623 14.96733.7218 22.8812-.33762-1.93169 1.28433-7.73325 7.13223-12.85291 6.93419-4.2773-.16546-10.02829-6.59657-10.02829-6.59657z" fill="#404040"/>
        <path id="tongue" class="tongue" clip-path="url(#a)" d="m62.075769 162.23786c7.40427.623 14.96733.7218 22.8812-.33762-1.93169 1.28433-7.73325 7.13223-12.85291 6.93419-4.2773-.16546-10.02829-6.59657-10.02829-6.59657z" fill="#c00" transform="translate(47.672251 -29.62389)"/>
     </g>
</svg>

Spróbujemy go wprawić w ruch.

Najpopularniejszymi metodami dodawania grafiki wektorowej na strony są:

  • <img> jak każdy inny obrazek,
  • w CSS jako background-image,
  • wklejenie kodu SVG do HTML

Dodawanie przez <img> oraz background-image

<img src="face.svg" alt="uśmiechnięta buźka" />
background-image: url(face.svg);

Głównym problemem plików dodanych w ten sposób jest to, że nie mamy dostępu do ich DOM, a w efekcie nie możemy operować na nich przez CSS lub JavaScript. Na stronie Mozzila otwarcie przyznają, że JavaScript oraz zewnętrze zasoby jak CSS, zostały wyłączone w przeglądarkach Firefox z powodów bezpieczeństwa.  Można jednak wprawić w ruch grafikę, poprzez umieszczenie stylów wewnątrz pliku SVG.

Aby naszemu rysunkowi dodać mruganie oczu, do pliku między tagi svg wklejamy:

<style type="text/css">
  .eye_left, .eye_right {
    animation-timing-function: ease-in-out;
    animation-duration: 2s;
    animation-iteration-count: infinite;
    animation-name: blinking;
    }

    @keyframes blinking {
      10% {
        opacity: 0;
      }
      12% {
          opacity: 1;
      }
    }
  </style>

Zaletą tej metody jest mobilność. Możemy przenosić pliki SVG na odrębne strony internetowe, nie martwiąc się o kopiowanie stylów z CSS.

Minusem jest mieszanie ze sobą SVG i CSS. Przy dużych plikach, utrzymanie kodu będzie problematyczne.

PS. Jeżeli ktoś bardzo potrzebuje operować na SVG w <img>, dostępne jest rozwiąznie JavaScript, zamieniająca image na inline.

Wprost do HTML przez <svg>

Wystarczy skopiować kod z pliku wektorowego i kleić na stronę.

Teraz mamy dostęp do całego DOM obrazka i możemy swobodnie na nim operować przez zewnętrze pliki CSS oraz Javascript. Oszczędzamy przy tym na  HTTP request.

Często kod SVG może być wielokrotnie dłuższy od kodu strony, na której ma być umieszczony. Wyobraźcie sobie teraz, że do estetycznie sformatowanego, semantycznego dokumentu HTML dodajemy kod SVG.  Już HTML nie będzie wyglądał przejrzyście. Jeszcze gorzej, gdy mamy parę takich rysunków.

Użycie PHP

W tym wypadku zaciągamy do pracy PHP z backendu.

<?php echo file_get_contents("face.svg"); ?>

lub

<?php readfile("face.svg"); ?>

Tutaj mała dygresja. Nie stosuję tutaj polecenia include, ponieważ przy nagłówku <?xml version=”1.0″ encoding=”UTF-8″?>, parser PHP wyrzuci błędy.

Na tak załączony obrazek działają skrypty oraz zewnętrzne arkusze stylów. Wadą tego użycia jest dodatkowe używanie PHP i mieszczanie jego kodu  z HTML.

Dodawanie przez <object>.

Moja ulubiona metoda. Element <object> reprezentuje zewnętrzne źródła.

<object type="image/svg+xml" data="face.svg">
   Twoja przeglądarka nie obsługuje SVG
</object>

Tutaj również działają skrypty oraz zewnętrzne pliki CSS. Moim skromnym zdaniem to najlepszy sposób osadzania plików SVG.

<embed> oraz <iframe>

Możecie się też natknąć na wyświetlanie SVG w tych tagach, ale są one o wiele mniej popularne od <object>. Pierwszy z nich <embed> jest odradzany z powodu luźnego podejścia implementacji do niego przez różne rodzaje przeglądarek. Jedna wyświetli zawartość, druga poinformuje, że zawartość wymaga wtyczki. <iframe> umożliwia osadzanie innego dokumentu w bieżącej stronie. Jak najbardziej można stosować do plików wektorowych, ale dochodzi zabawa z wielkością okna, obramowaniem i paskiem przewijania.

<iframe src="face.svg"></iframe>

 

animacja w iframe

Podsumowanie

Na koniec mały test. W pliku face.svg umieściłem animację mrugania oczu, a w zewnętrznym arkuszu stylów animację ruchu głowy.

.whole_head {
  animation-timing-function: ease-in-out;
  animation-duration: 2s;
  animation-iteration-count: infinite;
  animation-name: head_down;
}

@keyframes head_down {
  50% {
    transform: translateY(12px);
  }
}

Porównanie animacji w różnych rodzajach dołączenia SVG

Zgodnie z oczekiwaniami, background-image oraz <img> nie mogą pobrać animacji ruchu głowy, ale działają style odpowiadające za mruganie oczu, które są wewnątrz pliku.  Każda następna działa prawidłowo. Przy <iframe> widać ucięty podbródek – należałoby ustawić parametry okna.

Aby w inframe i object głowy się poruszały w górę i w dół, należy podlinkować zewnętrzny arkusz stylów bezpośrednio w pliku SVG.
Można to zrobić nad tagiem <svg> poprzez:
<?xml-stylesheet type="text/css" href="animation.css" ?>

lub  w środku <svg>:

<style type="text/css">
<![CDATA[
    @import url(animation.css);
]]>
</style>

W innym wypadku ruszają się tylko inline i php.

 

Ten artykuł jest wpisem gościnnym. Uważasz, że znasz bardzo dobrze jakiś temat związany z Web Developmentem i chciałbyś się podzielić wiedzą? Napisz na kontakt@devcorner.pl.

Spodobał Ci się artykuł? Dzięki naciśnięciu serduszka poniżej będę wiedział jakie treści tworzyć. Dzięki! :)

17 niesamowitych efektów tekstowych w CSS3 12 niesamowitych karuzel CSS/JS Mobilne menu ze Slicknav.js
View Comments
  • Rady co do animowania SVG od najlepszego w konkursie, szanuję i popieram inicjatywę a przy okazji gratuluję Guy Diamond 🙂

  • Mam pytanie, jak ostylować svg wrzucone w object ?? Na przykład chcę zmienić kolor ścieżki po najechaniu na svg.

    • Na powyższym przykładzie możesz to zrobić np poprzez:
      svg:hover .hair {
      fill: #111111;
      }

      Musisz jednak dodać do pliku SVG arkusz stylów.
      Można to zrobić nad tagiem poprzez:
      xml-stylesheet type=”text/css” href=”animation.css”

      • Teraz rozumie, ale taka opcja wyklucza zmiany styli svg po najechaniu na coś innego niż to svg, czy się mylę ?

        • Masz rację. W takim wypadku jak wyżej możesz zmienić tylko wewnętrzne części svg. Ale możesz to obejść przez js np:

          document.querySelector(„.svgClass”).getSVGDocument().getElementById(„svgInternalID”).setAttribute(„fill”, „red”)

  • Warto dodać że korzystając z webpacka i np. Reacta możemy rozszerzyć Webpacka o plug-in obsługujący import obrazków i wstawianie tak jak komponentów. Wynikowy html będzie zawierał obrazek inline A w kodzie będziemy mieć fajnie zaimportowany i wykorzystany SVG jako komponent