css单标签实现转转logo

转转品牌升级后更新了全新的Logo,今天我们用纯CSS来实现转转的新Logo,为了有一定的挑战性,这里我们只使用一个标签实现,将最大化的使用CSS能力完成Logo的绘制与动画效果。

新logo保留了原本logo里转转熊的轮廓,两个熊耳是两个卫星围绕熊头旋转,是"循环"的意思。中间倾斜的转转首字母"Z",既像二手质检的印章,又像N------NEW的首字母,代表着全新的二手生活方式。

以上是我们要还原的Logo效果动图,现阶段使用方式主要是gif和lottie SVG两种方式。因为我们的目的是使用单标签实现所有的功能点,对于一些细节部分有所取舍,并不是百分百还原,也并不代表使用CSS的成本和效果是最好的,仅表达CSS的强大能力。接下来分析我们要核心实现的功能点:

  • 开始动画时中心的大圆以及2个围绕的小圆都有放大的效果
  • 动画开始后2个小圆围绕中心的椭圆旋转
  • 字母 Z 由大变小覆盖在中心的椭圆
  • 字母 Z 出现时中心的椭圆由红色边框圆变成实心红色圆
  • 仔细观察这个字母 Z 并不是普通的字符

基于上述分析接下来开始核心的代码拆解实现,在开始前先定义一些变量方便后续使用:

css 复制代码
:root {
  /* 主题色 */
  --mainColor: #ff483c;
  /* 字体颜色 */
  --fontColor: #fff;
  /* 字体宽度 */
  --zWidth: 260px;
  /* 中心椭圆宽高比 */
  --parentScaleY: 0.9;
  /* 子元素抵消比例 */
  --childScaleY: calc(1 / var(--parentScaleY))
}

2个小圆旋转动画

如果是围绕一个正圆的旋转那么实现就简单很多了,但是这里是一个椭圆,纯CSS应该怎么做呢?根据小编目前的了解大概有以下几种方式都可以实现,但是对应的效果有所区别:

  • 使用 transform-style: preserve-3d;开启3D模式,但是对应的小圆在旋转角度存在视角消失的情况,需要额外处理
  • 使用 cubic-bezier 贝塞尔曲线执行动画可以达到椭圆曲线的效果,但是存在动画开始停止不可控的情况
  • 使用 rotate 0-360deg旋转,对应子元素需要设置反向旋转来抵消父级的旋转带来的影响

对比各种情况最终使用第三个方案即可满足条件且实现成本较低,首先画出一个椭圆的边框效果,设置scaleYborder-radius将一个正方形变成椭圆形,核心代码如下:

css 复制代码
  width: 570px;
  aspect-ratio: 1;
  border-radius: 50%;
  border: 10px solid var(--mainColor);
  transform: scaleY(var(--parentScaleY));

然后给这个大圆添加旋转的动画,将整体旋转360度,这时还没有添加其他的元素,所以界面没有变化。

css 复制代码
@keyframes circle {
  0% {
    transform: scaleY(var(--parentScaleY)) rotate(0);
  }
  100% {
    transform: scaleY(var(--parentScaleY)) rotate(360deg);
  }
}

设置大圆的动画执行相关参数。

css 复制代码
animation: circle 1s 1 cubic-bezier(.5,.08,.52,.93) forwards;

边框上面的两个圈基于伪元素实现,绘制一个圆并使用定位将小圆定位于大圆的顶部两端。然后设置动画,这里需要注意的是需要设置反向旋转来抵消父级的旋转。

css 复制代码
@keyframes mini-circle {
  0%{
    transform: rotate(0deg) scaleY(var(--childScaleY));
  }
 100%{
    transform: rotate(-360deg) scaleY(var(--childScaleY));
  }
}

这里为了方便查看将椭圆的参数调大进行对比,可以看到设置抵消后的区别一个圆被压缩了另一个保持了正常的圆形:

未设置抵消

已设置抵消

这里为了更好的利用元素的使用,这里将两个圆的绘制进一步优化到一个伪元素中,核心使用径向渐变背景实现,在同一个 background 中绘制两个纯色圆形,两个圆除了绘制的位置不同其他都是一样。代码如下:

css 复制代码
background: 
  radial-gradient(circle 65px at 31% 24.5%,var(--mainColor) 0% 100%, transparent),
  radial-gradient(circle 65px at 72% 24.5%, var(--mainColor) 0% 100%, transparent);

到此这部分的内容基本功能完成,实际效果如下:

Z 字母

接下来使用另一个伪元素实现 Z 字母的效果,仔细观察 Z 字母的两个拐角都是锐角效果,并不是日常字母有拐角的效果。

基于当前的样式我们可以用3段矩形拼接完成效果,上下各一段,中间一段增加旋转角度,但是只用一个伪元素如何绘制三个矩形呢,还是用到CSS渐变,这次需要用到linear-gradient线性渐变,顶部和底部正常从上往下绘制,中间的部分需要绘制线条的旋转角度,除开需要显示的颜色其他部分用#0000透明色,为了方便看效果对三个矩形更换了不同的颜色,代码如下:

css 复制代码
background: 
  linear-gradient(#f00 25%, #0000 25%),
  linear-gradient(#0000 75%, #29eb9a 25%),
  linear-gradient(124deg, #0000 40%, #000 40% 60%, #0000 60%);

绘制的效果如下:

可以看到目前的效果还不能满足需求,两端都出现了多余的部分,需要进一步优化将其隐藏。这时候需要用到background-sizebackground-position,通过background-size设置绘制内容的大小,通过设置background-position设置绘制内容的起点位置,因为设置了一定的空隙部分需要增加no-repeat不重复,增加以下代码:

css 复制代码
background-size: 80% var(--w), 80% var(--w), 100% 100%;
background-position: 0 0, 100% 0;
background-repeat: no-repeat;

此时基本符合预期的效果,但实际设计图左下角的锐角部分有超出正常矩形一部分。

所以需要对刚刚设置的sizeposition部分改进,将第一个矩形左侧空出16px:

css 复制代码
background-size: 74% var(--w), 80% var(--w), 100% 100%;
background-position: 16px 0, 100% 0;

因为空出了左侧一部分距离,导致整个内容不再是一个正方形,所以需要设置 scaleX 还原宽度将图像还原到正方形。

对于刚刚设置的background相关属性可以在代码层进一步优化,使用简写将代码合并到一行:

css 复制代码
background:
  linear-gradient(var(--fontColor) 25%, #0000 25%) 16px 0 / 74% var(--zWidth) no-repeat,
  linear-gradient(#0000 75%, var(--fontColor) 25%) 100% 0 / 80% var(--zWidth) no-repeat,
  linear-gradient(124deg, #0000 40%, var(--fontColor) 40% 60%, #0000 60%) 0 0 / 100% 100% no-repeat;

然后继续给这个 Z 添加动画效果,默认设置 opacity: 0 隐藏,因为 Z 是小圆动画执行结束才出现的,所以还需增加动画的延迟执行时间,增加动画相关代码:

css 复制代码
animation: z 0.3s 1s 1 ease-in-out forwards;
opacity: 0;

设置动画将内容从1.5倍缩小到正常并设置旋转角度,返抵消以及平移到Logo正中心。这里因为初始增加了1.5的放大所以设置返抵消相关参数有所不同,在设置scaleY的同时还设置了skew进一步还原尺寸。

css 复制代码
@keyframes z {
  0% {
    transform: rotate(-45deg) scale(1.5) translate(0, -50%) skew(-13deg, 8deg);
    opacity: 1;
  }
  100% {
    transform: rotate(-42deg) scaleY(var(--childScaleY)) translate(-4%, -64%) skew(-13deg, 8deg);
    opacity: 1;
  }
}

完成后的 Z 字母动画效果:

其他细节

开始动画时中心的椭圆以及2个围绕的小圆都有放大的效果,所以需要对前面动画关键帧的定义继续完善。

小圆部分执行动画的前10%也增加scale(0.5)

css 复制代码
@keyframes mini-circle {
  0%{
    transform: rotate(0) scale(0.5);
  }
  10%{
    transform: rotate(0) scaleY(var(--childScaleY));
  }
}

大圆执行动画的前10%部分增加scale(0.8)。大圆部分还有一个效果是字母 Z 出现的时候中心的椭圆由边框圆变成实心圆,所以是在动画结束前增加对背景色的变化,代码如下:

css 复制代码
@keyframes circle {
  0% {
    transform: scale(0.8) rotate(0);
  }
  10% {
    transform: scaleY(var(--parentScaleY)) rotate(0);
  }
  80% {
    background-color: var(--fontColor);
  }
  100% {
    background-color: var(--mainColor);
    transform: scaleY(var(--parentScaleY)) rotate(360deg);
  }
}

最后

到此我们整个代码实现过程就结束了,基于一个标签实现了转转的Logo的绘制及动画效果。当然这只是对其主要的功能还原,如需完整还原细节还需要进一步优化。

CSS的确是足够强大且对很多复杂的图形效果都能实现,这里我们主要是使用渐变背景实现图案的绘制,除了渐变还可以使用CSS阴影也能达到类似的效果。使用CSS对比使用SVG或GIF在资源体积上有很大的提升,本次实现的Logo使用lottiejson需要100KB左右,使用GIF大约需要27KB左右,但是纯CSS实现仅1KB不到即可完成,但是对于较为复杂的场景对应的代码也提升了不少的复杂度,大家要根据实际的情况使用,感兴趣的同学欢迎留言交流。

> 转转研发中心及业界小伙伴们的技术学习交流平台,定期分享一线的实战经验及业界前沿的技术话题。 > 关注公众号「转转技术」(综合性)、「大转转FE」(专注于FE)、「转转QA」(专注于QA),更多干货实践,欢迎交流分享~

相关推荐
有梦想的刺儿11 分钟前
webWorker基本用法
前端·javascript·vue.js
cy玩具32 分钟前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
qq_390161771 小时前
防抖函数--应用场景及示例
前端·javascript
John.liu_Test2 小时前
js下载excel示例demo
前端·javascript·excel
Yaml42 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事2 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶2 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo2 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v2 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript
知孤云出岫2 小时前
web 渗透学习指南——初学者防入狱篇
前端·网络安全·渗透·web