上次发完 不可思议的纯 CSS 导航栏下划线跟随效果 这篇文章之后,很多朋友找我讨论,感叹 CSS 的奇妙。

然后昨天,群里一位朋友问到了一个和这个效果比较类似的效果,问如何

将下面这个动画的下划线效果,从左进入,右边离开修改为从上方进入,下方离开。

描述很难理解,看看原本的效果:

难点所在

第一眼看到这个效果,我的内心毫无波澜。以为只是简单的一个下划线 hover 效果,经过友人提醒,才发现,这个动画效果中,下划线是从一端进入,从另外一端离开的。而且,这个 hover 动画是纯 CSS 实现的。

先不考虑上面说的修改需求,先想一想,如果就是还原上述效果,仅仅使用 CSS,该如何做呢?

还原效果

嗯,正常而言,我们一个 hover 效果,可能就是从哪里来,回哪里去,大部分的应该是这样的:

现在,难点就在于如何在 hover 离开的时候,改变动画行进的方向。

下面我们将一个 hover 动画分解为 3 个部分:

  1. hover 进入状态
  2. hover 停留状态
  3. hover 离开状态

但是,对于一个 hover 效果而言,正常来说,只有初始状态,和hover状态两种。可能我们的代码是这样:

div {
xxxx...
} div:hover {
xxxx...
}

对于一个 hover transition 动画,它应该是从:

  • 正常状态 -> hover状态 -> 正常状态 (三个步骤,两种状态)

所以,必须要有一种方法,能够使得 hover 动画的进入与离开产生两种不一样的效果,实现:

  • 状态1 -> hover状态 -> 状态2 (三个步骤,三种状态)

实现控制动画方向的关键点

所以,这里的关键点就在于(划重点):

使得 hover 动画的进入与离开产生两种不一样的效果 。

接下来,也就是本文的关键所在,使用 transform: scale() 以及 transform-origin 实现这个效果。

transform: scale() 实现线条运动

transform: scale 大家应该都很熟悉了,通俗来说是用于缩放,用官方的话说,就是:

CSS 函数 scale() 用于修改元素的大小。可以通过向量形式定义的缩放值来放大或缩小元素,同时可以在不同的方向设置不同的缩放值。

这里我们使用 transform: scaleX(0) 与 transform: scaleX(1) 来改变线条的显示与隐藏,它的 CSS 代码简单来看,可能是这样:

div {
position: absolute;
width: 200px;
height: 60px;
} div::before {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 200px;
height: 2px;
background: deeppink;
transition: transform .5s;
transform: scaleX(0);
} div:hover::before {
transform: scaleX(1);
}

嗯?为什么是要用 transform: scale() 来实现线条的动画?因为它可以配合 transform-origin 实现动画的不同运动方向:

transform-origin 实现线条运动方向

transform-origin 让我们可以更改一个元素变形(transform)的原点,transform-origin 属性可以使用一个,两个或三个值来指定,其中每个值都表示一个偏移量。 没有明确定义的偏移将重置为其对应的初始值。

本效果最最最重要的地方就在于这里,我们使用 transform-origin 去改变 transform: scale() 的原点实现线条运动的方向。

  1. 我们给线条设置一个默认的 transform-origin 记为状态1
  2. hover 的时候,设置另外一个不同的 transform-origin, 记为状态2

所以,当然我们 hover 的时候,会读取状态2的transform-origin,从该原点开始放大至 scaleX(1),hover 离开的时候,会读取状态1的transform-origin,从scaleX(1)状态缩小至该原点。

嗯,CSS代码大概是这样:

div {
position: absolute;
width: 200px;
height: 60px;
} div::before {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 200px;
height: 2px;
background: deeppink;
transition: transform .5s;
transform: scaleX(0);
transform-origin: 100% 0;
} div:hover::before {
transform: scaleX(1);
transform-origin: 0 0;
}

这里,我们巧妙的通过 hover 状态施加了一层新的 transform-origin ,让动画的进入与离开产生了两种不同的效果,两个不同的方向。

如此一来,也就顺利实现了我们想要的效果,撒花:

注意,这里使用了 transform-origin 去改变 transform: scale() 的原点实现线条运动的方向,而没有借助诸如 position 位移,transform: translate(),或者 margin 等位置属性去改变线条所在的位置。

所以,有趣的是,线条其实没有产生过任何位移,这里其实也是障眼法,让它看上去,它好像在移动。

拓展延伸

嗯,有了上述方法,也就是 transform: scale() 配合 transform-origin ,我们可以开始随意改变动画的初始与结束状态了。把他们运用到其他效果之上,简单的几个示意效果:

值得注意的点

还有几个点是比较有意思的,大家可以尝试尝试,思考思考:

  • 尝试改变两种状态的 transition-timing-function 缓动函数,可以让动画更加流畅具有美感;
  • 注意一下,线条的 transition 设置的是 transition: transform .5s 而不是 transition: all .5s,体验一下两种写法所产生的不同效果。

最后

本方法我个人最早见于 Css菜单悬停效果。如果你有更好的方法欢迎提出共同探讨。

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

好了,本文到此结束,希望对你有帮助 :)

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3ly2fi88twowo

妙用 scale 与 transfrom-origin,精准控制动画方向的更多相关文章

  1. CSS3属性animation-play-state控制动画运行或暂停的技巧

    animation-play-state介绍 animation-play-state 属性规定动画正在运行还是暂停. div{ animation-play-state:paused; -webki ...

  2. Cocos2d-x游戏开发CCBAnimationManager控制动画

    CocosBuilder能方便的编辑各种动画.大部分动画都是以独立片段的形式存在的. 须要由程序来控制何时播放. 管理ccbi文件的动画播放有个专门的类:CCBAnimationManager 大致的 ...

  3. 用css3动画 @keyframes里设置transform:rotate(); 控制动画暂停和运动用属性:animation-play-state:paused暂停,在微信和safari里设置paused无效,在QQ里是正常的

    这几天遇到了两个很奇葩的问题,终于找到原因,趁还记得解决方法,赶紧记下来: 用css3动画 @keyframes里设置transform:rotate(); 控制动画暂停和运动可以用属性:animat ...

  4. WPF控制动画开始、停止、暂停和恢复

    1.闲言 好久也没更新一博客了,自己有点发懒,同时确实这几个月来也有点忙.风机监测软件,项目中,有这样一个小需求:正常风机在旋转的时候,上位机软要做一个风机的图片,让它不停地旋转,一但检测到下面风机停 ...

  5. (转)在Unity3D中控制动画播放

    用Unity3D也算是好久了,但是每次做项目总还是能学到新的东西.这次做一个TPS的项目就遇到了这样一个问题,如何同时在上下半身播放不同的动画?解决方法其实是很简单,但由于对于动画资源的了解不足导致问 ...

  6. vue用js部分控制动画实现

    上次我们提到用vue实现过渡动画,其实只讲了vue动画的一部分,用vue自带的css状态控制动画实现,不带js http://www.cnblogs.com/null11/p/7081506.html ...

  7. js课程 5-14 js如何实现控制动画角色走动

    js课程 5-14 js如何实现控制动画角色走动 一.总结 一句话总结:首先是onkeydown事件,然后是改变元素的left和top属性 1.常用键盘事件有哪些? • onkeydown和 onke ...

  8. css3的transform-origin配合scale,控制动画,实现各种hover效果

    1.底部画线,从左边开始,右边结束 html: <div class="silde-txt">底部划线</div> css: <style>.s ...

  9. JUC——线程同步锁(Condition精准控制)

    在进行锁处理的时候还有一个接口:Condition,这个接口可以由用户来自己进行锁的对象创建. Condition的作用是对锁进行更精确的控制. Condition的await()方法相当于Objec ...

随机推荐

  1. 定位bug的姿势对吗?

    举个例子来说明 WEB页面上数据显示错误,本来应该显示38,  结果显示35,这个时候你怎么去定位这个问题出在哪里? 1.通过fiddler抓包工具(或者其他抓包工具), 分析接口返回的数据是35还是 ...

  2. Java注解(1)-注解基础

    注解(Annotation)是在JAVA5中开始引入的,它为在代码中添加信息提供了一种新的方式.注解在一定程度上把元数据与源代码文件结合在一起,正如许多成熟的框架(Spring)所做的那样.那么,注解 ...

  3. HIVE使用mysql作为外置数据库配置详情

    Hive安装配置(mysql) 安装mysql hadoop$:sudo apt-get update hadoop$:sudo apt-get install mysql-server 启动mysq ...

  4. MySQL之连接查询

    主要是多表查询和连接查询

  5. Beta冲刺-用户测试报告

    一.项目概述 1.1项目名称 高校学生征信系统 1.2项目简介 此项目基于SSH框架,力图为学生提供征信服务和信用相关的借款和申请活动.其中以信用统计和管理为主,信用使用为辅,构建出一个集信用收集和使 ...

  6. 团队作业4——第一次项目冲刺(Alpha版本)11.14

    a. 提供当天站立式会议照片一张 举行站立式会议,讨论项目安排: PM对整个项目的需求进行讲解: 全队对整个项目的细节进行沟通: 对整个项目的开发计划进行分析,分配每天的任务: 统一确定项目的开发环境 ...

  7. 第十一条:谨慎的覆盖clone()方法

    一个类要想实现克隆,需要实现Cloneable接口,表明这个类的对象具有克隆的功能. Cloneable接口是一个mixin接口,它里面并没有任何的抽象方法,类似的接口有Serializable接口, ...

  8. node创建第一个应用

    如果我们使用PHP来编写后端的代码时,需要Apache 或者 Nginx 的HTTP 服务器,并配上 mod_php5 模块和php-cgi. 从这个角度看,整个"接收 HTTP 请求并提供 ...

  9. Ubuntu的软件管理与安装

    感谢燕十八,的Linux的基础进阶视频 来哥:应该是装的wineQQ,它用的12年的国际版,ubuntu的这个版本应该比较好用! [3]apt-get 用Linux apt-get命令的第一步就是引入 ...

  10. Windows中添加自己的程序到开机启动中(添加服务,添加注册表)

    在系统启动的时候启动自己想要启动的程序: 方法一:利用开机启动文件夹 将exe文件或exe文件的快捷方式复制到(启动)文件夹下 以win7为例:开始→所有程序→启动→鼠标右键打开 方法二:添加系统服务 ...