Skip to content

Instantly share code, notes, and snippets.

@pierreburel
Created February 17, 2023 04:58
Show Gist options
  • Save pierreburel/b947e1eb6acb4d382e03c026a41cee60 to your computer and use it in GitHub Desktop.
Save pierreburel/b947e1eb6acb4d382e03c026a41cee60 to your computer and use it in GitHub Desktop.
Generated by SassMeister.com.
@use "sass:list";
@use "sass:map";
@use "sass:math";
@use "sass:string";
$mass: 1 !default;
$stiffness: 100 !default;
$damping: 15 !default;
@function spring($t, $mass: $mass, $stiffness: $stiffness, $damping: $damping) {
$w0: math.sqrt($stiffness / $mass);
$zeta: $damping / (2 * math.sqrt($stiffness * $mass));
$wd: if($zeta < 1, $w0 * math.sqrt(1 - $zeta * $zeta), 0);
$a: 1;
$b: if($zeta < 1, $zeta * $w0 / $wd, $w0);
@if $zeta < 1 {
@return 1 - math.pow(math.$e, -$t * $zeta * $w0) * ($a * math.cos($wd * $t) + $b * math.sin($wd * $t));
}
@return 1 - ($a + $b * $t) * math.exp(-$t * $w0);
}
@function lerp($from, $to, $t) {
@return $from * (1 - $t) + $to * $t;
}
@function precision($float, $digits: 1) {
$pow: math.pow(10, $digits);
@return round($float * $pow) / $pow;
}
@function remove-consecutive-values($keyframes) {
$last: ();
$before-last: ();
@each $keyframe, $properties in $keyframes {
@each $property, $value in $properties {
@if map.get($last, $property, value) == $value and map.get($before-last, $property, value) == $value {
$keyframes: map.deep-remove($keyframes, map.get($last, $property, keyframe), $property);
}
$before-last: map.set($before-last, $property, map.get($last, $property));
$last: map.set($last, $property, (keyframe: $keyframe, value: $value));
}
}
@return $keyframes;
}
$transforms: ('translateX', 'translateY', 'translateZ', 'rotate', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'perspective');
@mixin keyframes($name, $properties, $steps: 50, $args...) {
$keyframes: ();
@for $i from 0 through $steps {
$percentage: $i * 100 / $steps + '%';
$keyframe: ();
$transform: '';
@each $property, $values in $properties {
$from: list.nth($values, 1);
$to: list.nth($values, 2);
$value: if($i == 0, $from, if($i == $steps, $to, precision(lerp($from, $to, spring($i / $steps, $args...)))));
@if list.index($transforms, $property) {
$transform: "#{$transform} #{$property}(#{$value})";
} @else {
$keyframe: map.set($keyframe, $property, $value);
}
}
$keyframe: map.set($keyframe, transform, string.slice(string.unquote($transform), 2, -1));
$keyframes: map.set($keyframes, $percentage, $keyframe);
}
@keyframes #{$name} {
@each $keyframe, $properties in remove-consecutive-values($keyframes) {
#{$keyframe} {
@each $property, $value in $properties {
#{$property}: $value;
}
}
}
}
}
$properties: (
opacity: (0, 1),
translateX: (0%, 100%),
rotate: (0deg, 1turn),
scale: (1, 1.5),
);
@include keyframes(test1, $properties, $stiffness: 600);
@include keyframes(test2, $properties, $stiffness: 600);
div {
width: 100px;
height: 100px;
animation-timing-function: linear;
animation-duration: 1s;
animation-fill-mode: both;
opacity: .5;
position: absolute;
inset: 0;
margin: auto;
&:first-child {
background: red;
:hover & {
animation-name: test1;
}
}
&:last-child {
background: blue;
:hover & {
animation-name: test2;
}
}
}
<div></div>
<div></div>
@keyframes test1 {
0% {
opacity: 0;
transform: translateX(0%) rotate(0deg) scale(1);
}
2% {
opacity: 0.1;
transform: translateX(10.7%) rotate(38.4deg) scale(1.1);
}
4% {
opacity: 0.4;
transform: translateX(36.7%) rotate(132.2deg) scale(1.2);
}
6% {
opacity: 0.7;
transform: translateX(68.9%) rotate(248deg) scale(1.3);
}
8% {
opacity: 1;
transform: translateX(99%) rotate(356.6deg) scale(1.5);
}
10% {
opacity: 1.2;
transform: translateX(121.6%) rotate(437.7deg) scale(1.6);
}
12% {
opacity: 1.3;
transform: translateX(133.9%) rotate(482deg) scale(1.7);
}
14% {
opacity: 1.4;
transform: translateX(136.1%) rotate(490deg) scale(1.7);
}
16% {
opacity: 1.3;
transform: translateX(130.4%) rotate(469.5deg) scale(1.7);
}
18% {
opacity: 1.2;
transform: translateX(120%) rotate(432.1deg) scale(1.6);
}
20% {
opacity: 1.1;
transform: translateX(108.3%) rotate(389.7deg) scale(1.5);
}
22% {
opacity: 1;
transform: translateX(97.9%) rotate(352.3deg) scale(1.5);
}
24% {
opacity: 0.9;
transform: translateX(90.6%) rotate(326.1deg) scale(1.5);
}
26% {
transform: translateX(87.1%) rotate(313.6deg) scale(1.4);
}
28% {
transform: translateX(87.2%) rotate(313.8deg) scale(1.4);
}
30% {
transform: translateX(89.8%) rotate(323.3deg) scale(1.4);
}
32% {
opacity: 0.9;
transform: translateX(93.8%) rotate(337.8deg) scale(1.5);
}
34% {
opacity: 1;
transform: translateX(98.1%) rotate(353.1deg) scale(1.5);
}
36% {
transform: translateX(101.6%) rotate(365.8deg) scale(1.5);
}
38% {
transform: translateX(103.9%) rotate(374deg) scale(1.5);
}
40% {
transform: translateX(104.8%) rotate(377.3deg) scale(1.5);
}
42% {
transform: translateX(104.5%) rotate(376.2deg) scale(1.5);
}
44% {
transform: translateX(103.4%) rotate(372.1deg) scale(1.5);
}
46% {
transform: translateX(101.8%) rotate(366.6deg) scale(1.5);
}
48% {
transform: translateX(100.3%) rotate(361.2deg) scale(1.5);
}
50% {
transform: translateX(99.1%) rotate(356.9deg) scale(1.5);
}
52% {
transform: translateX(98.4%) rotate(354.4deg) scale(1.5);
}
54% {
transform: translateX(98.2%) rotate(353.7deg) scale(1.5);
}
56% {
transform: translateX(98.5%) rotate(354.4deg) scale(1.5);
}
58% {
transform: translateX(98.9%) rotate(356.1deg) scale(1.5);
}
60% {
transform: translateX(99.5%) rotate(358.1deg) scale(1.5);
}
62% {
transform: translateX(100%) rotate(360deg) scale(1.5);
}
64% {
transform: translateX(100.4%) rotate(361.4deg) scale(1.5);
}
66% {
transform: translateX(100.6%) rotate(362.2deg) scale(1.5);
}
68% {
transform: translateX(100.6%) rotate(362.3deg) scale(1.5);
}
70% {
transform: translateX(100.5%) rotate(361.9deg) scale(1.5);
}
72% {
transform: translateX(100.3%) rotate(361.2deg) scale(1.5);
}
74% {
transform: translateX(100.1%) rotate(360.5deg) scale(1.5);
}
76% {
transform: translateX(100%) rotate(359.8deg) scale(1.5);
}
78% {
transform: translateX(99.8%) rotate(359.4deg) scale(1.5);
}
80% {
transform: translateX(99.8%) rotate(359.2deg) scale(1.5);
}
82% {
transform: translateX(99.8%) rotate(359.2deg) scale(1.5);
}
84% {
transform: translateX(99.8%) rotate(359.4deg) scale(1.5);
}
86% {
transform: translateX(99.9%) rotate(359.6deg) scale(1.5);
}
88% {
transform: translateX(100%) rotate(359.9deg) scale(1.5);
}
90% {
transform: translateX(100%) rotate(360.1deg) scale(1.5);
}
92% {
transform: translateX(100.1%) rotate(360.3deg) scale(1.5);
}
96% {
transform: translateX(100.1%) rotate(360.3deg) scale(1.5);
}
98% {
transform: translateX(100.1%) rotate(360.2deg) scale(1.5);
}
100% {
opacity: 1;
transform: translateX(100%) rotate(1turn) scale(1.5);
}
}
@keyframes test2 {
0% {
opacity: 0;
transform: translateX(0%) rotate(0deg) scale(1);
}
2% {
opacity: 0.1;
transform: translateX(10.7%) rotate(38.4deg) scale(1.1);
}
4% {
opacity: 0.4;
transform: translateX(36.7%) rotate(132.2deg) scale(1.2);
}
6% {
opacity: 0.7;
transform: translateX(68.9%) rotate(248deg) scale(1.3);
}
8% {
opacity: 1;
transform: translateX(99%) rotate(356.6deg) scale(1.5);
}
10% {
opacity: 1.2;
transform: translateX(121.6%) rotate(437.7deg) scale(1.6);
}
12% {
opacity: 1.3;
transform: translateX(133.9%) rotate(482deg) scale(1.7);
}
14% {
opacity: 1.4;
transform: translateX(136.1%) rotate(490deg) scale(1.7);
}
16% {
opacity: 1.3;
transform: translateX(130.4%) rotate(469.5deg) scale(1.7);
}
18% {
opacity: 1.2;
transform: translateX(120%) rotate(432.1deg) scale(1.6);
}
20% {
opacity: 1.1;
transform: translateX(108.3%) rotate(389.7deg) scale(1.5);
}
22% {
opacity: 1;
transform: translateX(97.9%) rotate(352.3deg) scale(1.5);
}
24% {
opacity: 0.9;
transform: translateX(90.6%) rotate(326.1deg) scale(1.5);
}
26% {
transform: translateX(87.1%) rotate(313.6deg) scale(1.4);
}
28% {
transform: translateX(87.2%) rotate(313.8deg) scale(1.4);
}
30% {
transform: translateX(89.8%) rotate(323.3deg) scale(1.4);
}
32% {
opacity: 0.9;
transform: translateX(93.8%) rotate(337.8deg) scale(1.5);
}
34% {
opacity: 1;
transform: translateX(98.1%) rotate(353.1deg) scale(1.5);
}
36% {
transform: translateX(101.6%) rotate(365.8deg) scale(1.5);
}
38% {
transform: translateX(103.9%) rotate(374deg) scale(1.5);
}
40% {
transform: translateX(104.8%) rotate(377.3deg) scale(1.5);
}
42% {
transform: translateX(104.5%) rotate(376.2deg) scale(1.5);
}
44% {
transform: translateX(103.4%) rotate(372.1deg) scale(1.5);
}
46% {
transform: translateX(101.8%) rotate(366.6deg) scale(1.5);
}
48% {
transform: translateX(100.3%) rotate(361.2deg) scale(1.5);
}
50% {
transform: translateX(99.1%) rotate(356.9deg) scale(1.5);
}
52% {
transform: translateX(98.4%) rotate(354.4deg) scale(1.5);
}
54% {
transform: translateX(98.2%) rotate(353.7deg) scale(1.5);
}
56% {
transform: translateX(98.5%) rotate(354.4deg) scale(1.5);
}
58% {
transform: translateX(98.9%) rotate(356.1deg) scale(1.5);
}
60% {
transform: translateX(99.5%) rotate(358.1deg) scale(1.5);
}
62% {
transform: translateX(100%) rotate(360deg) scale(1.5);
}
64% {
transform: translateX(100.4%) rotate(361.4deg) scale(1.5);
}
66% {
transform: translateX(100.6%) rotate(362.2deg) scale(1.5);
}
68% {
transform: translateX(100.6%) rotate(362.3deg) scale(1.5);
}
70% {
transform: translateX(100.5%) rotate(361.9deg) scale(1.5);
}
72% {
transform: translateX(100.3%) rotate(361.2deg) scale(1.5);
}
74% {
transform: translateX(100.1%) rotate(360.5deg) scale(1.5);
}
76% {
transform: translateX(100%) rotate(359.8deg) scale(1.5);
}
78% {
transform: translateX(99.8%) rotate(359.4deg) scale(1.5);
}
80% {
transform: translateX(99.8%) rotate(359.2deg) scale(1.5);
}
82% {
transform: translateX(99.8%) rotate(359.2deg) scale(1.5);
}
84% {
transform: translateX(99.8%) rotate(359.4deg) scale(1.5);
}
86% {
transform: translateX(99.9%) rotate(359.6deg) scale(1.5);
}
88% {
transform: translateX(100%) rotate(359.9deg) scale(1.5);
}
90% {
transform: translateX(100%) rotate(360.1deg) scale(1.5);
}
92% {
transform: translateX(100.1%) rotate(360.3deg) scale(1.5);
}
96% {
transform: translateX(100.1%) rotate(360.3deg) scale(1.5);
}
98% {
transform: translateX(100.1%) rotate(360.2deg) scale(1.5);
}
100% {
opacity: 1;
transform: translateX(100%) rotate(1turn) scale(1.5);
}
}
div {
width: 100px;
height: 100px;
animation-timing-function: linear;
animation-duration: 1s;
animation-fill-mode: both;
opacity: 0.5;
position: absolute;
inset: 0;
margin: auto;
}
div:first-child {
background: red;
}
:hover div:first-child {
animation-name: test1;
}
div:last-child {
background: blue;
}
:hover div:last-child {
animation-name: test2;
}
{
"sass": {
"compiler": "dart-sass/1.32.12",
"extensions": {},
"syntax": "SCSS",
"outputStyle": "expanded"
},
"autoprefixer": false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment