Jackie0
Jackie0

Reputation: 3

Workaround for Safari's lack of support for negative values in SVGs

I'm currently diving into animated SVGs using CSS, and I'm getting ready to say "screw Safari" and just upload a static svg for those users. However, thought I put it to the World before I give up.

Neither element will "flip" when viewed in Safari, but works fine in FF and Chrome. I'm aware that safari doesn't like negative values, but I can't wrap my head around how to revise this code using absolute coordinates instead of relative. Please help!

<?xml version="1.1" encoding="UTF-8"?>
<svg id="logo-layers" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 41 21">
    <defs>
    <style>
    .cls-1 {
                stroke: #4e2164;
        stroke-linecap: round;
        stroke-dasharray: 63;
        animation-name: o-ani;
        animation-duration: 3s;
        animation-timing-function: linear;
        animation-fill-mode: forwards;
      }
.cls-1, .cls-2 {
                fill: none;
                stroke-miterlimit: 10;
      }
.cls-2 {
                stroke: #CCCC00;
        stroke-linecap: round;
        stroke-dasharray: 47;
        animation-name: j-ani;
        animation-duration: 3s;
        animation-timing-function: linear;
        animation-fill-mode: forwards;
      }
@keyframes o-ani {
            0%{
                stroke-dashoffset: 63;
            }
            20%{
                stroke-dashoffset: 0;
            }
            21%{
                d: path("M10.5,0.5c5.523,0,10,4.477,10,10s-4.477,10-10,10s-10-4.477-10-10S4.977,0.5,10.5,0.5z");
            }
            41%{
                d: path("M30.5,0.5c-5.523,0-10,4.477-10,10s4.477,10,10,10s10-4.477,10-10S36.023,0.5,30.5,0.5z");
            }
            100%{
                d: path("M30.5,0.5c-5.523,0-10,4.477-10,10s4.477,10,10,10s10-4.477,10-10S36.023,0.5,30.5,0.5z");
            }
        }   
@keyframes j-ani {
            0%{
                opacity: 0;
            }
            40%{
                opacity: 0;
            }
            41%{
                opacity: 100;
            }
            42%{
                stroke-dashoffset: 47;
            }
            62%{
                stroke-dashoffset: 0;
            }
            63%{
                d: path("M30.5,0.5c-5.523,0-10,4.477-10,10s4.477,10,10,10,10-4.477,10-10");
            }
            83%{
                d: path("M10.5,0.5c5.523,0,10,4.477,10,10s-4.477,10-10,10S0.5,16.023,0.5,10.5");
            }
            100%{
                d: path("M10.5,0.5c5.523,0,10,4.477,10,10s-4.477,10-10,10S0.5,16.023,0.5,10.5");
            }
        }
    </style>
  </defs>
<path id="o-letter" class="cls-1" d="M10.5,.5c5.523,0,10,4.477,10,10s-4.477,10-10,10S.5,16.023,.5,10.5,4.977,.5,10.5,.5Z"/>
  <path id="j-letter" class="cls-2" d="M30.5,.5c-5.523,0-10,4.477-10,10s4.477,10,10,10,10-4.477,10-10"/>
</svg>

Upvotes: 0

Views: 60

Answers (1)

herrstrietzel
herrstrietzel

Reputation: 17307

As commented, you can replace the d path animation with a simple scale() transformation to flip/mirror the paths at certain keyframes:

<svg id="logo-layers" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 41 21">
  <defs>
    <style>
      .cls-1 {
        stroke: #4e2164;
        stroke-linecap: round;
        stroke-dasharray: 63;
        animation-name: o-ani;
        animation-duration: 3s;
        animation-timing-function: linear;
        animation-fill-mode: forwards;
      }

      .cls-1,
      .cls-2 {
        fill: none;
        stroke-miterlimit: 10;
        transform-origin: center;
      }

      .cls-2 {
        stroke: #cccc00;
        stroke-linecap: round;
        stroke-dasharray: 47;
        animation-name: j-ani;
        animation-duration: 3s;
        animation-timing-function: linear;
        animation-fill-mode: forwards;
      }

      @keyframes o-ani {
        0% {
          stroke-dashoffset: 63;
        }

        20% {
          stroke-dashoffset: 0;
        }

        21% {
          transform: scale(1, 1);
        }

        41%,
        100% {
          transform: scale(-1, 1);
        }
      }

      @keyframes j-ani {
        0% {
          opacity: 0;
        }

        40% {
          opacity: 0;
        }

        41% {
          opacity: 100;
        }

        42% {
          stroke-dashoffset: 47;
        }

        62% {
          stroke-dashoffset: 0;
        }

        63% {
          transform: scale(1, 1);
        }

        83%,
        100% {
          transform: scale(-1, 1);
        }
      }
    </style>
  </defs>
  <path id="o-letter" class="cls-1" d="M10.5,.5c5.523,0,10,4.477,10,10s-4.477,10-10,10S.5,16.023,.5,10.5,4.977,.5,10.5,.5Z" />
  <path id="j-letter" class="cls-2" d="M30.5,.5c-5.523,0-10,4.477-10,10s4.477,10,10,10,10-4.477,10-10" />
</svg>

It's crucial to define a transform-origin: center (or define the center coordinates explicitely like transform-origin: 20.5px 10.5px) otherwise the browser assumes. We can replace the d transformation since both states don't really change the path geometry.

Unfortunately, safari/webkit still doesn't support d animations/transitions while other engines support it flawlessly for may years. See caniuse stats.

Worth noting, SMIL animations are supported by all browsers but you may find a lot of comments in older SO posts they are removed from Chromium. Fortunately, Chromium changed their mind.

Upvotes: 0

Related Questions