JSFiddle - React, Tailwind, and code Playground
by dart_eugenius
HTML
<div id="elem">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="172.233 108.423 154.767 296.165"
enable-background="new 172.233 108.423 154.767 296.165">
<g transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)">
<path d="M2222.002,3910c-105-15-223.003-47.998-301.001-85c-86.001-41.001-192.002-115-188.003-131.001
c1.001-6.997,72.002-87.998,156.001-181.001l155-170l52.002,42.002c78.999,65,162.998,90,298.999,90
c100,0,115.996-2.998,172.998-28.999c105-48.003,152.002-123.999,137.998-221.001C2690,3122.001,2602.002,3067.998,2300,2975
c-235-72.002-341.001-125-430-215c-113.999-115-157.002-242.002-146.001-430c11.001-197.998,61.001-317.002,190-445
c153.999-152.998,358.999-225,638.999-225c266.006,0,491.006,77.998,674.004,232.998l42.998,35l-167.002,185l-167.998,185
l-52.002-52.002c-102.998-103.994-227.998-150-386.997-143.994c-91.001,2.998-108.999,7.002-170,37.002
c-107.002,51.992-152.002,135-126.001,230c27.002,100,117.998,156.997,405,250.996c225,73.999,345,132.998,427.002,207.998
c113.994,106.001,155.996,195,165,352.002c25,422.002-292.998,721.001-782.002,735C2343.999,3917.001,2257.002,3915,2222.002,3910z
"/>
<path d="M2390,1465c-25-7.998-65-30.996-88.999-52.002c-142.002-120.996-113.999-347.002,53.999-435.996
c57.002-31.006,172.998-30,230.996,0c96.006,50.996,145,132.002,145,237.002c0,76.992-18.994,127.998-68.994,178.994
C2589.004,1469.004,2486.001,1495.996,2390,1465z"/>
</g>
</svg>
</div>
CSS
#elem {
width: 80px;
margin: 100px auto 0;
}
#elem svg{
width: 100%;
}
@-webkit-keyframes flipLeft {
0% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 45deg);
transform: perspective(400px) rotate3d(0, 1, 0, 45deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
40% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
60% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
}
80% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
}
100% {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
}
@keyframes flipLeft {
0% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 45deg);
transform: perspective(400px) rotate3d(0, 1, 0, 45deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
40% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
60% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
}
80% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
}
100% {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
}
@-webkit-keyframes flipRight {
0% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -45deg);
transform: perspective(400px) rotate3d(0, 1, 0, -45deg);
...
JavaScript
var $elem = $('#elem'),
rect = $elem[0].getBoundingClientRect()
timerId = null;
timeStamp = 0, x = 0,
blocked = false,
transform = 'rotateY({d}deg)';
run = function(velocity){
var abs = Math.abs(velocity)
if(abs < .1) return;
if(abs < 1) {
if(velocity > 0) {
$elem.addClass('flipLeft');
} else {
$elem.addClass('flipRight');
}
setTimeout(function(){
clearTimeout(timerId);
$elem.removeClass('flipLeft flipRight');
}, 1200); // animations duration + 200
} else {
$elem.addClass('rotate');
$elem.css({
'-webkit-transform': transform.replace('{d}', parseInt(velocity,10) * 360),
'transform': transform.replace('{d}', parseInt(velocity,10) * 360)
});
if(abs > 2) {
$elem.css({
'-webkit-transition-duration': abs *.66 + 's',
'transition-duration': abs *.66 + 's',
});
}
setTimeout(function(){
clearTimeout(timerId);
$elem.removeClass('rotate');
$elem.removeAttr('style');
}, abs > 2 ? abs *.66 * 1000 + 200 : 1200);
}
}
$elem.on('mouseenter',function (e) {
x = e.clientX - rect.left;
timeStamp = e.timeStamp || Date.now();
})
$elem.on('mousemove',function (e) {
timeStamp = timeStamp || Date.now();
time = e.timeStamp - timeStamp;
distance = e.clientX - rect.left - x;
clearTimeout(timerId);
timerId = setTimeout(function(){
run(distance/time);
timeStamp = 0;
}, 200);
});
$elem.on('mouseleave',function (e) {
var distance = e.clientX - rect.left - x;
var time = e.timeStamp? e.timeStamp - timeStamp : Date.now() - timeStamp;
run(distance/time);
clearTimeout(timerId);
timeStamp = 0;
x = 0;
});