Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

妙用 scale 与 transfrom-origin,精准控制动画方向 #34

Open
chokcoco opened this issue Apr 18, 2018 · 6 comments
Open

妙用 scale 与 transfrom-origin,精准控制动画方向 #34

chokcoco opened this issue Apr 18, 2018 · 6 comments
Labels

Comments

@chokcoco
Copy link
Owner

chokcoco commented Apr 18, 2018

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

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

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

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

tsorigin

难点所在

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

youqu

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

还原效果

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

xxx

CodePen Demo -- 从哪里来,回哪里去

现在,难点就在于如何在 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);
}

scale

CodePen Demo -- transform: scaleX(0) 与 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 的时候,会读取状态2transform-origin,从该原点开始放大至 scaleX(1),hover 离开的时候,会读取状态1transform-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 ,让动画的进入与离开产生了两种不同的效果,两个不同的方向。

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

torigin

CodePen Demo -- transform-origin妙用

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

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

拓展延伸

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

othertraorigin

CodePen Demo -- transform:scale 配合 transfrom-origin 控制动画方向

值得注意的点

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

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

补充

补充修改于 2018/4/23

一开始看到这个问题,陷入了一些思考误区。评论中 @w5240 指出其实直接使用定位就可以实现:

div {
position: absolute;
width: 200px;
height: 60px;
}

div:before {
    content: "";
    position: absolute;
    right: 0;
    bottom: 0;
    width: 0;
    height: 2px;
    background: deeppink;
    transition: width .5s;
}

div:hover:before {
    width: 200px;
    left:0;
    right:unset;
}

这种方法无异更加便捷。关键点还是 hover 的时候修改起始动画的点位。

最后

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

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

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

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


最后,新开通的公众号求关注,形式希望是更短的篇幅,质量更高一些的技巧类文章,包括但不局限于 CSS:

image

@chokcoco chokcoco changed the title 使用 transfrom-origin 控制动画方向 妙用 transfrom-origin, 精准控制动画方向 Apr 19, 2018
@chokcoco chokcoco changed the title 妙用 transfrom-origin, 精准控制动画方向 妙用 scale 与 transfrom-origin, 精准控制动画方向 Apr 19, 2018
@chokcoco chokcoco changed the title 妙用 scale 与 transfrom-origin, 精准控制动画方向 妙用 scale 与 transfrom-origin,精准控制动画方向 Apr 19, 2018
@w5240
Copy link

w5240 commented Apr 19, 2018

你都用定位了 这完全不需要用transform 用了反而多此一举 想想

@w5240
Copy link

w5240 commented Apr 20, 2018

@chokcoco
借用你模板
` div {
position: absolute;
width: 200px;
height: 60px;
}

div:before {
    content: "";
    position: absolute;
    right: 0;
    bottom: 0;
    width: 0;
    height: 2px;
    background: deeppink;
    transition: width .5s;
}

div:hover:before {
    width: 200px;
    left:0;
    right:unset;
}`

@chokcoco
Copy link
Owner Author

@w5240
确实是多此一举了,想复杂了 😂 😂
学习了~

@chokcoco chokcoco added the 技巧 label Aug 9, 2018
@AMrainman
Copy link

大佬竟然还有群~~都不拉我

@GaoJuqian
Copy link

Mark

@GaoJuqian
Copy link

大佬有群吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants