问题
I can't make a CSS animation with my SVG sprite similar to Pinterest. The sprite is 90 frames, but I can't get it to work
Pinterest Reactions Emojis
View Pinterest Sprite 90 frames in Svg
My code:
.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>
My JSFiddle:
https://jsfiddle.net/u81xkcon/
回答1:
Here you go
.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>
回答2:
If you take Temani his great answer, add a modern W3C standard Web Component that uses Template Literal parsing to create the SVG sprite Client Side in a shadowDOM
(and do some better animation calculations in the <template>
)
You save downloading a 65KB SVG file, and get:
<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, "%23").replace(/\n/g, "").replace(/</g, "%3C").replace(/>/g, "%3E").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>
来源:https://stackoverflow.com/questions/65516030/i-cant-make-css-svg-animation-emoji-similar-to-pinterest-reactions