Я не могу сделать анимацию css svg emoji похожей на реакции Pinterest

#css #svg #css-animations

#css #svg #css-анимация

Вопрос:

Я не могу сделать анимацию CSS с моим SVG-спрайтом, похожим на Pinterest. Спрайт состоит из 90 кадров, но я не могу заставить его работать

Эмодзи реакций Pinterest Эмодзи реакций Pinterest

Просмотр 90 кадров Pinterest Sprite в формате Svg

Мой код:

 .emoji{
  width: 110px;
  height: 110px;
  background-image : url(https://s.pinimg.com/webapp/style/images/wow-0a7ea725.svg);
  animation: moveX 1s steps(90) infinite;
}

@keyframes moveX{
  from{background-position-x:0px;}
  to{background-position-x:-500px;}
} 
 <div class="emoji"></div> 

Мой JSFiddle:

https://jsfiddle.net/u81xkcon/

Комментарии:

1. Единственная проблема с вашим кодом заключалась в том, что вы неправильно установили ширину изображения… если бы вы вместо этого пошли с to{background-position-x:-100%;} этим, это сработало бы как шарм;-)

Ответ №1:

Вот так

 .emoji {
  width: 110px;
  display: inline-flex;
  background-image: url(https://s.pinimg.com/webapp/style/images/wow-0a7ea725.svg);
  background-size: auto 100%;
  animation: moveX 1s steps(90) infinite;
}

.emoji::before {
  content: "";
  padding-top: 100%; /* keep the square ratio */
}

@keyframes moveX {
  to {
    background-position: right; /* you only need to move to right */
  }
} 
 <div class="emoji"></div>
<div class="emoji" style="width:50px"></div> 

Комментарии:

1. Отличный друг, спасибо. но у меня есть вопрос… почему анимация вибрирует по оси X?

2. @DavidPumaRios либо спрайты не идеально выровнены, либо, возможно, проблема с отображением в браузере

3. @DavidPumaRios Я обновил код, чтобы избавиться от него. Используйте 100% по оси Y, чтобы не было места для прыжков

4. ::before для чего? Я не вижу в этом никакой пользы … в противном случае, отличный ответ!

5. @Christoph чтобы сохранить квадратное соотношение, обратите внимание, как я использовал два div с разной шириной, и я никогда не указывал высоту, потому что это сделает псевдоэлемент.

Ответ №2:

Если вы возьмете у Темани его отличный ответ, добавьте современный стандартный веб-компонент W3C, который использует буквальный синтаксический анализ шаблонов для создания клиентской части SVG sprite в ShadowDOM

(и сделайте несколько улучшенных вычислений анимации в <template> )

Вы сохраняете загрузку SVG-файла размером 65 КБ и получаете:

 <svg-spriter w=100 h=100 s=40 width="130px">
  <template>
    <g id="sprite${n}_${s}" transform="translate(${n*w})">
      <rect x='5' y='5' width='90' height='90' rx='20' fill='#ffad65'></rect>
      <circle cx='30' cy='30' r='${12 (n<10?-n:n)*.1}'></circle>
      <circle cx='80' cy='30' r='${12 (n<10?n:-n)*.1}'></circle>
      <ellipse cx='60' cy='70' rx="${10 (n<20?n*0.5:((20-n)*-0.5))}" ry="5"></ellipse>
    </g>
  </template>
</svg-spriter>
<script>
  customElements.define("svg-spriter", class extends HTMLElement {
    constructor() { super().attachShadow({mode: "open"}) }
    connectedCallback() {
      const parsed = (template, vars = {}) => new Function('vars', [
        'let f = ( '   Object.keys(vars).join(', ')   ' ) =>',
        '`'   template   '`','return f(...Object.values(vars))'
      ].join('n'))(vars);
      setTimeout(() => { // wait till <template> is parsed by the Browser
        let attr = (x) => this.getAttribute(x);
        let [w, h, s] = ["w", "h", "s"].map(a => ~~attr(a));
        let width = attr("width");
        let frame = this.querySelector("template").innerHTML;
        let svg =
          (`data:image/svg xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${s*w} ${h}'>`  
            Array(s).fill().map((s, n) => parsed(frame, {n,w,h,s})).join("")   "</svg>").replace(/#/g, "#").replace(/n/g, "").replace(/</g, "<").replace(/>/g, ">").replaceAll('"', "'");
        let html = `<style>div{width:${width};display:inline-flex;background-image: url("${svg}");background-size: auto ${width};animation:moveX 1s steps(${s-1}) infinite}div::before{content:"";padding-top:100%;}@keyframes moveX{to{background-position:right}}</style><div></div>`;
        html  = `<br>Sprite as IMG:<br><img src="${svg}">`;
        this.shadowRoot.innerHTML = html;
      })
    }
  });
</script>