如何使用CSS实现一个“我裂开”动画表情

事情的起因也是偶然在群里看到有人问如何使用CSS实现一个图片锯齿状裂开然后往两边倒的动画效果,也就是下面描述的效果

想了一下,感觉也不难,就尝试一下实现这个效果,主要思路还是 伪元素+clip-path+animation,这是最后实现的效果,codepen预览

实现思路

设置左右半边

首先是实现一左一右两个半边,使用伪元素+clip-path来实现

css 复制代码
&:after,
&:before {
	content: "🙂";
	font-size: 200px;
	display: flex;
	justify-content: center;
	position: absolute;
	inset: 0;
	transform-origin: bottom center;
}

&:after {
	clip-path: polygon(0 0, 50% 0, 50% 100%, 0% 100%);
}
&:before {
	clip-path: polygon(50% 0, 50% 100%, 100% 100%, 100% 0);
}

增加裂纹

然后修改clip-path来设置左右半边的裂纹,需要注意的是左右裂纹必须吻合,所以可以考虑提取成css变量公用

css 复制代码
--crack: 40% 10%, 60% 20%, 30% 30%, 65% 40%, 40% 50%, 60% 70%, 40% 70%, 60% 80%,
	40% 90%;

&:after,
&:before {
	content: "🙂";
	font-size: 200px;
	display: flex;
	justify-content: center;
	position: absolute;
	inset: 0;
	transform-origin: bottom center;
}

&:after {
	clip-path: polygon(0 0, 50% 0, var(--crack), 50% 100%, 0% 100%);
}
&:before {
	clip-path: polygon(50% 0, var(--crack), 50% 100%, 100% 100%, 100% 0);
}

将裂纹位置的变量插入合适的位置即可实现完全一致的裂纹边缘,下图中已经可以隐约看见表情中的裂纹

设置裂开动画

为左右半边设置动画,动画的原点都为底部中间,但是左右旋转方向不同,旋转方向一开始设置的90deg,但是实际效果发现90度在动画完成后锯齿边会凸出来,所以要设置为比90大的角度。 需要设置animation-fill-mode: forwards来保证动画完成后图片保持状态,否则完成后会恢复第一帧的状态

css 复制代码
&:after {
	clip-path: polygon(0 0, 50% 0, var(--crack), 50% 100%, 0% 100%);
	animation: rotate-left 2s linear;
	animation-delay: 1s;
	animation-fill-mode: forwards;
}
&:before {
	clip-path: polygon(50% 0, var(--crack), 50% 100%, 100% 100%, 100% 0);
	animation: rotate-right 2s linear;
	animation-delay: 1s;
	animation-fill-mode: forwards;
}

@keyframes rotate-left {
	from {
		transform: rotate(0deg);
	}
	to {
		transform: rotate(-110deg);
	}
}

@keyframes rotate-right {
	from {
		transform: rotate(0deg);
	}
	to {
		transform: rotate(110deg);
	}
}

完整代码

css 复制代码
div {
	position: relative;
	width: 200px;
	height: 200px;
	border: 1px solid;
	overflow: hidden;

	--crack: 40% 10%, 60% 20%, 30% 30%, 65% 40%, 40% 50%, 60% 70%, 40% 70%, 60% 80%,
		40% 90%;

	&:after,
	&:before {
		content: "🙂";
		font-size: 200px;
		display: flex;
		justify-content: center;
		position: absolute;
		inset: 0;
		transform-origin: bottom center;
	}

	&:after {
		clip-path: polygon(0 0, 50% 0, var(--crack), 50% 100%, 0% 100%);
		animation: rotate-left 2s linear;
		animation-delay: 1s;
		animation-fill-mode: forwards;
	}
	&:before {
		clip-path: polygon(50% 0, var(--crack), 50% 100%, 100% 100%, 100% 0);
		animation: rotate-right 2s linear;
		animation-delay: 1s;
		animation-fill-mode: forwards;
	}
}

@keyframes rotate-left {
	from {
		transform: rotate(0deg);
	}
	to {
		transform: rotate(-110deg);
	}
}

@keyframes rotate-right {
	from {
		transform: rotate(0deg);
	}
	to {
		transform: rotate(110deg);
	}
}
相关推荐
小桥风满袖5 小时前
极简三分钟ES6 - ES9中字符串扩展
前端·javascript
小Wang5 小时前
npm私有库创建(docker+verdaccio)
前端·docker·npm
用户73087011793085 小时前
Vue中集成文字转语音:使用Web Speech API实现功能
前端
李重楼5 小时前
前端性能优化之 HTTP/2 多路复用
前端·面试
yanessa_yu5 小时前
全屏滚动网站PC端自适应方案
前端
RoyLin5 小时前
TypeScript设计模式:桥接模式
前端·后端·typescript
火星开发者5 小时前
Vue中实现Word、Excel、PDF预览的详细步骤
前端
brzhang5 小时前
干翻 Docker?WebAssembly 3.0 的野心,远不止浏览器,来一起看看吧
前端·后端·架构
lecepin6 小时前
AI Coding 资讯 2025-09-17
前端·javascript·面试
IT_陈寒6 小时前
React 18实战:7个被低估的Hooks技巧让你的开发效率提升50%
前端·人工智能·后端