SOURCE

console 命令行工具 X clear

                    
>
console
const animationDuration = 3;
const animationRepeatDelay = 3;
const totalDuration = animationDuration + animationRepeatDelay;
const mouthDuration = 0.4;
const mouthDelay = 0.4;

const mouthBorderRadius = "0.8rem 0.8rem 10rem 10rem";
const mouthHeight = "13vmin";
const mouthWidth = "95%";

gsap.registerEffect({
	name: "rotate",
	effect: (targets, config) => {
		return gsap.to(targets, {
			duration: animationDuration,
			rotate: 360 * 3,
			repeat: -1,
			repeatDelay: animationRepeatDelay,
			ease: "back.inOut"
		});
	}
});

gsap.effects.rotate(".head");

var mouthTimeline = gsap.timeline();
mouthTimeline.fromTo(
	".face__mouth",
	{
		borderRadius: mouthBorderRadius,
		width: mouthWidth,
		height: mouthHeight
	},
	{
		borderRadius: "50%",
		width: "4vmin",
		height: "4vmin",
		duration: mouthDuration,
		delay: mouthDelay,
		repeat: -1,
		repeatDelay: totalDuration - mouthDuration
	}
);
mouthTimeline.to(".face__mouth", {
	borderRadius: mouthBorderRadius,
	width: mouthWidth,
	height: mouthHeight,
	duration: mouthDuration,
	delay: animationDuration,
	repeat: -1,
	repeatDelay: totalDuration - mouthDuration
});

var tongueTimeline = gsap.timeline();
tongueTimeline.to(".face__tongue", {
	scale: "0",
	duration: mouthDuration,
	delay: mouthDelay,
	repeat: -1,
	repeatDelay: totalDuration - mouthDuration
});
tongueTimeline.to(".face__tongue", {
	scale: "1",
	duration: mouthDuration,
	delay: animationDuration,
	repeat: -1,
	repeatDelay: totalDuration - mouthDuration
});
<div class="head" role="img" aria-label="Spinning smiley face">
	<div class="face">
		<div class="face__eyes">
			<div class="face__eyes--left"></div>
			<div class="face__eyes--right"></div>
		</div>
		<div class="face__mouth">
			<div class="face__tongue"></div>
		</div>
	</div>
</div>
$black: #20184e;
$yellow: #fbd671;

html {
	box-sizing: border-box;
}

*,
*::before,
*::after {
	box-sizing: inherit;
}

body {
	display: flex;
	height: 100vh;
	width: 100vw;
	align-items: center;
	justify-content: center;
	background-color: #feee9d;
}

.head {
	height: 50vmin;
	width: 50vmin;
	background: $yellow;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	padding-top: 4vmin;
}

.face {
	width: 55%;
	height: 70%;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: space-evenly;

	&__eyes {
		display: flex;
		justify-content: space-around;
		width: 100%;

		&--left,
		&--right {
			width: 5vmin;
			height: 8vmin;
			background-color: $black;
			border-radius: 50%;
			border: 1vmin solid $black;
			position: relative;

			&::after {
				content: "";
				position: absolute;
				width: 40%;
				height: 40%;
				top: 5%;
				background-color: $yellow;
				border-radius: 50%;
			}
		}
	}

	&__mouth {
		bottom: 0;
		background-color: $black;
		border: 1vmin solid $black;
		overflow: hidden;
		position: relative;
	}

	&__tongue {
		position: absolute;
		width: 75%;
		height: 70%;
		left: 20%;
		top: 60%;
		background-color: #f15962;
		border-radius: 50%;
	}
}

本项目引用的自定义外部资源